diff --git a/DEPS b/DEPS
index 99705f4..9abebd80 100644
--- a/DEPS
+++ b/DEPS
@@ -305,19 +305,19 @@
   # 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': 'a60d46ccb6f87592fb259207f7a7dc29797258fe',
+  'src_internal_revision': '796b60e971aab3ab6e82cb1514b01b17a06c62dc',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '3480f588eb09d25a4b1c15e643197a1eef058718',
+  'skia_revision': 'e4dc4fdb541d30b786d373b09217d769d06ed946',
   # 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': '033fd2f04cb7ff9d69cbaf0876e808186ca2dc5c',
+  'v8_revision': '99022d9158c6e40babc442b84dc0b60ed64cd378',
   # 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': 'f9685fdb79805ace8376705bafb024a1bd64c05a',
+  'angle_revision': '17977bb088acae8e114bae7f1ae92326b5fe8d1d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -329,7 +329,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': '08a77f3d88475b092c365d12576de078a54a6d91',
+  'boringssl_revision': 'ed44d6f8deb450d8178908027ff46a0252b2d405',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
@@ -373,7 +373,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '179e38564ddc7cdf0b58d5c923f2c5c3b132899a',
+  'catapult_revision': '423d5e63ff44523b3e2895d94165b80d4a003227',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -421,7 +421,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': 'd1ef389738224f8a92c5a4557a812db47cf042cc',
+  'dawn_revision': '895a2f1fc2a1e02c99b3b9522fbb4474b0c8da93',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -529,7 +529,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'compiler_rt_revision': '5436a04e9d9f47771ae83ac5942e1d0e690baf76',
+  'compiler_rt_revision': '75e783208e3c6a8c6236cc9f45d11d10f601c14f',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling clusterfuzz-data
   # and whatever else without interference from each other.
@@ -1201,7 +1201,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': 'GqmrYkmJMgA4l2sZT4qSIi1g6Tp7B-QvZLrcOlMEUe8C',
+              'version': 'Ja235hBXF0gUw-zfldml6WY02SgCPeQ34fbrQ67VIrsC',
           },
       ],
       'condition': 'checkout_android',
@@ -1223,7 +1223,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/orderfiles/arm64',
-              'version': '2f46Njln16sr_t17cz1_oEgJAbTaqHEI45x1V5Kb9_gC',
+              'version': 'oyb8wPBAwpY2mlqf65dx00Eqbi8o-WKKm1bn0QBTx9UC',
           },
       ],
       'condition': 'checkout_android',
@@ -1231,7 +1231,7 @@
   },
 
   'src/chrome/browser/resources/preinstalled_web_apps/internal': {
-    'url': Var('chrome_git') + '/chrome/components/default_apps.git' + '@' + '656ac90405cdbb7d7ab05c54a1628c6d7418832e',
+    'url': Var('chrome_git') + '/chrome/components/default_apps.git' + '@' + '73cc53e1db0fddd9fb797c40c6085579b27e7bf3',
     'condition': 'checkout_src_internal',
   },
 
@@ -1395,7 +1395,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_linux64',
-          'version': 'version:2@1521004',
+          'version': 'version:2@1522001',
         },
       ],
   },
@@ -1406,7 +1406,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_mac_amd64',
-          'version': 'version:2@1521006',
+          'version': 'version:2@1522001',
         },
       ],
   },
@@ -1417,7 +1417,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_mac_arm64',
-          'version': 'version:2@1521003',
+          'version': 'version:2@1522002',
         },
       ],
   },
@@ -1428,7 +1428,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_win_arm64',
-          'version': 'version:2@1521006',
+          'version': 'version:2@1522002',
         },
       ],
   },
@@ -1439,7 +1439,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_win_x86',
-          'version': 'version:2@1521014',
+          'version': 'version:2@1522001',
         },
       ],
   },
@@ -1450,7 +1450,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/updater/chromium_win_x86_64',
-          'version': 'version:2@1521004',
+          'version': 'version:2@1522003',
         },
       ],
   },
@@ -1528,7 +1528,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_linux64',
-          'version': 'VuY7G-r5ROPn1RhaX-CO0-h0tv3tf8OoFdXn4UWvQmAC',
+          'version': 'EN1Ts3o9uW-pnurxVE-DhJOd0UTRmNVI-EzKSQGbMwIC',
         },
       ],
   },
@@ -1539,7 +1539,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_mac_amd64',
-          'version': 'X3YlXY7g01u10ZlwzhHD5DkS8y__F7FqPuMHNhEokwkC',
+          'version': 'IzWyA5LaAxmFfpKgsiU1tdk8W263wTOZyr1jgYd_8NQC',
         },
       ],
   },
@@ -1550,7 +1550,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_mac_arm64',
-          'version': '9TRuQAdh6f-LzeVpjGzo0V_-DI03ThMrX_ZwBxS69boC',
+          'version': 'LRUUeVy1xpQNgpOvSgIHyarpgDydm5h0KJeH8c6HVAkC',
         },
       ],
   },
@@ -1561,7 +1561,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_win_x86',
-          'version': 'wvssxH76sPWNlIHFyrVUwfBiuHJtkAxe388mehyw-LUC',
+          'version': 'bfUQts1yi4CTddqaVCCva6R5rg0gRXkQcI0hV62R6vUC',
         },
       ],
   },
@@ -1572,7 +1572,7 @@
       'packages': [
         {
           'package': 'chromium/third_party/enterprise_companion/chromium_win_x86_64',
-          'version': 'LLRKSK0DCJFxGt0AOSmULvF76jMXd6DRzGB9RYso-RUC',
+          'version': 'x5fCUnkpRA6UoJKtg1V0oCM2dxLIGmJwjLL9eg9kVPQC',
         },
       ],
   },
@@ -1608,7 +1608,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/variations/cipd',
-        'version': 'OzNQYR2vrh1kpdTAezDqPscQVyG_8OXtcHwmh3ej024C',
+        'version': 'WD_CViMxB7xbucef237Tu2k5m57qF9uogU9WYarMUkoC',
       },
     ],
     'dep_type': 'cipd',
@@ -1619,7 +1619,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'e77b8efbb4d973044f6b8d448e2c578c0900db51',
+    'e1b431c9a8ec43eb47ae9e1bca1e1bfe86ee5445',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1719,7 +1719,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'fyinP9RshUI8vASuLvf1tuBf8jI4KnxUWd6QzLb1b5YC',
+          'version': 'DeEJdhsAl-OeZqdi5R97nLaquqMpvsCmeySRp4nK1hIC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -2055,7 +2055,7 @@
     Var('chromium_git') + '/chromium/web-tests.git' + '@' + Var('crossbench_web_tests_revision'),
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8fc14e1deafc4356319f2534de813899a3e01094',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '8c6304befd2205384c73e73d214848e57d9a0239',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -2605,7 +2605,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'ff11fbe7c825083afe471945766e615bc675800b',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'd7ea394300667faed7b239e087a51447586a3132',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2796,7 +2796,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'llWUebGsQPrzc7z3fwJF78NcrdGs1wrUhy0Y-0Wrb-4C',
+              'version': '2aBDG942g42qUBPPInGETRHusdxru1U3anwJI_QX5wIC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2924,7 +2924,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@cd34cfe6a579d03c0675b32844599294773634aa',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@90603b2036a87d17dde4d38f5fa16fc770961e94',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@f6652dcf751920b1fbc132619b0e84ef3d6e77c4',
   'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3',
   'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@a5164829e8f0255392c481696b63763a5e80be3c',
@@ -2933,7 +2933,7 @@
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@385716f0a63fe2c26e54a5140c9877a80da66592',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@faf69f66f2d9ba782fe37cabd19b9742f9f62eb3',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@a1e45945b3a84140956dc4672684090cf8e636a4',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@07a7e8afd318ba34ac2a999002e6602d88205c41',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@1acbea52c1e445b9398ecc228cb3bb115d97aac5',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50',
@@ -2976,7 +2976,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '85cbfaf6b96394215415527d67546d4bd872208a',
+    Var('webrtc_git') + '/src.git' + '@' + '661a2e642d3bec939e203650fb0b86e1af815c63',
 
   # 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.
@@ -3757,7 +3757,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'deec601008dc93b675f5a8d94df26732d38a3d59',
+        'f34aa19784ed9d36ae10f877a4347e2e23aab6cb',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java
index 0790e03..a2bbe16 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/services/JsSandboxServiceTest.java
@@ -983,6 +983,7 @@
 
     @Test
     @LargeTest
+    @DisabledTest(message = "crbug.com/450361757")
     public void testArrayBufferSizeEnforced() throws Throwable {
         final long maxHeapSize = REASONABLE_HEAP_SIZE;
         // V8 cannot sparsely allocate array buffers, so no fill required.
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index bcf6c95b..f60ca4d 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -2954,11 +2954,11 @@
       </message>
 
       <!-- Status tray charging strings. -->
-      <message name="IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_TITLE" desc="The title of a notification indicating that an incompatible charger has been connected, and no charging will occur." translateable="false">
-        Incompatible charger
+      <message name="IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_TITLE" desc="The title of a notification indicating that an incompatible charger has been connected, and no charging will occur.">
+        Can't charge device
       </message>
-      <message name="IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_MESSAGE" desc="The message body of a notification indicating that an incompatible charger has been connected, and that the user needs to connect a more powerful one." translateable="false">
-        Connect an adapter with more watts (W) to charge your device.
+      <message name="IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_MESSAGE" desc="The message body of a notification indicating that an incompatible charger has been connected, and that the user needs to connect a more powerful one.">
+        Try a charger with more watts (W) or use your original charger.
       </message>
       <message name="IDS_ASH_STATUS_TRAY_LOW_POWER_CHARGER_TITLE" desc="The title of a notification indicating that a low-current USB charger has been connected.">
         Low-power charger connected
@@ -3117,8 +3117,8 @@
       <message name="IDS_ASH_STATUS_TRAY_BATTERY_CHARGING_UNRELIABLE_ACCESSIBLE" desc="The message used by accessibility to indicate that battery charging is unreliable.">
         Plugged in to a low-power charger. Battery charging may not be reliable.
       </message>
-      <message name="IDS_ASH_STATUS_TRAY_BATTERY_INCOMPATIBLE_CHARGER_ACCESSIBLE" desc="The message used by accessibility to announce that an incompatible charger is connected." translateable="false">
-        Plugged in to an incompatible charger. Connect the original charger (or a similar wattage charger) to charge your device.
+      <message name="IDS_ASH_STATUS_TRAY_BATTERY_INCOMPATIBLE_CHARGER_ACCESSIBLE" desc="The message used by accessibility to announce that an incompatible charger is connected.">
+        Device plugged in, but not charging. Try a charger with more watts (W) or use your original charger.
       </message>
       <message name="IDS_ASH_STATUS_TRAY_BATTERY_STATUS_SEPARATOR" desc="The separator symbol between battery percentage string and battery remaining time string">
         ''' - '''
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BATTERY_INCOMPATIBLE_CHARGER_ACCESSIBLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BATTERY_INCOMPATIBLE_CHARGER_ACCESSIBLE.png.sha1
new file mode 100644
index 0000000..91f9b48b
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_BATTERY_INCOMPATIBLE_CHARGER_ACCESSIBLE.png.sha1
@@ -0,0 +1 @@
+d9dc5f401a9d66176191a9c8adb0c3671b42a806
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_MESSAGE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_MESSAGE.png.sha1
new file mode 100644
index 0000000..91f9b48b
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_MESSAGE.png.sha1
@@ -0,0 +1 @@
+d9dc5f401a9d66176191a9c8adb0c3671b42a806
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_TITLE.png.sha1 b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_TITLE.png.sha1
new file mode 100644
index 0000000..91f9b48b
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_STATUS_TRAY_INCOMPATIBLE_CHARGER_TITLE.png.sha1
@@ -0,0 +1 @@
+d9dc5f401a9d66176191a9c8adb0c3671b42a806
\ No newline at end of file
diff --git a/ash/system/brightness/unified_brightness_view_unittest.cc b/ash/system/brightness/unified_brightness_view_unittest.cc
index 7f7ac031..4da89275 100644
--- a/ash/system/brightness/unified_brightness_view_unittest.cc
+++ b/ash/system/brightness/unified_brightness_view_unittest.cc
@@ -14,6 +14,7 @@
 #include "ash/wm/window_util.h"
 #include "base/memory/raw_ptr.h"
 #include "ui/base/l10n/l10n_util.h"
+#include "ui/display/test/display_manager_test_api.h"
 #include "ui/gfx/vector_icon_types.h"
 #include "ui/views/accessibility/view_accessibility.h"
 #include "ui/views/controls/image_view.h"
@@ -114,6 +115,9 @@
 // letting them get through to the slider. Effectively the `slider_button` is
 // part of the slider in the brightness view.
 TEST_F(UnifiedBrightnessViewTest, SliderButtonClickThrough) {
+  display::test::DisplayManagerTestApi(display_manager())
+      .SetFirstDisplayAsInternalDisplay();
+  controller()->UpdateBrightnessSlider();
   slider()->SetValue(1.0);
   EXPECT_FLOAT_EQ(unified_brightness_view()->slider()->GetValue(), 1.0);
 
diff --git a/ash/system/unified/unified_system_tray_controller.cc b/ash/system/unified/unified_system_tray_controller.cc
index 57a221d6..e2e1aed9 100644
--- a/ash/system/unified/unified_system_tray_controller.cc
+++ b/ash/system/unified/unified_system_tray_controller.cc
@@ -94,9 +94,13 @@
   pagination_controller_ = std::make_unique<PaginationController>(
       model_->pagination_model(), PaginationController::SCROLL_AXIS_HORIZONTAL,
       base::BindRepeating(&RecordPageSwitcherSourceByEventType));
+
+  display::Screen::Get()->AddObserver(this);
 }
 
-UnifiedSystemTrayController::~UnifiedSystemTrayController() = default;
+UnifiedSystemTrayController::~UnifiedSystemTrayController() {
+  display::Screen::Get()->RemoveObserver(this);
+}
 
 void UnifiedSystemTrayController::AddObserver(Observer* observer) {
   if (observer) {
@@ -138,6 +142,7 @@
                       base::Unretained(this))));
   unified_brightness_view_ =
       qs_view->AddSliderView(brightness_slider_controller_->CreateView());
+  UpdateBrightnessSlider();
 
   qs_view->SetMaxHeight(max_height);
 
@@ -494,4 +499,40 @@
   }
 }
 
+void UnifiedSystemTrayController::UpdateBrightnessSlider() const {
+  if (!unified_brightness_view_) {
+    return;
+  }
+  auto* slider =
+      views::AsViewClass<UnifiedBrightnessView>(unified_brightness_view_)
+          ->slider();
+  for (const display::Display& display :
+       display::Screen::Get()->GetAllDisplays()) {
+    if (display.IsInternal()) {
+      slider->SetEnabled(true);
+      return;
+    }
+  }
+  slider->SetEnabled(false);
+}
+
+bool UnifiedSystemTrayController::GetBrightnessSliderEnabledForTesting() const {
+  if (!unified_brightness_view_) {
+    return false;
+  }
+  return views::AsViewClass<UnifiedBrightnessView>(unified_brightness_view_)
+      ->slider()
+      ->GetEnabled();
+}
+
+void UnifiedSystemTrayController::OnDisplayAdded(
+    const display::Display& new_display) {
+  UpdateBrightnessSlider();
+}
+
+void UnifiedSystemTrayController::OnDisplaysRemoved(
+    const display::Displays& removed_displays) {
+  UpdateBrightnessSlider();
+}
+
 }  // namespace ash
diff --git a/ash/system/unified/unified_system_tray_controller.h b/ash/system/unified/unified_system_tray_controller.h
index 5202649..b4d5ec8 100644
--- a/ash/system/unified/unified_system_tray_controller.h
+++ b/ash/system/unified/unified_system_tray_controller.h
@@ -5,15 +5,21 @@
 #ifndef ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_CONTROLLER_H_
 #define ASH_SYSTEM_UNIFIED_UNIFIED_SYSTEM_TRAY_CONTROLLER_H_
 
+#include <memory>
+
 #include "ash/ash_export.h"
 #include "ash/system/audio/unified_volume_slider_controller.h"
 #include "ash/system/media/quick_settings_media_view_controller.h"
 #include "ash/system/time/calendar_metrics.h"
 #include "ash/system/unified/quick_settings_view.h"
 #include "ash/system/unified/unified_system_tray_model.h"
+#include "base/memory/raw_ptr.h"
 #include "base/memory/safety_checks.h"
 #include "base/memory/scoped_refptr.h"
 #include "components/global_media_controls/public/constants.h"
+#include "ui/display/display_observer.h"
+#include "ui/views/controls/slider.h"
+#include "ui/views/view.h"
 
 namespace ash {
 
@@ -27,7 +33,8 @@
 
 // Controller class of `QuickSettingsView`. Handles events of the view.
 class ASH_EXPORT UnifiedSystemTrayController
-    : public UnifiedVolumeSliderController::Delegate {
+    : public UnifiedVolumeSliderController::Delegate,
+      public display::DisplayObserver {
   // Do not remove this macro!
   // The macro is maintained by the memory safety team.
   ADVANCED_MEMORY_SAFETY_CHECKS();
@@ -127,6 +134,10 @@
   // UnifiedVolumeSliderController::Delegate:
   void OnAudioSettingsButtonClicked() override;
 
+  // display::DisplayObserver:
+  void OnDisplayAdded(const display::Display& new_display) override;
+  void OnDisplaysRemoved(const display::Displays& removed_displays) override;
+
   // Sets whether the quick settings view should show the media view.
   void SetShowMediaView(bool show_media_view);
 
@@ -170,6 +181,10 @@
 
   void ShutDownDetailedViewController();
 
+  // Enable or disable the brightness slider view.
+  void UpdateBrightnessSlider() const;
+  bool GetBrightnessSliderEnabledForTesting() const;
+
  private:
   friend class AccessibilityFeaturePodControllerTest;
   friend class SystemTrayTestApi;
diff --git a/ash/system/unified/unified_system_tray_unittest.cc b/ash/system/unified/unified_system_tray_unittest.cc
index 8c7a296..ee66929 100644
--- a/ash/system/unified/unified_system_tray_unittest.cc
+++ b/ash/system/unified/unified_system_tray_unittest.cc
@@ -64,6 +64,7 @@
 #include "ui/chromeos/styles/cros_tokens_color_mappings.h"
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
+#include "ui/display/test/display_manager_test_api.h"
 #include "ui/events/event_constants.h"
 #include "ui/message_center/message_center.h"
 #include "ui/views/accessibility/view_accessibility.h"
@@ -864,6 +865,40 @@
   tray->CloseBubble();
 }
 
+TEST_P(UnifiedSystemTrayTest, BrightnessSliderDisabledInDockedMode) {
+  const int64_t internal_display_id =
+      display::test::DisplayManagerTestApi(display_manager())
+          .SetFirstDisplayAsInternalDisplay();
+  const auto internal_info =
+      display_manager()->GetDisplayInfo(internal_display_id);
+  constexpr int64_t external_id = 210000010;
+
+  const auto external_info =
+      display::ManagedDisplayInfo::CreateFromSpecWithID("400x300", external_id);
+
+  std::vector<display::ManagedDisplayInfo> display_info_list;
+  display_info_list.push_back(internal_info);
+  display_info_list.push_back(external_info);
+  display_manager()->OnNativeDisplaysChanged(display_info_list);
+  EXPECT_EQ(2U, display_manager()->GetNumDisplays());
+
+  auto* tray = GetPrimaryUnifiedSystemTray();
+  tray->ShowBubble();
+
+  EXPECT_TRUE(tray->bubble()
+                  ->unified_system_tray_controller()
+                  ->GetBrightnessSliderEnabledForTesting());
+
+  display_info_list.clear();
+  display_info_list.push_back(external_info);
+  display_manager()->OnNativeDisplaysChanged(display_info_list);
+  EXPECT_EQ(1U, display_manager()->GetNumDisplays());
+
+  EXPECT_FALSE(tray->bubble()
+                   ->unified_system_tray_controller()
+                   ->GetBrightnessSliderEnabledForTesting());
+}
+
 // Tests that there's no bubble in the kiosk mode.
 TEST_P(UnifiedSystemTrayTest, NoBubbleAndNoDetailedViewInKioskMode) {
   SimulateKioskMode(user_manager::UserType::kKioskChromeApp);
diff --git a/ash/webui/boca_ui/boca_app_page_handler.cc b/ash/webui/boca_ui/boca_app_page_handler.cc
index 7777de8..d375b12 100644
--- a/ash/webui/boca_ui/boca_app_page_handler.cc
+++ b/ash/webui/boca_ui/boca_app_page_handler.cc
@@ -650,6 +650,7 @@
     std::move(callback).Run(std::nullopt);
     return;
   }
+  GetSessionManager()->EndSpotlightSession(base::DoNothing());
   EndViewScreenSessionInternal(id, std::move(callback));
 }
 
@@ -774,7 +775,11 @@
       &BocaAppHandler::OnEndViewScreenResponseForPresentStudentScreen,
       weak_ptr_factory_.GetWeakPtr(), session->session_id(), std::move(student),
       receiver_id, std::move(callback));
-  EndViewScreenSessionInternal(student_id, std::move(end_view_screen_cb));
+  auto end_spotlight_cb =
+      base::BindOnce(&BocaAppHandler::EndViewScreenSessionInternal,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(student_id),
+                     std::move(end_view_screen_cb));
+  GetSessionManager()->EndSpotlightSession(std::move(end_spotlight_cb));
 }
 
 void BocaAppHandler::StopPresentingStudentScreen(
@@ -1339,10 +1344,6 @@
     EndViewScreenSessionCallback callback) {
   CHECK(spotlight_service_);
 
-  if (ash::features::IsBocaSpotlightRobotRequesterEnabled()) {
-    GetSessionManager()->EndSpotlightSession();
-  }
-
   spotlight_service_->UpdateViewScreenState(
       id, ::boca::ViewScreenConfig::INACTIVE, base_url_,
       base::BindOnce(
@@ -1402,17 +1403,8 @@
     std::move(callback).Run(false);
     return;
   }
-  // Delay presentation to increase the likelihood the host receives the
-  // inactive connection notification and can accept the new one.
-  // TODO(crbug.com/445259545): The race condition is still there even with the
-  // delay. Update the host side to allow new connection even if the previous
-  // one is ongoing and then remove this delay.
-  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&BocaAppHandler::PresentStudentScreenInternal,
-                     weak_ptr_factory_.GetWeakPtr(), session_id,
-                     std::move(student), receiver_id, std::move(callback)),
-      base::Seconds(5));
+  PresentStudentScreenInternal(session_id, std::move(student), receiver_id,
+                               std::move(callback));
 }
 
 TeacherScreenPresenter* BocaAppHandler::teacher_screen_presenter() {
diff --git a/ash/webui/boca_ui/boca_app_page_handler_unittest.cc b/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
index 4bddb6e6..a95575e 100644
--- a/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
+++ b/ash/webui/boca_ui/boca_app_page_handler_unittest.cc
@@ -315,6 +315,7 @@
               GetStudentActiveDeviceId,
               (std::string_view),
               (override));
+  MOCK_METHOD(void, EndSpotlightSession, (base::OnceClosure), (override));
   ~MockSessionManager() override = default;
 };
 
@@ -2626,6 +2627,7 @@
 
 TEST_F(BocaAppPageHandlerProducerTest, EndViewScreenSessionSucceeded) {
   const std::string student_id = "123";
+  EXPECT_CALL(*session_manager(), EndSpotlightSession).Times(1);
   EXPECT_CALL(
       *spotlight_service(),
       UpdateViewScreenState(student_id, ::boca::ViewScreenConfig::INACTIVE,
@@ -2649,6 +2651,7 @@
   ON_CALL(*session_manager(), GetStudentScreenPresenter)
       .WillByDefault(Return(student_screen_presenter.get()));
   ON_CALL(*student_screen_presenter, IsPresenting).WillByDefault(Return(true));
+  EXPECT_CALL(*session_manager(), EndSpotlightSession).Times(0);
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState).Times(0);
 
   boca_app_handler()->EndViewScreenSession("student-id", future.GetCallback());
@@ -2659,6 +2662,7 @@
   base::HistogramTester histogram_tester;
   const std::string student_id = "123";
 
+  EXPECT_CALL(*session_manager(), EndSpotlightSession).Times(1);
   EXPECT_CALL(
       *spotlight_service(),
       UpdateViewScreenState(student_id, ::boca::ViewScreenConfig::INACTIVE,
@@ -3103,6 +3107,8 @@
   EXPECT_CALL(*session_manager(), GetCurrentSession())
       .WillRepeatedly(Return(&session));
   boca_app_handler()->OnSessionStarted("session_id", ::boca::UserIdentity());
+  EXPECT_CALL(*session_manager(), EndSpotlightSession)
+      .WillOnce([](base::OnceClosure callback) { std::move(callback).Run(); });
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState)
       .WillOnce([](std::string, ::boca::ViewScreenConfig::ViewScreenState,
                    std::string, ViewScreenRequestCallback callback) {
@@ -3123,7 +3129,6 @@
   boca_app_handler()->PresentStudentScreen(student_identity_mojom->Clone(),
                                            kReceiverId,
                                            success_future.GetCallback());
-  task_environment()->FastForwardBy(base::Seconds(5));
   EXPECT_TRUE(success_future.Get());
   EXPECT_EQ(student_identity.gaia_id(), student_identity_mojom->id);
   EXPECT_EQ(student_identity.full_name(), student_identity_mojom->name);
@@ -3145,6 +3150,8 @@
   EXPECT_CALL(*session_manager(), GetCurrentSession())
       .WillRepeatedly(Return(&session));
   boca_app_handler()->OnSessionStarted("session_id", ::boca::UserIdentity());
+  EXPECT_CALL(*session_manager(), EndSpotlightSession)
+      .WillOnce([](base::OnceClosure callback) { std::move(callback).Run(); });
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState)
       .WillOnce([](std::string, ::boca::ViewScreenConfig::ViewScreenState,
                    std::string, ViewScreenRequestCallback callback) {
@@ -3163,7 +3170,6 @@
       mojom::Identity::New(kActiveStudentId, "student name",
                            "student@email.com", std::nullopt),
       kReceiverId, success_future.GetCallback());
-  task_environment()->FastForwardBy(base::Seconds(5));
   EXPECT_FALSE(success_future.Get());
 }
 
@@ -3178,6 +3184,8 @@
   EXPECT_CALL(*session_manager(), GetCurrentSession())
       .WillRepeatedly(Return(&session));
   boca_app_handler()->OnSessionStarted("session_id", ::boca::UserIdentity());
+  EXPECT_CALL(*session_manager(), EndSpotlightSession)
+      .WillOnce([](base::OnceClosure callback) { std::move(callback).Run(); });
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState)
       .WillOnce([](std::string, ::boca::ViewScreenConfig::ViewScreenState,
                    std::string, ViewScreenRequestCallback callback) {
@@ -3198,15 +3206,21 @@
       std::make_unique<MockStudentScreenPresenter>();
   ON_CALL(*session_manager(), GetStudentScreenPresenter)
       .WillByDefault(Return(student_screen_presenter.get()));
+  ON_CALL(*session_manager(), GetStudentActiveDeviceId)
+      .WillByDefault(Return(kStudentDeviceId));
   base::test::TestFuture<bool> success_future;
+  ViewScreenRequestCallback view_screen_update_cb;
   ::boca::Session session = GetCommonActiveSessionProto();
   EXPECT_CALL(*session_manager(), GetCurrentSession())
       .WillRepeatedly(Return(&session));
   boca_app_handler()->OnSessionStarted("session_id", ::boca::UserIdentity());
+  EXPECT_CALL(*session_manager(), EndSpotlightSession)
+      .WillOnce([](base::OnceClosure callback) { std::move(callback).Run(); });
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState)
-      .WillOnce([](std::string, ::boca::ViewScreenConfig::ViewScreenState,
-                   std::string, ViewScreenRequestCallback callback) {
-        std::move(callback).Run(true);
+      .WillOnce([&view_screen_update_cb](
+                    std::string, ::boca::ViewScreenConfig::ViewScreenState,
+                    std::string, ViewScreenRequestCallback callback) {
+        view_screen_update_cb = std::move(callback);
       });
   EXPECT_CALL(*student_screen_presenter, Start).Times(0);
   boca_app_handler()->PresentStudentScreen(
@@ -3214,7 +3228,7 @@
                            "student@email.com", std::nullopt),
       kReceiverId, success_future.GetCallback());
   session.set_session_state(::boca::Session::PAST);
-  task_environment()->FastForwardBy(base::Seconds(5));
+  std::move(view_screen_update_cb).Run(true);
   EXPECT_FALSE(success_future.Get());
 }
 
@@ -3228,6 +3242,8 @@
   EXPECT_CALL(*session_manager(), GetCurrentSession())
       .WillRepeatedly(Return(&session));
   boca_app_handler()->OnSessionStarted("session_id", ::boca::UserIdentity());
+  EXPECT_CALL(*session_manager(), EndSpotlightSession)
+      .WillOnce([](base::OnceClosure callback) { std::move(callback).Run(); });
   EXPECT_CALL(*spotlight_service(), UpdateViewScreenState)
       .WillOnce([](std::string, ::boca::ViewScreenConfig::ViewScreenState,
                    std::string, ViewScreenRequestCallback callback) {
@@ -3240,7 +3256,6 @@
       mojom::Identity::New(kActiveStudentId, "student name",
                            "student@email.com", std::nullopt),
       kReceiverId, success_future.GetCallback());
-  task_environment()->FastForwardBy(base::Seconds(5));
   EXPECT_FALSE(success_future.Get());
 }
 
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h
index 7805d87..46c8e6d 100644
--- a/base/memory/memory_pressure_listener.h
+++ b/base/memory/memory_pressure_listener.h
@@ -51,7 +51,8 @@
   kResourcePool = 21,
   kOnDeviceTailModelService = 22,
   kGpuChannelManager = 23,
-  kSharedDictionaryManagerOnDisk = 24,
+  // Deprecated.
+  // kSharedDictionaryManagerOnDisk = 24,
   kSharedDictionaryManager = 25,
   kHistoryBackend = 26,
   kMediaUrlIndex = 27,
diff --git a/buildtools/reclient_cfgs/fetch_reclient_cfgs.py b/buildtools/reclient_cfgs/fetch_reclient_cfgs.py
deleted file mode 100755
index 4f136f5..0000000
--- a/buildtools/reclient_cfgs/fetch_reclient_cfgs.py
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2021 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""This script is used to fetch reclient cfgs.
-
-This is renamed to configure_reclient_cfgs.py, delete this file if there are no
-reference to this file.
-"""
-
-import sys
-
-import configure_reclient_cfgs
-
-if __name__ == '__main__':
-    sys.exit(configure_reclient_cfgs.main())
diff --git a/buildtools/third_party/libc++/BUILD.gn b/buildtools/third_party/libc++/BUILD.gn
index c0c6cfb9..f1ac049d 100644
--- a/buildtools/third_party/libc++/BUILD.gn
+++ b/buildtools/third_party/libc++/BUILD.gn
@@ -126,7 +126,7 @@
   }
 }
 
-if (use_clang_modules && use_xcode_symlinks) {
+if (use_clang_modules && use_xcode_symlinks && !use_autogenerated_modules) {
   # sysroot_modulemaps can be inside the build directory. This no-op action
   # declares the modulemap files as outputs to satisfy GN's dependency
   # tracking when other targets use them as inputs.
diff --git a/buildtools/third_party/libc++/modules.gni b/buildtools/third_party/libc++/modules.gni
index a4d2635..adbdc7e 100644
--- a/buildtools/third_party/libc++/modules.gni
+++ b/buildtools/third_party/libc++/modules.gni
@@ -35,21 +35,6 @@
         public_deps = []
       }
 
-      if (use_xcode_symlinks) {
-        # The `copy_sysroot_modulemaps` action depends on SDK paths that differ
-        # between macOS and iOS, so it must be built with the correct toolchain
-        # for the target OS.
-        toolchain = "//build/toolchain/mac:clang_$target_cpu"
-        if (is_ios || target_environment == "catalyst") {
-          toolchain = "//build/toolchain/ios:ios_clang_$target_cpu"
-        } else if (target_os == "ios" && is_mac) {
-          toolchain = "//build/toolchain/mac:clang_$host_cpu"
-        }
-        public_deps += [
-          "//buildtools/third_party/libc++:copy_sysroot_modulemaps($toolchain)",
-        ]
-      }
-
       # Implicit module maps won't work on apple because we're currently
       # missing some dependencies.
       if (use_autogenerated_modules) {
@@ -73,6 +58,19 @@
         # intentionally disabled because it's broken (eg. Darwin.modulemap).
         cflags += [ clang_arg_prefix + "-fno-implicit-module-maps" ]
       } else {
+        if (use_xcode_symlinks) {
+          # The `copy_sysroot_modulemaps` action depends on SDK paths that differ
+          # between macOS and iOS, so it must be built with the correct toolchain
+          # for the target OS.
+          toolchain = "//build/toolchain/mac:clang_$target_cpu"
+          if (is_ios || target_environment == "catalyst") {
+            toolchain = "//build/toolchain/ios:ios_clang_$target_cpu"
+          } else if (target_os == "ios" && is_mac) {
+            toolchain = "//build/toolchain/mac:clang_$host_cpu"
+          }
+          public_deps += [ "//buildtools/third_party/libc++:copy_sysroot_modulemaps($toolchain)" ]
+        }
+
         if (!defined(public_configs)) {
           public_configs = []
         }
diff --git a/cc/DEPS b/cc/DEPS
index 69aab669..17c1fe4 100644
--- a/cc/DEPS
+++ b/cc/DEPS
@@ -74,6 +74,9 @@
     "+gpu/command_buffer/common/command_buffer_id.h",
     "+gpu/command_buffer/common/constants.h",
   ],
+  "gpu_image_decode_cache_unittest\.cc" : [
+      "+gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h",
+  ],
   "oop_pixeltest\.cc" : [
     "+gpu/command_buffer/client",
     "+gpu/command_buffer/common",
diff --git a/cc/paint/paint_op_raster_fuzzer.cc b/cc/paint/paint_op_raster_fuzzer.cc
index def3b5c2..8eb0891 100644
--- a/cc/paint/paint_op_raster_fuzzer.cc
+++ b/cc/paint/paint_op_raster_fuzzer.cc
@@ -85,7 +85,6 @@
 
   SkImageInfo image_info = SkImageInfo::MakeN32(
       kRasterDimension, kRasterDimension, kOpaque_SkAlphaType);
-  context_provider->BindToCurrentSequence();
   sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(
       context_provider->GrContext(), skgpu::Budgeted::kYes, image_info);
   SkCanvas* canvas = surface->getCanvas();
diff --git a/cc/paint/transfer_cache_fuzzer.cc b/cc/paint/transfer_cache_fuzzer.cc
index 8f34017..07a58fe 100644
--- a/cc/paint/transfer_cache_fuzzer.cc
+++ b/cc/paint/transfer_cache_fuzzer.cc
@@ -64,7 +64,7 @@
   base::span<const uint8_t> span(unaligned_data, size - unaligned_gap);
 #endif
 
-  if (!entry->Deserialize(context_provider->GrContext(),
+  if (!entry->Deserialize(/*gr_context=*/nullptr,
                           /*graphite_recorder=*/nullptr, span)) {
     return 0;
   }
diff --git a/cc/raster/raster_buffer_provider_perftest.cc b/cc/raster/raster_buffer_provider_perftest.cc
index 89314f6c..a017a18 100644
--- a/cc/raster/raster_buffer_provider_perftest.cc
+++ b/cc/raster/raster_buffer_provider_perftest.cc
@@ -38,7 +38,6 @@
 #include "testing/gtest/include/gtest/gtest.h"
 #include "testing/perf/perf_result_reporter.h"
 #include "third_party/khronos/GLES2/gl2.h"
-#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 
 namespace cc {
 namespace {
@@ -113,9 +112,6 @@
     return raster_context_.get();
   }
   gpu::ContextSupport* ContextSupport() override { return &support_; }
-  class GrDirectContext* GrContext() override {
-    return nullptr;
-  }
   gpu::SharedImageInterface* SharedImageInterface() override {
     if (!test_context_provider_) {
       test_context_provider_ = viz::TestContextProvider::CreateRaster();
diff --git a/cc/tiles/gpu_image_decode_cache_unittest.cc b/cc/tiles/gpu_image_decode_cache_unittest.cc
index 22d5e616..7528359 100644
--- a/cc/tiles/gpu_image_decode_cache_unittest.cc
+++ b/cc/tiles/gpu_image_decode_cache_unittest.cc
@@ -39,6 +39,7 @@
 #include "gpu/command_buffer/common/command_buffer_id.h"
 #include "gpu/command_buffer/common/constants.h"
 #include "gpu/config/gpu_finch_features.h"
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -57,6 +58,8 @@
 #include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h"
 #include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 #include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h"
+#include "third_party/skia/include/gpu/ganesh/gl/GrGLDirectContext.h"
+#include "third_party/skia/include/gpu/ganesh/gl/GrGLInterface.h"
 
 using testing::_;
 using testing::StrictMock;
@@ -320,10 +323,16 @@
     context_provider_ = GPUImageDecodeTestMockContextProvider::Create(
         &transfer_cache_helper_, advertise_accelerated_decoding_);
     context_provider_->BindToCurrentSequence();
+    sk_sp<const GrGLInterface> gr_interface =
+        skia_bindings::CreateGLES2InterfaceBindings(
+            context_provider_->UnboundTestContextGL(),
+            context_provider_->ContextSupport());
+    gr_context_ = GrDirectContexts::MakeGL(std::move(gr_interface));
+    ASSERT_TRUE(!!gr_context_);
     {
       viz::RasterContextProvider::ScopedRasterContextLock context_lock(
           context_provider_.get());
-      transfer_cache_helper_.SetGrContext(context_provider_->GrContext());
+      transfer_cache_helper_.SetGrContext(gr_context_.get());
       max_texture_size_ =
           context_provider_->ContextCapabilities().max_texture_size;
     }
@@ -609,6 +618,7 @@
   // on |transfer_cache_helper_|.
   TransferCacheTestHelper transfer_cache_helper_;
   scoped_refptr<GPUImageDecodeTestMockContextProvider> context_provider_;
+  sk_sp<GrDirectContext> gr_context_;
 
   // Only used when |do_yuv_decode_| is true.
   SkYUVAPixmapInfo::DataType yuv_data_type_ =
diff --git a/chrome/VERSION b/chrome/VERSION
index 720c91c5..8c049f7 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=143
 MINOR=0
-BUILD=7461
+BUILD=7462
 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsIphMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsIphMessageCardViewModel.java
index 720dc7f..48d2708 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsIphMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ArchivedTabsIphMessageCardViewModel.java
@@ -4,9 +4,25 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.ACTION_BUTTON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.DISMISS_BUTTON_CONTENT_DESCRIPTION;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.ICON_PROVIDER;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.IS_ICON_VISIBLE;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.IS_INCOGNITO;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_IDENTIFIER;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_SERVICE_ACTION_PROVIDER;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MESSAGE_TYPE;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.MessageCardScope.REGULAR;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageCardViewProperties.VIEW_AS_ACTION_BUTTON;
+import static org.chromium.chrome.browser.tasks.tab_management.MessageService.DEFAULT_MESSAGE_IDENTIFIER;
+import static org.chromium.chrome.browser.tasks.tab_management.ResizableMessageCardViewProperties.ALL_KEYS;
 import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_ALPHA;
 import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.CARD_TYPE;
 import static org.chromium.chrome.browser.tasks.tab_management.TabListModel.CardProperties.ModelType.MESSAGE;
+import static org.chromium.chrome.browser.tasks.tab_management.TabSwitcherMessageManager.MessageType.ARCHIVED_TABS_IPH_MESSAGE;
 
 import android.content.Context;
 
@@ -37,34 +53,25 @@
         String dismissButtonContextDescription =
                 context.getString(R.string.accessibility_tab_suggestion_dismiss_button);
 
-        return new PropertyModel.Builder(ResizableMessageCardViewProperties.ALL_KEYS)
-                .with(MessageCardViewProperties.MESSAGE_TYPE, MessageType.ARCHIVED_TABS_IPH_MESSAGE)
+        return new PropertyModel.Builder(ALL_KEYS)
+                .with(MESSAGE_TYPE, ARCHIVED_TABS_IPH_MESSAGE)
+                .with(MESSAGE_IDENTIFIER, DEFAULT_MESSAGE_IDENTIFIER)
                 .with(
-                        MessageCardViewProperties.MESSAGE_IDENTIFIER,
-                        MessageService.DEFAULT_MESSAGE_IDENTIFIER)
-                .with(
-                        MessageCardViewProperties.ICON_PROVIDER,
+                        ICON_PROVIDER,
                         (callback) -> {
                             callback.onResult(
                                     AppCompatResources.getDrawable(
                                             context, R.drawable.archived_tab_icon));
                         })
-                .with(
-                        MessageCardViewProperties.MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER,
-                        serviceDismissActionProvider)
-                .with(MessageCardViewProperties.MESSAGE_SERVICE_ACTION_PROVIDER, actionProvider)
-                .with(
-                        MessageCardViewProperties.DISMISS_BUTTON_CONTENT_DESCRIPTION,
-                        dismissButtonContextDescription)
-                .with(MessageCardViewProperties.VIEW_AS_ACTION_BUTTON, true)
-                .with(MessageCardViewProperties.ACTION_BUTTON_VISIBLE, false)
-                .with(MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW, true)
-                .with(MessageCardViewProperties.IS_ICON_VISIBLE, true)
-                .with(MessageCardViewProperties.IS_INCOGNITO, false)
-                .with(
-                        MessageCardViewProperties
-                                .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
-                        MessageCardViewProperties.MessageCardScope.BOTH)
+                .with(MESSAGE_SERVICE_DISMISS_ACTION_PROVIDER, serviceDismissActionProvider)
+                .with(MESSAGE_SERVICE_ACTION_PROVIDER, actionProvider)
+                .with(DISMISS_BUTTON_CONTENT_DESCRIPTION, dismissButtonContextDescription)
+                .with(VIEW_AS_ACTION_BUTTON, true)
+                .with(ACTION_BUTTON_VISIBLE, false)
+                .with(SHOULD_KEEP_AFTER_REVIEW, true)
+                .with(IS_ICON_VISIBLE, true)
+                .with(IS_INCOGNITO, false)
+                .with(MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE, REGULAR)
                 .with(CARD_TYPE, MESSAGE)
                 .with(CARD_ALPHA, 1f)
                 .build();
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
index 91d471b..9c9feee3 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageCardViewModel.java
@@ -58,7 +58,7 @@
                         dismissButtonContextDescription)
                 .with(MessageCardViewProperties.SHOULD_KEEP_AFTER_REVIEW, true)
                 .with(MessageCardViewProperties.IS_ICON_VISIBLE, false)
-                .with(MessageCardViewProperties.IS_INCOGNITO, false)
+                .with(MessageCardViewProperties.IS_INCOGNITO, data.isIncognito())
                 .with(
                         MessageCardViewProperties
                                 .MESSAGE_CARD_VISIBILITY_CONTROL_IN_REGULAR_AND_INCOGNITO_MODE,
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java
index 58cbb0a..bd058d2 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageService.java
@@ -24,12 +24,15 @@
 import org.chromium.components.feature_engagement.Tracker;
 import org.chromium.ui.modelutil.PropertyModel;
 
+import java.util.function.Supplier;
+
 /** One of the concrete {@link MessageService} that only serves {@link MessageType.IPH}. */
 @NullMarked
 public class IphMessageService extends MessageService<@MessageType Integer, @UiType Integer> {
     private static boolean sSkipIphInTests = true;
 
     private final TabSwitcherIphController mIphController;
+    private final Supplier<Profile> mProfileSupplier;
     private Tracker mTracker;
 
     private final Callback<Boolean> mInitializedCallback =
@@ -44,12 +47,15 @@
     static class IphMessageData {
         private final MessageCardView.ActionProvider mAcceptActionProvider;
         private final MessageCardView.ActionProvider mDismissActionProvider;
+        private final boolean mIsIncognito;
 
         IphMessageData(
                 MessageCardView.ActionProvider acceptActionProvider,
-                MessageCardView.ActionProvider dismissActionProvider) {
+                MessageCardView.ActionProvider dismissActionProvider,
+                boolean isIncognito) {
             mAcceptActionProvider = acceptActionProvider;
             mDismissActionProvider = dismissActionProvider;
+            mIsIncognito = isIncognito;
         }
 
         /**
@@ -65,16 +71,22 @@
         MessageCardView.ActionProvider getDismissActionProvider() {
             return mDismissActionProvider;
         }
+
+        /** Returns whether the message card is to be themed for incognito */
+        boolean isIncognito() {
+            return mIsIncognito;
+        }
     }
 
-    IphMessageService(Profile profile, TabSwitcherIphController controller) {
+    IphMessageService(Supplier<Profile> profileSupplier, TabSwitcherIphController controller) {
         super(
                 MessageType.IPH,
                 UiType.IPH_MESSAGE,
                 R.layout.tab_grid_message_card_item,
                 MessageCardViewBinder::bind);
         mIphController = controller;
-        mTracker = TrackerFactory.getTrackerForProfile(profile);
+        mTracker = TrackerFactory.getTrackerForProfile(profileSupplier.get());
+        mProfileSupplier = profileSupplier;
     }
 
     @VisibleForTesting
@@ -124,7 +136,10 @@
     private PropertyModel buildModel(
             Context context,
             ServiceDismissActionProvider<@MessageType Integer> serviceActionProvider) {
+        boolean isIncognito = mProfileSupplier.get().isIncognitoBranded();
         return IphMessageCardViewModel.create(
-                context, serviceActionProvider, new IphMessageData(this::review, this::dismiss));
+                context,
+                serviceActionProvider,
+                new IphMessageData(this::review, this::dismiss, isIncognito));
     }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
index c1428580..19a833b4 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderCoordinator.java
@@ -8,12 +8,10 @@
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tasks.tab_management.MessageCardView.ServiceDismissActionProvider;
 import org.chromium.chrome.browser.tasks.tab_management.MessageService.Message;
 
 import java.util.List;
-import java.util.function.Supplier;
 
 /**
  * This is the coordinator for MessageCardProvider component. This component is used to build a
@@ -29,12 +27,8 @@
     private @Nullable MessageHostDelegate<MessageT, UiT> mMessageHostDelegate;
 
     MessageCardProviderCoordinator(
-            Context context,
-            Supplier<Profile> profileSupplier,
-            ServiceDismissActionProvider<MessageT> serviceDismissActionProvider) {
-        mMediator =
-                new MessageCardProviderMediator<>(
-                        context, profileSupplier, serviceDismissActionProvider);
+            Context context, ServiceDismissActionProvider<MessageT> serviceDismissActionProvider) {
+        mMediator = new MessageCardProviderMediator<>(context, serviceDismissActionProvider);
     }
 
     /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
index 8712a4f..2fa672e 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediator.java
@@ -10,7 +10,6 @@
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tasks.tab_management.MessageCardView.ServiceDismissActionProvider;
 import org.chromium.chrome.browser.tasks.tab_management.MessageService.Message;
 import org.chromium.chrome.browser.tasks.tab_management.MessageService.MessageModelFactory;
@@ -21,7 +20,6 @@
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.function.Supplier;
 
 /**
  * This is a {@link MessageObserver} that creates and owns different {@link PropertyModel} based on
@@ -33,16 +31,12 @@
 @NullMarked
 public class MessageCardProviderMediator<MessageT, UiT> implements MessageObserver<MessageT> {
     private final Context mContext;
-    private final Supplier<Profile> mProfileSupplier;
     private final ServiceDismissActionProvider<MessageT> mServiceDismissActionProvider;
     private final Map<MessageT, MessageService<MessageT, UiT>> mMessageServices = new HashMap<>();
 
     public MessageCardProviderMediator(
-            Context context,
-            Supplier<Profile> profileSupplier,
-            ServiceDismissActionProvider<MessageT> serviceDismissActionProvider) {
+            Context context, ServiceDismissActionProvider<MessageT> serviceDismissActionProvider) {
         mContext = context;
-        mProfileSupplier = profileSupplier;
         mServiceDismissActionProvider = serviceDismissActionProvider;
     }
 
@@ -55,13 +49,7 @@
     public @Nullable Message<MessageT> getNextMessageItemForType(MessageT messageType) {
         MessageService<MessageT, UiT> service = mMessageServices.get(messageType);
         if (service == null) return null;
-
-        Message<MessageT> message = service.getNextMessageItem();
-        if (message == null) return null;
-
-        PropertyModel model = message.model;
-        maybeSetCardIncognitoStatus(model);
-        return message;
+        return service.getNextMessageItem();
     }
 
     /**
@@ -82,7 +70,6 @@
         if (service == null) return;
 
         PropertyModel model = factory.build(mContext, this::invalidateShownMessage);
-        maybeSetCardIncognitoStatus(model);
         service.addMessage(new Message<>(type, model));
     }
 
@@ -131,12 +118,4 @@
     Map<MessageT, MessageService<MessageT, UiT>> getMessageServicesMap() {
         return mMessageServices;
     }
-
-    private void maybeSetCardIncognitoStatus(PropertyModel model) {
-        if (model.containsKey(MessageCardViewProperties.IS_INCOGNITO)) {
-            model.set(
-                    MessageCardViewProperties.IS_INCOGNITO,
-                    mProfileSupplier.get().isOffTheRecord());
-        }
-    }
 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java
index e34589d..861afabf 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMessageManager.java
@@ -231,16 +231,9 @@
         mDesktopWindowStateManager = desktopWindowStateManager;
         mLayoutStateProviderSupplier = layoutStateProviderSupplier;
 
-        Supplier<Profile> profileSupplier =
-                () -> {
-                    TabGroupModelFilter tabGroupModelFilter =
-                            mCurrentTabGroupModelFilterSupplier.get();
-                    assumeNonNull(tabGroupModelFilter);
-                    return assumeNonNull(tabGroupModelFilter.getTabModel().getProfile());
-                };
         mMessageCardProviderCoordinator =
                 new MessageCardProviderCoordinator<@MessageType Integer, @UiType Integer>(
-                        activity, profileSupplier, this::dismissHandler);
+                        activity, this::dismissHandler);
 
         mTabGridIphDialogCoordinator =
                 new TabGridIphDialogCoordinator(activity, mModalDialogManager);
@@ -345,7 +338,7 @@
         mMessageCardProviderCoordinator.subscribeMessageService(mArchivedTabsMessageService);
 
         IphMessageService iphMessageService =
-                new IphMessageService(profile, mTabGridIphDialogCoordinator);
+                new IphMessageService(this::getCurrentProfile, mTabGridIphDialogCoordinator);
         mMessageCardProviderCoordinator.subscribeMessageService(iphMessageService);
 
         if (IncognitoReauthManager.isIncognitoReauthFeatureAvailable()
@@ -598,9 +591,7 @@
         if (!shouldShowMessages()) return;
         TabListCoordinator tabListCoordinator = mTabListCoordinatorSupplier.get();
         assert tabListCoordinator != null;
-
-        assert assumeNonNull(mCurrentTabGroupModelFilterSupplier.get()).getTabModel().getProfile()
-                != null;
+        assert getCurrentProfile() != null;
 
         sAppendedMessagesForTesting = false;
         List<MessageService<@MessageType Integer, @UiType Integer>> messageServices =
@@ -714,4 +705,10 @@
             removeAllAppendedMessage();
         }
     }
+
+    private Profile getCurrentProfile() {
+        TabGroupModelFilter tabGroupModelFilter = mCurrentTabGroupModelFilterSupplier.get();
+        assumeNonNull(tabGroupModelFilter);
+        return assumeNonNull(tabGroupModelFilter.getTabModel().getProfile());
+    }
 }
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java
index d5d12523..426ba45 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderTest.java
@@ -157,7 +157,7 @@
 
                     mCoordinator =
                             new MessageCardProviderCoordinator<>(
-                                    sActivity, () -> mProfile, mServiceDismissActionProvider);
+                                    sActivity, mServiceDismissActionProvider);
                     mCoordinator.subscribeMessageService(mTestingService);
                     mCoordinator.subscribeMessageService(mPriceService);
                 });
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageServiceUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageServiceUnitTest.java
index b6b3925..4dd2052 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageServiceUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IphMessageServiceUnitTest.java
@@ -4,13 +4,13 @@
 
 package org.chromium.chrome.browser.tasks.tab_management;
 
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
-import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -49,7 +49,7 @@
     public void setUp() {
         IphMessageService.setSkipIphInTestsForTesting(false);
         TrackerFactory.setTrackerForTests(mTracker);
-        mIphMessageService = new IphMessageService(mProfile, mIphController);
+        mIphMessageService = new IphMessageService(() -> mProfile, mIphController);
     }
 
     @Test
@@ -70,8 +70,7 @@
     public void testAddObserver_NotInitialized() {
         doReturn(false).when(mTracker).isInitialized();
         mIphMessageService.addObserver(mMessageObserver);
-        Assert.assertTrue(
-                mIphMessageService.getObserversForTesting().hasObserver(mMessageObserver));
+        assertTrue(mIphMessageService.getObserversForTesting().hasObserver(mMessageObserver));
         verify(mTracker, times(1))
                 .addOnInitializedCallback(mIphMessageService.getInitializedCallbackForTesting());
     }
@@ -83,8 +82,7 @@
                 .wouldTriggerHelpUi(eq(FeatureConstants.TAB_GROUPS_DRAG_AND_DROP_FEATURE));
         doReturn(true).when(mTracker).isInitialized();
         mIphMessageService.addObserver(mMessageObserver);
-        Assert.assertTrue(
-                mIphMessageService.getObserversForTesting().hasObserver(mMessageObserver));
+        assertTrue(mIphMessageService.getObserversForTesting().hasObserver(mMessageObserver));
         verify(mMessageObserver, times(1)).messageReady(eq(MessageType.IPH), any());
     }
 
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
index 6c86f3f..d331bc57 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/MessageCardProviderMediatorUnitTest.java
@@ -5,10 +5,13 @@
 package org.chromium.chrome.browser.tasks.tab_management;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -29,7 +32,6 @@
 
 import org.chromium.base.test.BaseRobolectricTestRunner;
 import org.chromium.chrome.browser.price_tracking.PriceDropNotificationManagerImpl;
-import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tasks.tab_management.MessageCardView.ServiceDismissActionProvider;
 import org.chromium.chrome.browser.tasks.tab_management.MessageService.Message;
 import org.chromium.chrome.browser.tasks.tab_management.PriceMessageService.PriceMessageType;
@@ -38,7 +40,6 @@
 import org.chromium.ui.modelutil.PropertyModel;
 
 import java.util.List;
-import java.util.function.Supplier;
 
 /** Unit tests for {@link MessageCardProviderMediator}. */
 @RunWith(BaseRobolectricTestRunner.class)
@@ -55,13 +56,8 @@
 
     @Mock private Resources mResourcesMock;
 
-    @Mock private Profile mProfileMock;
-    @Mock private Profile mIncognitoProfileMock;
-
     @Mock private PriceMessageService.PriceMessageData mPriceMessageData;
 
-    @Mock private Supplier<Profile> mProfileSupplier;
-
     @Mock private IphMessageService.IphMessageData mIphMessageData;
 
     @Mock
@@ -70,13 +66,8 @@
 
     @Before
     public void setUp() {
-
-        doReturn(true).when(mIncognitoProfileMock).isOffTheRecord();
-        doReturn(mProfileMock).when(mProfileSupplier).get();
         doNothing().when(mServiceDismissActionProvider).dismiss(anyInt());
-        mMediator =
-                new MessageCardProviderMediator<>(
-                        mContext, mProfileSupplier, mServiceDismissActionProvider);
+        mMediator = new MessageCardProviderMediator<>(mContext, mServiceDismissActionProvider);
         mMediator.addMessageService(initService(MessageType.FOR_TESTING));
         mMediator.addMessageService(initService(MessageType.PRICE_MESSAGE));
         mMediator.addMessageService(initService(MessageType.IPH));
@@ -97,7 +88,7 @@
                                         a,
                                         b,
                                         mPriceMessageData,
-                                        new PriceDropNotificationManagerImpl(mProfileMock)));
+                                        new PriceDropNotificationManagerImpl(mock())));
                 break;
             case MessageType.IPH:
                 when(mIphMessageData.getDismissActionProvider()).thenReturn(() -> {});
@@ -124,7 +115,7 @@
         enqueueMessageItem(MessageType.FOR_TESTING, TESTING_ACTION);
 
         assertNotNull(mMediator.getNextMessageItemForType(MessageType.FOR_TESTING));
-        Assert.assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
         assertNotNull(getShownMessageFromService(MessageType.FOR_TESTING));
     }
 
@@ -133,14 +124,14 @@
         enqueueMessageItem(MessageType.PRICE_MESSAGE, -1);
 
         assertNotNull(mMediator.getNextMessageItemForType(MessageType.PRICE_MESSAGE));
-        Assert.assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
         assertNotNull(getShownMessageFromService(MessageType.PRICE_MESSAGE));
 
         enqueueMessageItem(MessageType.FOR_TESTING, TESTING_ACTION);
 
         assertNotNull(mMediator.getNextMessageItemForType(MessageType.PRICE_MESSAGE));
         assertNotNull(mMediator.getNextMessageItemForType(MessageType.FOR_TESTING));
-        Assert.assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
         assertNotNull(getShownMessageFromService(MessageType.FOR_TESTING));
     }
 
@@ -243,7 +234,7 @@
         mMediator.messageInvalidate(MessageType.PRICE_MESSAGE);
 
         Assert.assertNull(getShownMessageFromService(MessageType.PRICE_MESSAGE));
-        Assert.assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
 
         // Testing multiple Messages has the same type.
         enqueueMessageItem(MessageType.FOR_TESTING, TESTING_ACTION);
@@ -251,7 +242,7 @@
 
         mMediator.messageInvalidate(MessageType.FOR_TESTING);
         Assert.assertNull(getShownMessageFromService(MessageType.FOR_TESTING));
-        Assert.assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
     }
 
     @Test
@@ -263,7 +254,7 @@
 
         verify(mServiceDismissActionProvider).dismiss(anyInt());
         Assert.assertNull(getShownMessageFromService(MessageType.PRICE_MESSAGE));
-        Assert.assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
+        assertTrue(getMessageItemsForService(MessageType.PRICE_MESSAGE).isEmpty());
 
         // Testing multiple Messages has the same type.
         enqueueMessageItem(MessageType.FOR_TESTING, TESTING_ACTION);
@@ -272,7 +263,7 @@
         mMediator.getNextMessageItemForType(MessageType.FOR_TESTING);
         mMediator.invalidateShownMessage(MessageType.FOR_TESTING);
         Assert.assertNull(getShownMessageFromService(MessageType.FOR_TESTING));
-        Assert.assertFalse(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
+        assertFalse(getMessageItemsForService(MessageType.FOR_TESTING).isEmpty());
     }
 
     @Test
@@ -322,36 +313,15 @@
     }
 
     @Test
-    public void getNextMessageItemForTypeTest_UpdateIncognito() {
-        enqueueMessageItem(MessageType.IPH, -1);
-
-        PropertyModel messageModel = mMediator.getNextMessageItemForType(MessageType.IPH).model;
-        Assert.assertFalse(messageModel.get(MessageCardViewProperties.IS_INCOGNITO));
-
-        doReturn(mIncognitoProfileMock).when(mProfileSupplier).get();
-        messageModel = mMediator.getNextMessageItemForType(MessageType.IPH).model;
-        Assert.assertTrue(messageModel.get(MessageCardViewProperties.IS_INCOGNITO));
-    }
-
-    @Test
-    public void getNextMessageItemForTypeTest_UpdateIncognito_NoShownMessage() {
-        enqueueMessageItem(MessageType.IPH, -1);
-
-        doReturn(mIncognitoProfileMock).when(mProfileSupplier).get();
-        PropertyModel messageModel = mMediator.getNextMessageItemForType(MessageType.IPH).model;
-        Assert.assertTrue(messageModel.get(MessageCardViewProperties.IS_INCOGNITO));
-    }
-
-    @Test
     public void isMessageShownTest() {
-        Assert.assertFalse(
+        assertFalse(
                 mMediator.isMessageShown(
                         MessageType.PRICE_MESSAGE, PriceMessageType.PRICE_WELCOME));
         enqueueMessageItem(MessageType.PRICE_MESSAGE, -1);
         // Mock pulling this message, which will move the message from mMessageItems to
         // mShownMessageItems.
         mMediator.getNextMessageItemForType(MessageType.PRICE_MESSAGE);
-        Assert.assertTrue(
+        assertTrue(
                 mMediator.isMessageShown(
                         MessageType.PRICE_MESSAGE, PriceMessageType.PRICE_WELCOME));
     }
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml
index f720733..9bfc863 100644
--- a/chrome/android/java/res/values/ids.xml
+++ b/chrome/android/java/res/values/ids.xml
@@ -59,6 +59,7 @@
     <item type="id" name="contextmenu_share_page" />
     <item type="id" name="contextmenu_print_page" />
     <item type="id" name="contextmenu_inspect_element" />
+    <item type="id" name="contextmenu_view_page_source" />
 
     <!-- Custom Tab Group -->
     <item type="id" name="contextmenu_open_in_new_chrome_tab" />
diff --git a/chrome/android/java/res/values/styles.xml b/chrome/android/java/res/values/styles.xml
index 90e058e..6fd6594 100644
--- a/chrome/android/java/res/values/styles.xml
+++ b/chrome/android/java/res/values/styles.xml
@@ -573,6 +573,8 @@
     -->
     <style name="ModernToolbarPopupTheme">
         <item name="android:listChoiceIndicatorSingle">@drawable/checkmark_selection_drawable</item>
+        <item name="android:itemTextAppearance">@style/TextAppearance.DensityAdaptive.TextLarge.Primary</item>
+        <item name="listPreferredItemHeightSmall">?attr/listItemHeight</item>
     </style>
 
     <style name="Theme.Chromium.Widget" parent="Theme.BrowserUI.DayNight" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
index da41ade8..3dbbc8f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBaseAppCompatActivity.java
@@ -410,9 +410,7 @@
                             mInsetObserver,
                             EdgeToEdgeUtils.isUseBackupNavbarInsetsEnabled(),
                             EdgeToEdgeFieldTrialImpl.getBackupNavbarInsetsOverrides(),
-                            ChromeFeatureList.sEdgeToEdgeUseBackupNavbarInsetsUseTappable
-                                    .getValue(),
-                            ChromeFeatureList.sEdgeToEdgeUseBackupNavbarInsetsUseTappable
+                            ChromeFeatureList.sEdgeToEdgeUseBackupNavbarInsetsUseGestures
                                     .getValue());
         }
         return mEdgeToEdgeLayoutCoordinator;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
index 949e80a..5b280cc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -385,6 +385,7 @@
                     StripLayoutTab stripTab = findTabById(tab.getId());
                     assumeNonNull(stripTab);
                     stripTab.setIsPinned(isPinned);
+                    setAccessibilityDescription(stripTab, tab);
                     mPinnedTabCount += isPinned ? 1 : -1;
 
                     // Compute each view's ideal position to get ready for the tab move animation
@@ -729,35 +730,35 @@
                         NEW_TAB_BUTTON_HOVER_BACKGROUND_PRESSED_OPACITY);
 
         // Primary container for default bg color.
-        int BackgroundDefaultTint = TabUiThemeProvider.getDefaultNtbContainerColor(context);
+        int backgroundDefaultTint = TabUiThemeProvider.getDefaultNtbContainerColor(context);
 
         // Primary @ 20% for default pressed bg color.
-        int BackgroundPressedTint =
+        int backgroundPressedTint =
                 ColorUtils.setAlphaComponentWithFloat(
                         SemanticColorUtils.getDefaultIconColorAccent1(context),
                         NEW_TAB_BUTTON_DEFAULT_PRESSED_OPACITY);
 
         // gm3_baseline_surface_container_dark for incognito bg color.
-        int BackgroundIncognitoDefaultTint =
+        int backgroundIncognitoDefaultTint =
                 context.getColor(R.color.tab_strip_bg_incognito_default_tint);
 
         // gm3_baseline_surface_container_highest_dark for incognito pressed bg color
-        int BackgroundIncognitoPressedTint =
+        int backgroundIncognitoPressedTint =
                 context.getColor(R.color.tab_strip_bg_incognito_pressed_tint);
 
         // Tab strip redesign new tab button night mode bg color.
         if (ColorUtils.inNightMode(context)) {
             // colorSurfaceContainerLow for night mode bg color.
-            BackgroundDefaultTint = SemanticColorUtils.getColorSurfaceContainerLow(context);
+            backgroundDefaultTint = SemanticColorUtils.getColorSurfaceContainerLow(context);
 
             // colorSurfaceContainerHighest for pressed night mode bg color.
-            BackgroundPressedTint = SemanticColorUtils.getColorSurfaceContainerHighest(context);
+            backgroundPressedTint = SemanticColorUtils.getColorSurfaceContainerHighest(context);
         }
         mNewTabButton.setBackgroundTint(
-                BackgroundDefaultTint,
-                BackgroundPressedTint,
-                BackgroundIncognitoDefaultTint,
-                BackgroundIncognitoPressedTint,
+                backgroundDefaultTint,
+                backgroundPressedTint,
+                backgroundIncognitoDefaultTint,
+                backgroundIncognitoPressedTint,
                 apsBackgroundHoveredTint,
                 apsBackgroundPressedTint,
                 apsBackgroundIncognitoHoveredTint,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
index aabc0a5..cb92de7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuItem.java
@@ -75,6 +75,7 @@
         Item.SAVE_PAGE,
         Item.SHARE_PAGE,
         Item.PRINT_PAGE,
+        Item.VIEW_PAGE_SOURCE,
         Item.INSPECT_ELEMENT,
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -131,9 +132,10 @@
         int SHARE_PAGE = 39;
         int PRINT_PAGE = 40;
         // Developer Group
-        int INSPECT_ELEMENT = 41;
+        int VIEW_PAGE_SOURCE = 41;
+        int INSPECT_ELEMENT = 42;
         // ALWAYS UPDATE!
-        int NUM_ENTRIES = 42;
+        int NUM_ENTRIES = 43;
     }
 
     /** Mapping from {@link Item} to the ID found in the ids.xml. */
@@ -179,6 +181,7 @@
         R.id.contextmenu_save_page, // Item.SAVE_PAGE
         R.id.contextmenu_share_page, // Item.SHARE_PAGE
         R.id.contextmenu_print_page, // Item.PRINT_PAGE
+        R.id.contextmenu_view_page_source, // Item.VIEW_PAGE_SOURCE
         R.id.contextmenu_inspect_element, // Item.INSPECT_ELEMENT
     };
 
@@ -225,6 +228,7 @@
         R.string.contextmenu_save_page, // Item.SAVE_PAGE
         R.string.contextmenu_share_page, // Item.SHARE_PAGE
         R.string.contextmenu_print_page, // Item.PRINT_PAGE
+        R.string.contextmenu_view_page_source, // Item.VIEW_PAGE_SOURCE
         R.string.contextmenu_inspect_element, // Item.INSPECT_ELEMENT
     };
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
index a0abf7a..e557a03 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -177,7 +177,7 @@
     static class ContextMenuUma {
         // Note: these values must match the ContextMenuOptionAndroid enum in enums.xml.
         // Only add values to the end, right before NUM_ENTRIES!
-        // LINT.IfChange(Action)
+        // LINT.IfChange(ContextMenuUma.Action)
         @IntDef({
             Action.OPEN_IN_NEW_TAB,
             Action.OPEN_IN_INCOGNITO_TAB,
@@ -226,6 +226,7 @@
             Action.ENTER_PICTURE_IN_PICTURE,
             Action.EXIT_PICTURE_IN_PICTURE,
             Action.OPEN_IN_INCOGNITO_WINDOW,
+            Action.VIEW_PAGE_SOURCE,
         })
         @Retention(RetentionPolicy.SOURCE)
         public @interface Action {
@@ -281,7 +282,8 @@
             int ENTER_PICTURE_IN_PICTURE = 49;
             int EXIT_PICTURE_IN_PICTURE = 50;
             int OPEN_IN_INCOGNITO_WINDOW = 51;
-            int NUM_ENTRIES = 52;
+            int VIEW_PAGE_SOURCE = 52;
+            int NUM_ENTRIES = 53;
         }
 
         // LINT.ThenChange(/tools/metrics/histograms/enums.xml:ContextMenuOptionAndroid)
@@ -424,6 +426,11 @@
                 && DeviceInput.supportsPrecisionPointer();
     }
 
+    @VisibleForTesting
+    boolean shouldShowViewPageSourceMenu() {
+        return DevToolsWindowAndroid.canViewSource(getProfile(), mItemDelegate.getWebContents());
+    }
+
     @Override
     public List<ModelList> buildContextMenu() {
         int nextCustomMenuItemId = CUSTOM_MENU_ITEM_ID_START;
@@ -714,6 +721,11 @@
 
         if (shouldShowDeveloperMenu()) {
             ModelList developerGroup = new ModelList();
+            if (mParams.isPage()
+                    && shouldShowEmptySpaceContextMenu()
+                    && shouldShowViewPageSourceMenu()) {
+                developerGroup.add(createListItem(Item.VIEW_PAGE_SOURCE));
+            }
             developerGroup.add(createListItem(Item.INSPECT_ELEMENT));
             groupedItems.add(developerGroup);
         }
@@ -1075,6 +1087,9 @@
                     mParams.getReferrer(),
                     /* navigateToTab= */ true,
                     /* additionalNavigationParams= */ null);
+        } else if (itemId == R.id.contextmenu_view_page_source) {
+            recordContextMenuSelection(ContextMenuUma.Action.VIEW_PAGE_SOURCE);
+            mItemDelegate.getWebContents().getMainFrame().viewSource();
         } else if (itemId == R.id.contextmenu_inspect_element) {
             recordContextMenuSelection(ContextMenuUma.Action.INSPECT_ELEMENT);
             mNativeDelegate.inspectElement(
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 249736a..f16fd3f 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
@@ -1275,7 +1275,10 @@
 
         mProgressBarCoordinator =
                 new LoadProgressCoordinator(
-                        mActivityTabProvider, mToolbar.getProgressBar(), topControlsStacker);
+                        mActivityTabProvider,
+                        mToolbar.getProgressBar(),
+                        topControlsStacker,
+                        mBrowserControlsSizer);
         mToolbar.setToolbarColorObserver(statusBarColorController);
 
         mActivityTabTabObserver =
@@ -1950,7 +1953,8 @@
                                 ? mHomePageButtonsCoordinator
                                 : mHomeButtonCoordinator,
                         mExtensionToolbarCoordinator,
-                        topControlsStacker);
+                        topControlsStacker,
+                        mBrowserControlsSizer);
 
         mHomepageStateListener =
                 () -> {
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
index 48fea35..10b6f83 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulatorTest.java
@@ -166,27 +166,29 @@
     }
 
     private void initializePopulator(@ContextMenuMode int mode, ContextMenuParams params) {
-        initializePopulator(mode, params, false, true);
-    }
-
-    private void initializePopulator(
-            @ContextMenuMode int mode, ContextMenuParams params, boolean shouldShowDeveloperMenu) {
-        initializePopulator(mode, params, shouldShowDeveloperMenu, true);
+        initializePopulator(mode, params, false, false, true);
     }
 
     private void initializePopulator(
             @ContextMenuMode int mode,
             ContextMenuParams params,
             boolean shouldShowDeveloperMenu,
+            boolean shouldShowViewPageSourceMenu,
             boolean supportPrint) {
-        initializePopulator(mode, params, List.of(), shouldShowDeveloperMenu, supportPrint);
+        initializePopulator(
+                mode,
+                params,
+                List.of(),
+                shouldShowDeveloperMenu,
+                shouldShowViewPageSourceMenu,
+                supportPrint);
     }
 
     private void initializePopulator(
             @ContextMenuMode int mode,
             ContextMenuParams params,
             List<CustomContentAction> actions) {
-        initializePopulator(mode, params, actions, false, true);
+        initializePopulator(mode, params, actions, false, false, true);
     }
 
     private void initializePopulator(
@@ -194,6 +196,7 @@
             ContextMenuParams params,
             List<CustomContentAction> actions,
             boolean shouldShowDeveloperMenu,
+            boolean shouldShowViewPageSourceMenu,
             boolean supportPrint) {
         mPopulator =
                 Mockito.spy(
@@ -211,6 +214,7 @@
         doReturn(true).when(mPopulator).shouldShowEmptySpaceContextMenu();
         doReturn(true).when(mExternalAuthUtils).isGoogleSigned(IntentHandler.PACKAGE_GSA);
         doReturn(shouldShowDeveloperMenu).when(mPopulator).shouldShowDeveloperMenu();
+        doReturn(shouldShowViewPageSourceMenu).when(mPopulator).shouldShowViewPageSourceMenu();
         doReturn(supportPrint).when(mItemDelegate).isPrintSupported();
     }
 
@@ -398,7 +402,8 @@
         };
         checkMenuOptions(expected5);
 
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true);
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true, false, true);
         int[] expected6Tab1 = {
             R.id.contextmenu_open_in_new_tab,
             R.id.contextmenu_open_in_new_tab_in_group,
@@ -902,7 +907,8 @@
         };
         checkMenuOptions(expected5Tab1, expected2Tab2);
 
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true);
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true, false, true);
         int[] expected6Tab1 = {
             R.id.contextmenu_open_in_new_tab,
             R.id.contextmenu_open_in_new_tab_in_group,
@@ -1152,7 +1158,8 @@
         };
         checkMenuOptions(expected5);
 
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true);
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true, false, true);
         int[] expected2Tab1 = {
             R.id.contextmenu_open_image_in_new_tab,
             R.id.contextmenu_open_image_in_ephemeral_tab,
@@ -1843,20 +1850,27 @@
 
         int[][] expected = {
             {R.id.contextmenu_save_page, R.id.contextmenu_share_page, R.id.contextmenu_print_page},
-            {R.id.contextmenu_inspect_element},
+            {R.id.contextmenu_view_page_source, R.id.contextmenu_inspect_element},
         };
 
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true);
-        checkMenuOptions(expected);
-
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.CUSTOM_TAB, params, true);
-        checkMenuOptions(expected);
-
-        initializePopulator(ChromeContextMenuPopulator.ContextMenuMode.WEB_APP, params, true);
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, true, true, true);
         checkMenuOptions(expected);
 
         initializePopulator(
-                ChromeContextMenuPopulator.ContextMenuMode.NETWORK_BOUND_TAB, params, true);
+                ChromeContextMenuPopulator.ContextMenuMode.CUSTOM_TAB, params, true, true, true);
+        checkMenuOptions(expected);
+
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.WEB_APP, params, true, true, true);
+        checkMenuOptions(expected);
+
+        initializePopulator(
+                ChromeContextMenuPopulator.ContextMenuMode.NETWORK_BOUND_TAB,
+                params,
+                true,
+                true,
+                true);
         checkMenuOptions(expected);
     }
 
@@ -1938,19 +1952,23 @@
         };
 
         initializePopulator(
-                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, false, false);
+                ChromeContextMenuPopulator.ContextMenuMode.NORMAL, params, false, false, false);
         checkMenuOptions(expected);
 
         initializePopulator(
-                ChromeContextMenuPopulator.ContextMenuMode.CUSTOM_TAB, params, false, false);
+                ChromeContextMenuPopulator.ContextMenuMode.CUSTOM_TAB, params, false, false, false);
         checkMenuOptions(expected);
 
         initializePopulator(
-                ChromeContextMenuPopulator.ContextMenuMode.WEB_APP, params, false, false);
+                ChromeContextMenuPopulator.ContextMenuMode.WEB_APP, params, false, false, false);
         checkMenuOptions(expected);
 
         initializePopulator(
-                ChromeContextMenuPopulator.ContextMenuMode.NETWORK_BOUND_TAB, params, false, false);
+                ChromeContextMenuPopulator.ContextMenuMode.NETWORK_BOUND_TAB,
+                params,
+                false,
+                false,
+                false);
         checkMenuOptions(expected);
     }
 
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index ee59bdc..0034af19 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2171,6 +2171,7 @@
     "//components/custom_handlers",
     "//components/data_sharing/internal",
     "//components/data_sharing/internal:personal_collaboration_data_internal",
+    "//components/data_sharing/migration/internal",
     "//components/data_sharing/public",
     "//components/data_sharing/public:personal_collaboration_data",
     "//components/device_event_log",
@@ -7137,6 +7138,9 @@
       "shutdown_signal_handlers_posix.cc",
       "shutdown_signal_handlers_posix.h",
     ]
+    if (!is_mac) {
+      deps += [ "//components/os_crypt/async/browser:posix_key_provider" ]
+    }
   }
 
   if (is_win || is_linux || is_chromeos) {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 47fa197..2e8b681 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -13311,6 +13311,13 @@
      flag_descriptions::kPasskeyUnlockErrorUiDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(device::kPasskeyUnlockErrorUi)},
 #endif
+
+#if BUILDFLAG(IS_CHROMEOS)
+    {"vids-app-preinstall", flag_descriptions::kVidsAppPreinstallName,
+     flag_descriptions::kVidsAppPreinstallDescription, kOsCrOS,
+     FEATURE_VALUE_TYPE(chromeos::features::kVidsAppPreinstall)},
+#endif
+
     // Add new entries above this line.
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/ai/ai_context_bound_object_set.cc b/chrome/browser/ai/ai_context_bound_object_set.cc
index 67a293a..5f81c24de 100644
--- a/chrome/browser/ai/ai_context_bound_object_set.cc
+++ b/chrome/browser/ai/ai_context_bound_object_set.cc
@@ -30,6 +30,6 @@
   }
 }
 
-size_t AIContextBoundObjectSet::GetSizeForTesting() {
+size_t AIContextBoundObjectSet::GetSize() const {
   return context_bound_object_set_.size();
 }
diff --git a/chrome/browser/ai/ai_context_bound_object_set.h b/chrome/browser/ai/ai_context_bound_object_set.h
index efd70c6..b79bd5b7 100644
--- a/chrome/browser/ai/ai_context_bound_object_set.h
+++ b/chrome/browser/ai/ai_context_bound_object_set.h
@@ -21,8 +21,8 @@
 
   // Add an `AIContextBoundObject` into the set.
   void AddContextBoundObject(std::unique_ptr<AIContextBoundObject> object);
-  // Returns the size of user data set for testing purpose.
-  size_t GetSizeForTesting();
+  // Returns the size of set.
+  size_t GetSize() const;
 
   // Remove the `AIContextBoundObject` from the set.
   void RemoveContextBoundObject(AIContextBoundObject* object);
diff --git a/chrome/browser/ai/ai_manager.cc b/chrome/browser/ai/ai_manager.cc
index e8d31c2..9569841 100644
--- a/chrome/browser/ai/ai_manager.cc
+++ b/chrome/browser/ai/ai_manager.cc
@@ -864,8 +864,13 @@
   // the reason.
   if (eligibility !=
       optimization_guide::OnDeviceModelEligibilityReason::kSuccess) {
+    // If context_bound_object_set_ size or model_download_progress_manager_
+    // reporters are non-zero, it implies that a download is pending.
+    // TODO(crbug.com/444320307): Make this more robust by actually checking
+    // opt-guide download status.
     bool is_downloading =
-        model_download_progress_manager_.GetNumberOfReporters() >= 1;
+        model_download_progress_manager_.GetNumberOfReporters() >= 1 ||
+        context_bound_object_set_.GetSize() >= 1;
     std::move(callback).Run(
         ConvertOnDeviceModelEligibilityReasonToModelAvailabilityCheckResult(
             eligibility, is_downloading));
diff --git a/chrome/browser/ai/ai_manager.h b/chrome/browser/ai/ai_manager.h
index 8e506eb..d92bc72 100644
--- a/chrome/browser/ai/ai_manager.h
+++ b/chrome/browser/ai/ai_manager.h
@@ -62,7 +62,7 @@
   void AddReceiver(mojo::PendingReceiver<blink::mojom::AIManager> receiver);
 
   size_t GetContextBoundObjectSetSizeForTesting() {
-    return context_bound_object_set_.GetSizeForTesting();
+    return context_bound_object_set_.GetSize();
   }
 
   size_t GetDownloadProgressObserversSizeForTesting() {
diff --git a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.cc b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.cc
index ef868ee..18d050d 100644
--- a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.cc
+++ b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.cc
@@ -71,9 +71,9 @@
 }
 
 void SensitivityPersistedTabDataAndroid::OnPageContentAnnotated(
-    const GURL& url,
+    const page_content_annotations::HistoryVisit& visit,
     const page_content_annotations::PageContentAnnotationsResult& result) {
-  if (tab_->GetURL() != url) {
+  if (tab_->GetURL() != visit.url) {
     return;
   }
   set_sensitivity_score(result.GetContentVisibilityScore());
diff --git a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.h b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.h
index 84a206f..6e6a792 100644
--- a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.h
+++ b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android.h
@@ -43,7 +43,7 @@
 
   // page_content_annotations::PageContentAnnotationsService::PageContentAnnotationsObserver
   void OnPageContentAnnotated(
-      const GURL& url,
+      const page_content_annotations::HistoryVisit& visit,
       const page_content_annotations::PageContentAnnotationsResult& result)
       override;
 
diff --git a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android_browsertest.cc b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android_browsertest.cc
index e3a6e7c..ce86dd69 100644
--- a/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android_browsertest.cc
+++ b/chrome/browser/android/persisted_tab_data/sensitivity_persisted_tab_data_android_browsertest.cc
@@ -18,6 +18,7 @@
 #include "url/gurl.h"
 
 namespace {
+using page_content_annotations::HistoryVisit;
 const char kSensitiveRelUrl[] = "/android/sensitive.html";
 const char kNonSensitiveRelUrl[] = "/android/hello.html";
 const char kNonSensitiveRelUrl2[] = "/android/second.html";
@@ -166,7 +167,8 @@
 
   EXPECT_EQ(tab_android->GetURL().spec(), sensitive_url.spec());
 
-  sptda->OnPageContentAnnotated(sensitive_url, kSensitiveResult);
+  sptda->OnPageContentAnnotated(HistoryVisit({}, sensitive_url),
+                                kSensitiveResult);
   EXPECT_TRUE(sptda->is_sensitive());
   EXPECT_FLOAT_EQ(0.1, sptda->sensitivity_score());
 }
@@ -183,7 +185,8 @@
       new SensitivityPersistedTabDataAndroid(tab_android);
   EXPECT_EQ(tab_android->GetURL().spec(), non_sensitive_url.spec());
 
-  sptda->OnPageContentAnnotated(non_sensitive_url, kNonSensitiveResult);
+  sptda->OnPageContentAnnotated(HistoryVisit({}, non_sensitive_url),
+                                kNonSensitiveResult);
   EXPECT_FALSE(sptda->is_sensitive());
   EXPECT_FLOAT_EQ(0.7, sptda->sensitivity_score());
 }
@@ -207,9 +210,12 @@
   EXPECT_EQ(tab_android->GetURL().spec(), sensitive_url.spec());
 
   // Annotate both sensitive and non-sensitive tabs
-  sptda->OnPageContentAnnotated(non_sensitive_url, kNonSensitiveResult);
-  sptda->OnPageContentAnnotated(sensitive_url, kSensitiveResult);
-  sptda->OnPageContentAnnotated(non_sensitive_url2, kNonSensitiveResult2);
+  sptda->OnPageContentAnnotated(HistoryVisit({}, non_sensitive_url),
+                                kNonSensitiveResult);
+  sptda->OnPageContentAnnotated(HistoryVisit({}, sensitive_url),
+                                kSensitiveResult);
+  sptda->OnPageContentAnnotated(HistoryVisit({}, non_sensitive_url2),
+                                kNonSensitiveResult2);
   tab_android->SetUserData(SensitivityPersistedTabDataAndroid::UserDataKey(),
                            nullptr);
 
diff --git a/chrome/browser/android/tab_storage_packager_android.cc b/chrome/browser/android/tab_storage_packager_android.cc
index ba6b30a1..5d5f8730 100644
--- a/chrome/browser/android/tab_storage_packager_android.cc
+++ b/chrome/browser/android/tab_storage_packager_android.cc
@@ -13,8 +13,7 @@
 #include "base/token.h"
 #include "chrome/browser/android/tab_android.h"
 #include "chrome/browser/tab/android_tab_package.h"
-#include "chrome/browser/tab/collection_storage_package.h"
-#include "chrome/browser/tab/storage_id_mapping.h"
+#include "chrome/browser/tab/storage_package.h"
 #include "chrome/browser/tab/tab_storage_package.h"
 #include "chrome/browser/tab/tab_storage_packager.h"
 #include "components/tabs/public/direct_child_walker.h"
@@ -31,40 +30,12 @@
       Java_TabStoragePackager_create(env, reinterpret_cast<intptr_t>(this)));
 }
 
-void TabStoragePackagerAndroid::Package(const TabInterface* tab) {
+std::unique_ptr<StoragePackage> TabStoragePackagerAndroid::Package(
+    const TabInterface* tab) {
   JNIEnv* env = base::android::AttachCurrentThread();
   Java_TabStoragePackager_packageTab(env, java_obj_,
                                      static_cast<const TabAndroid*>(tab));
-}
-
-void TabStoragePackagerAndroid::Package(const TabCollection* collection,
-                                        StorageIdMapping& mapping) {
-  tabs_pb::Children children_proto;
-  class ChildProcessor : public DirectChildWalker::Processor {
-   public:
-    ChildProcessor(tabs_pb::Children& children_proto, StorageIdMapping& mapping)
-        : children_proto_(children_proto), mapping_(mapping) {}
-
-    void ProcessTab(const TabInterface* tab) override {
-      children_proto_->add_storage_id(mapping_->GetStorageId(tab));
-    }
-    void ProcessCollection(const TabCollection* collection) override {
-      children_proto_->add_storage_id(mapping_->GetStorageId(collection));
-    }
-
-   private:
-    raw_ref<tabs_pb::Children> children_proto_;
-    raw_ref<StorageIdMapping> mapping_;
-  };
-
-  ChildProcessor processor(children_proto, mapping);
-  DirectChildWalker walker(collection, &processor);
-  walker.Walk();
-
-  // TODO(https://crbug.com/448875689): Fill this package with collection
-  // specific data.
-  package_ =
-      std::make_unique<CollectionStoragePackage>(std::move(children_proto));
+  return ReleasePackage();
 }
 
 void TabStoragePackagerAndroid::ConsolidatePackageData(
diff --git a/chrome/browser/android/tab_storage_packager_android.h b/chrome/browser/android/tab_storage_packager_android.h
index 495f499..eb6e1d7b 100644
--- a/chrome/browser/android/tab_storage_packager_android.h
+++ b/chrome/browser/android/tab_storage_packager_android.h
@@ -15,10 +15,8 @@
 #include "components/tabs/public/tab_interface.h"
 
 namespace tabs {
-class StorageIdMapping;
 class StoragePackage;
 class TabInterface;
-class TabCollection;
 
 // This class is the Android implementation of the TabStoragePackager.
 class TabStoragePackagerAndroid : public TabStoragePackager {
@@ -30,11 +28,8 @@
   TabStoragePackagerAndroid& operator=(const TabStoragePackagerAndroid&) =
       delete;
 
-  // TabStoragePackager overrides:
-  void Package(const TabInterface* tab) override;
-  void Package(const TabCollection* collection,
-               StorageIdMapping& mapping) override;
-  std::unique_ptr<StoragePackage> ReleasePackage() override;
+  // TabStoragePackager override:
+  std::unique_ptr<StoragePackage> Package(const TabInterface* tab) override;
 
   void ConsolidatePackageData(
       JNIEnv* env,
@@ -48,9 +43,11 @@
   base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
 
  private:
-  std::unique_ptr<StoragePackage> package_;
+  std::unique_ptr<StoragePackage> ReleasePackage();
+
   // A reference to the Java version of this class.
   base::android::ScopedJavaGlobalRef<jobject> java_obj_;
+  std::unique_ptr<StoragePackage> package_;
 };
 
 }  // namespace tabs
diff --git a/chrome/browser/ash/app_mode/kiosk_troubleshooting_tools_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_troubleshooting_tools_browsertest.cc
index 119cbef..6fe92f6 100644
--- a/chrome/browser/ash/app_mode/kiosk_troubleshooting_tools_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_troubleshooting_tools_browsertest.cc
@@ -69,8 +69,9 @@
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
     event_generator_ = std::make_unique<ui::test::EventGenerator>(
         ash::Shell::Get()->GetPrimaryRootWindow());
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
-    SelectFirstBrowser();
+    SetBrowser(browser_created_observer.Wait());
     ExpectOnlyKioskAppOpen();
   }
 
diff --git a/chrome/browser/ash/app_mode/test/kiosk_iwa_device_attributes_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_iwa_device_attributes_browsertest.cc
index d6e9d4f..1848638 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_iwa_device_attributes_browsertest.cc
+++ b/chrome/browser/ash/app_mode/test/kiosk_iwa_device_attributes_browsertest.cc
@@ -23,6 +23,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h"
 #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_test_update_server.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/ash/components/settings/cros_settings_names.h"
 #include "chromeos/ash/components/system/fake_statistics_provider.h"
 #include "chromeos/ash/components/system/statistics_provider.h"
@@ -237,9 +238,10 @@
 
   void LaunchIwaKiosk() {
     ASSERT_TRUE(LaunchAppManually(TheKioskApp()));
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
+    SetBrowser(browser_created_observer.Wait());
 
-    SelectFirstBrowser();
     ASSERT_NE(web_contents(), nullptr);
     ASSERT_EQ(web_contents()->GetVisibleURL(), kAppOrigin.GetURL());
     ASSERT_TRUE(WaitForLoadStop(web_contents()));
diff --git a/chrome/browser/ash/app_mode/test/kiosk_iwa_permissions_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_iwa_permissions_browsertest.cc
index 78b5c0b..9b8b4cb 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_iwa_permissions_browsertest.cc
+++ b/chrome/browser/ash/app_mode/test/kiosk_iwa_permissions_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h"
 #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_test_update_server.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/test_support/signed_web_bundles/key_pair.h"
 #include "components/webapps/isolated_web_apps/scheme.h"
@@ -179,10 +180,10 @@
 
   void SetUpOnMainThread() override {
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
-
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
+    SetBrowser(browser_created_observer.Wait());
 
-    SelectFirstBrowser();
     ASSERT_NE(web_contents(), nullptr);
     ASSERT_EQ(web_contents()->GetVisibleURL(), kExpectedOrigin.GetURL());
     WaitForPageLoad(web_contents());
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.cc b/chrome/browser/ash/crosapi/vpn_service_ash.cc
index b411c64..886a6c70 100644
--- a/chrome/browser/ash/crosapi/vpn_service_ash.cc
+++ b/chrome/browser/ash/crosapi/vpn_service_ash.cc
@@ -36,12 +36,6 @@
   std::move(callback).Run(nullptr);
 }
 
-void RunWarningCallback(
-    crosapi::VpnServiceForExtensionAsh::SuccessCallback callback,
-    const std::string& /*warning*/) {
-  std::move(callback).Run();
-}
-
 void RunFailureCallback(SuccessOrFailureCallback callback,
                         const std::string& error_name,
                         const std::string& error_message) {
@@ -264,60 +258,6 @@
               weak_factory_.GetWeakPtr(), std::move(failure)));
 }
 
-void VpnServiceForExtensionAsh::SetParameters(base::Value::Dict parameters,
-                                              SetParametersCallback callback) {
-  if (!OwnsActiveConfiguration()) {
-    RunFailureCallback(std::move(callback), /*error_name=*/{},
-                       "Unauthorized access.");
-    return;
-  }
-
-  auto [success, failure] = AdaptCallback(std::move(callback));
-  ash::ShillThirdPartyVpnDriverClient::Get()->SetParameters(
-      active_configuration_->object_path(), std::move(parameters),
-      base::BindOnce(&RunWarningCallback, std::move(success)),
-      std::move(failure));
-}
-
-void VpnServiceForExtensionAsh::SendPacket(const std::vector<uint8_t>& data,
-                                           SendPacketCallback callback) {
-  if (!OwnsActiveConfiguration()) {
-    RunFailureCallback(std::move(callback), /*error_name=*/{},
-                       "Unauthorized access.");
-    return;
-  }
-
-  if (data.empty()) {
-    RunFailureCallback(std::move(callback), /*error_name=*/{},
-                       "Can't send an empty packet.");
-    return;
-  }
-
-  auto [success, failure] = AdaptCallback(std::move(callback));
-  ash::ShillThirdPartyVpnDriverClient::Get()->SendPacket(
-      active_configuration_->object_path(),
-      std::vector<char>(data.begin(), data.end()), std::move(success),
-      std::move(failure));
-}
-
-void VpnServiceForExtensionAsh::NotifyConnectionStateChanged(
-    bool connection_success,
-    NotifyConnectionStateChangedCallback callback) {
-  if (!OwnsActiveConfiguration()) {
-    RunFailureCallback(std::move(callback), /*error_name=*/{},
-                       "Unauthorized access.");
-    return;
-  }
-
-  auto [success, failure] = AdaptCallback(std::move(callback));
-  ash::ShillThirdPartyVpnDriverClient::Get()->UpdateConnectionState(
-      active_configuration_->object_path(),
-      connection_success
-          ? base::to_underlying(api_vpn::VpnConnectionState::kConnected)
-          : base::to_underlying(api_vpn::VpnConnectionState::kFailure),
-      std::move(success), std::move(failure));
-}
-
 void VpnServiceForExtensionAsh::BindPepperVpnProxyObserver(
     const std::string& configuration_name,
     mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>
@@ -376,6 +316,14 @@
   DestroyConfigurationInternal(configuration);
 }
 
+std::optional<std::string>
+VpnServiceForExtensionAsh::GetActiveConfigurationObjectPath() const {
+  if (active_configuration_) {
+    return active_configuration_->object_path();
+  }
+  return std::nullopt;
+}
+
 bool VpnServiceForExtensionAsh::OwnsActiveConfiguration() const {
   return !!active_configuration_;
 }
@@ -540,8 +488,13 @@
   if (!service) {
     return;
   }
-  service->NotifyConnectionStateChanged(
-      /*connection_success=*/false, base::DoNothing());
+  if (std::optional<std::string> object_path =
+          service->GetActiveConfigurationObjectPath()) {
+    ash::ShillThirdPartyVpnDriverClient::Get()->UpdateConnectionState(
+        *object_path,
+        base::to_underlying(api_vpn::VpnConnectionState::kFailure),
+        base::DoNothing(), base::DoNothing());
+  }
 
   if (destroy_configurations) {
     service->DestroyAllConfigurations();
diff --git a/chrome/browser/ash/crosapi/vpn_service_ash.h b/chrome/browser/ash/crosapi/vpn_service_ash.h
index 8d6f7ff..a248573 100644
--- a/chrome/browser/ash/crosapi/vpn_service_ash.h
+++ b/chrome/browser/ash/crosapi/vpn_service_ash.h
@@ -79,13 +79,6 @@
                            CreateConfigurationCallback) override;
   void DestroyConfiguration(const std::string& configuration_name,
                             DestroyConfigurationCallback) override;
-  void SetParameters(base::Value::Dict parameters,
-                     SetParametersCallback) override;
-  void SendPacket(const std::vector<uint8_t>& data,
-                  SendPacketCallback) override;
-  void NotifyConnectionStateChanged(
-      bool connection_success,
-      NotifyConnectionStateChangedCallback) override;
   void BindPepperVpnProxyObserver(
       const std::string& configuration_name,
       mojo::PendingRemote<crosapi::mojom::PepperVpnProxyObserver>
@@ -96,6 +89,10 @@
   void OnConfigurationRemoved(const std::string& service_path,
                               const std::string& guid) override;
 
+  // Returns the object path of the active configuration if it exists.
+  // Otherwise, returns std::nullopt.
+  std::optional<std::string> GetActiveConfigurationObjectPath() const;
+
   bool OwnsActiveConfiguration() const;
   bool HasConfigurationForServicePath(const std::string& service_path) const;
 
@@ -205,6 +202,10 @@
   void OnVpnExtensionsChanged(
       base::flat_set<std::string> vpn_extensions) override;
 
+  // Always returns a valid pointer.
+  VpnServiceForExtensionAsh* GetVpnServiceForExtension(
+      const std::string& extension_id);
+
  private:
   friend class chromeos::VpnProviderApiTest;
   friend class VpnServiceForExtensionAsh;
@@ -217,9 +218,6 @@
       const std::string& service_path,
       std::optional<base::Value::Dict> configuration_properties);
 
-  // Always returns a valid pointer.
-  VpnServiceForExtensionAsh* GetVpnServiceForExtension(
-      const std::string& extension_id);
 
   // Ids of enabled vpn extensions.
   base::flat_set<std::string> vpn_extensions_;
diff --git a/chrome/browser/ash/extensions/default_app_order.cc b/chrome/browser/ash/extensions/default_app_order.cc
index d69eb2b..a56dced 100644
--- a/chrome/browser/ash/extensions/default_app_order.cc
+++ b/chrome/browser/ash/extensions/default_app_order.cc
@@ -149,6 +149,8 @@
 
     ash::kNotebookLmAppId,
 
+    ash::kVidsAppId,
+
     arc::kYoutubeAppId,
     extension_misc::kYoutubeAppId,
     ash::kYoutubeAppId,
diff --git a/chrome/browser/ash/input_method/assistive_suggester.cc b/chrome/browser/ash/input_method/assistive_suggester.cc
index 7ca53145..c3736c0 100644
--- a/chrome/browser/ash/input_method/assistive_suggester.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester.cc
@@ -208,9 +208,7 @@
 }
 
 bool AssistiveSuggester::IsEmojiSuggestAdditionEnabled() {
-  return profile_->GetPrefs()->GetBoolean(
-             prefs::kEmojiSuggestionEnterpriseAllowed) &&
-         profile_->GetPrefs()->GetBoolean(prefs::kEmojiSuggestionEnabled);
+  return false;
 }
 
 bool AssistiveSuggester::IsMultiWordSuggestEnabled() {
diff --git a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
index 59e50ba7..238275b1 100644
--- a/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
+++ b/chrome/browser/ash/input_method/assistive_suggester_unittest.cc
@@ -190,18 +190,6 @@
   EXPECT_FALSE(assistive_suggester_->IsAssistiveFeatureEnabled());
 }
 
-TEST_F(AssistiveSuggesterTest, EmojiSuggestion_BothPrefsEnabledTrue) {
-  base::test::ScopedFeatureList feature_list;
-  feature_list.InitWithFeatures(
-      /*enabled_features=*/{},
-      /*disabled_features=*/{features::kAssistMultiWord});
-  profile_->GetPrefs()->SetBoolean(prefs::kEmojiSuggestionEnterpriseAllowed,
-                                   true);
-  profile_->GetPrefs()->SetBoolean(prefs::kEmojiSuggestionEnabled, true);
-
-  EXPECT_TRUE(assistive_suggester_->IsAssistiveFeatureEnabled());
-}
-
 TEST_F(AssistiveSuggesterTest, EmojiSuggestion_BothPrefsEnabledFalse) {
   base::test::ScopedFeatureList feature_list;
   feature_list.InitWithFeatures(
@@ -1179,25 +1167,6 @@
   EXPECT_FALSE(suggestion_handler_->GetShowingSuggestion());
 }
 
-TEST_F(AssistiveSuggesterEmojiTest, ShouldRecordNotAllowedWhenSwitchDisabled) {
-  // TODO(b/242472734): Allow enabled suggestions passed without replace.
-  assistive_suggester_ = std::make_unique<AssistiveSuggester>(
-      suggestion_handler_.get(), profile_.get(),
-      std::make_unique<FakeSuggesterSwitch>(EnabledSuggestions{
-          .emoji_suggestions = false,
-      }));
-  assistive_suggester_->get_emoji_suggester_for_testing()
-      ->LoadEmojiMapForTesting(kEmojiData);
-  assistive_suggester_->OnActivate(kUsEnglishEngineId);
-  assistive_suggester_->OnFocus(5, empty_context);
-
-  assistive_suggester_->OnSurroundingTextChanged(u"arrow ", gfx::Range(6));
-
-  histogram_tester_.ExpectTotalCount("InputMethod.Assistive.NotAllowed", 1);
-  histogram_tester_.ExpectUniqueSample("InputMethod.Assistive.NotAllowed",
-                                       AssistiveType::kEmoji, 1);
-}
-
 TEST_F(AssistiveSuggesterEmojiTest,
        ShouldRecordDisabledReasonWhenSwitchDisabled) {
   // TODO(b/242472734): Allow enabled suggestions passed without replace.
@@ -1218,13 +1187,4 @@
                                        DisabledReason::kUrlOrAppNotAllowed, 1);
 }
 
-TEST_F(AssistiveSuggesterEmojiTest, ShouldReturnPrefixBasedEmojiSuggestions) {
-  assistive_suggester_->OnActivate(kUsEnglishEngineId);
-  assistive_suggester_->OnFocus(5, empty_context);
-  assistive_suggester_->OnSurroundingTextChanged(u"arrow ", gfx::Range(6));
-
-  EXPECT_TRUE(suggestion_handler_->GetShowingSuggestion());
-  EXPECT_EQ(suggestion_handler_->GetSuggestionText(), u"←;↑;→");
-}
-
 }  // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_without_ime_service_browsertest.cc b/chrome/browser/ash/input_method/native_input_method_engine_without_ime_service_browsertest.cc
index d1d9400..29f50fc 100644
--- a/chrome/browser/ash/input_method/native_input_method_engine_without_ime_service_browsertest.cc
+++ b/chrome/browser/ash/input_method/native_input_method_engine_without_ime_service_browsertest.cc
@@ -219,37 +219,6 @@
 }  // namespace
 
 IN_PROC_BROWSER_TEST_F(NativeInputMethodEngineWithoutImeServiceTest,
-                       SuggestEmoji) {
-  base::HistogramTester histogram_tester;
-  engine_->Enable(kEngineIdUs);
-  TextInputTestHelper helper(GetBrowserInputMethod());
-  SetUpTextInput(helper);
-  const std::u16string prefix_text = u"happy ";
-  const std::u16string expected_result_text = u"happy 😀";
-
-  helper.GetTextInputClient()->InsertText(
-      prefix_text,
-      ui::TextInputClient::InsertTextCursorBehavior::kMoveCursorAfterText);
-  helper.WaitForSurroundingTextChanged(prefix_text);
-  // Selects first emoji.
-  DispatchKeyPress(ui::VKEY_DOWN, false);
-  DispatchKeyPress(ui::VKEY_RETURN, false);
-  helper.WaitForSurroundingTextChanged(expected_result_text);
-
-  EXPECT_EQ(expected_result_text, helper.GetSurroundingText());
-  histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Match",
-                                      AssistiveType::kEmoji, 1);
-  histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Disabled.Emoji",
-                                      DisabledReason::kNone, 1);
-  histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Coverage",
-                                      AssistiveType::kEmoji, 1);
-  histogram_tester.ExpectUniqueSample("InputMethod.Assistive.Success",
-                                      AssistiveType::kEmoji, 1);
-
-  SetFocus(nullptr);
-}
-
-IN_PROC_BROWSER_TEST_F(NativeInputMethodEngineWithoutImeServiceTest,
                        DismissEmojiSuggestionWhenUsersContinueTyping) {
   base::HistogramTester histogram_tester;
   engine_->Enable(kEngineIdUs);
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
index 88ea577..d9cd1da 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_accelerator_browsertest.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
@@ -52,7 +53,9 @@
 
   void SetUpOnMainThread() override {
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
+    SetBrowser(browser_created_observer.Wait());
   }
 
   KioskMixin kiosk_{
@@ -64,7 +67,6 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebKioskAcceleratorTest, AcceleratorsDontCloseSession) {
-  SelectFirstBrowser();
   ASSERT_EQ(BrowserList::GetInstance()->size(), 1u);
   ASSERT_FALSE(PressCloseTabAccelerator(browser()));
   ASSERT_FALSE(PressCloseWindowAccelerator(browser()));
@@ -77,8 +79,6 @@
 }
 
 IN_PROC_BROWSER_TEST_F(WebKioskAcceleratorTest, ZoomAccelerators) {
-  SelectFirstBrowser();
-
   BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
   ASSERT_NE(browser_view, nullptr);
   content::WebContents* web_contents = browser_view->GetActiveWebContents();
diff --git a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
index 9de0ac3..463fa1a 100644
--- a/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/kiosk_enterprise_input_api_browsertest.cc
@@ -151,14 +151,15 @@
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
     ExtensionTestMessageListener extension_ready("ready");
     extension_ready.set_extension_id(std::string(kExtensionId));
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(kiosk::test::WaitKioskLaunched());
+    SetBrowser(browser_created_observer.Wait());
     // `chrome.runtime` only gets defined once the page finishes loading.
     ASSERT_TRUE(WaitForLoadStop(&GetAppWebContents()));
     ASSERT_TRUE(extension_ready.WaitUntilSatisfied());
   }
 
   content::WebContents& GetAppWebContents() {
-    SelectFirstBrowser();
     BrowserView* browser_view =
         BrowserView::GetBrowserViewForBrowser(browser());
     return CHECK_DEREF(browser_view->GetActiveWebContents());
diff --git a/chrome/browser/ash/login/app_mode/test/web_kiosk_browser_permissions_browsertest.cc b/chrome/browser/ash/login/app_mode/test/web_kiosk_browser_permissions_browsertest.cc
index 15c7847..8044553a 100644
--- a/chrome/browser/ash/login/app_mode/test/web_kiosk_browser_permissions_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/web_kiosk_browser_permissions_browsertest.cc
@@ -13,6 +13,7 @@
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/test/browser_test.h"
@@ -63,8 +64,9 @@
 
   void SetUpOnMainThread() override {
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
-    SelectFirstBrowser();
+    SetBrowser(browser_created_observer.Wait());
   }
 
   content::WebContents* GetKioskAppWebContents() {
diff --git a/chrome/browser/ash/login/app_mode/test/web_kiosk_device_attributes_browsertest.cc b/chrome/browser/ash/login/app_mode/test/web_kiosk_device_attributes_browsertest.cc
index d90adc2..77197e9 100644
--- a/chrome/browser/ash/login/app_mode/test/web_kiosk_device_attributes_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/web_kiosk_device_attributes_browsertest.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/ash/components/system/fake_statistics_provider.h"
 #include "chromeos/ash/components/system/statistics_provider.h"
 #include "components/permissions/features.h"
@@ -122,8 +123,9 @@
 
   void SetUpOnMainThread() override {
     MixinBasedInProcessBrowserTest::SetUpOnMainThread();
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(WaitKioskLaunched());
-    SelectFirstBrowser();
+    SetBrowser(browser_created_observer.Wait());
   }
 
  protected:
diff --git a/chrome/browser/ash/login/app_mode/test/web_kiosk_media_ui_browsertest.cc b/chrome/browser/ash/login/app_mode/test/web_kiosk_media_ui_browsertest.cc
index 9d94724..48ff4ce5 100644
--- a/chrome/browser/ash/login/app_mode/test/web_kiosk_media_ui_browsertest.cc
+++ b/chrome/browser/ash/login/app_mode/test/web_kiosk_media_ui_browsertest.cc
@@ -62,13 +62,13 @@
 };
 
 IN_PROC_BROWSER_TEST_F(WebKioskMediaUITest, MediaTrayStaysPinnedInKiosk) {
+  ui_test_utils::BrowserCreatedObserver browser_created_observer;
   ASSERT_TRUE(WaitKioskLaunched());
+  SetBrowser(browser_created_observer.Wait());
 
   ash::MediaTray::SetPinnedToShelf(false);
   ASSERT_FALSE(ash::MediaTray::IsPinnedToShelf());
 
-  SelectFirstBrowser();
-
   MediaNotificationServiceFactory::GetForProfile(GetProfile())
       ->ShowDialogAsh(DummyPresentationContext(CHECK_DEREF(browser())));
 
diff --git a/chrome/browser/ash/login/test/DEPS b/chrome/browser/ash/login/test/DEPS
index db05db1..d6046835 100644
--- a/chrome/browser/ash/login/test/DEPS
+++ b/chrome/browser/ash/login/test/DEPS
@@ -29,6 +29,7 @@
   "+chrome/browser/lifetime",
   "+chrome/browser/profiles",
   "+chrome/browser/ui/ash",
+  "+chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h",
   "+chrome/browser/ui/webui/ash/login",
   "+chrome/browser/ui/webui/signin",
   "+chrome/common/chrome_paths.h",
diff --git a/chrome/browser/ash/login/test/logged_in_user_mixin.cc b/chrome/browser/ash/login/test/logged_in_user_mixin.cc
index 8d799adf..f1bbe85d 100644
--- a/chrome/browser/ash/login/test/logged_in_user_mixin.cc
+++ b/chrome/browser/ash/login/test/logged_in_user_mixin.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/ash/login/test/cryptohome_mixin.h"
 #include "chrome/browser/ash/login/test/login_manager_mixin.h"
 #include "chrome/browser/ash/login/test/user_auth_config.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/test/base/fake_gaia_mixin.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
@@ -160,7 +161,7 @@
     login_manager_.WaitForActiveSession();
     // If should_launch_browser was set to true, then ensures
     // InProcessBrowserTest::browser() doesn't return nullptr.
-    test_base_->SelectFirstBrowser();
+    test_base_->SetBrowser(GetLastActiveBrowserWindowInterfaceWithAnyProfile());
   }
 }
 
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_donation_service.cc b/chrome/browser/auxiliary_search/auxiliary_search_donation_service.cc
index e075fbb..6b095c5 100644
--- a/chrome/browser/auxiliary_search/auxiliary_search_donation_service.cc
+++ b/chrome/browser/auxiliary_search/auxiliary_search_donation_service.cc
@@ -24,8 +24,15 @@
 }
 
 void AuxiliarySearchDonationService::OnPageContentAnnotated(
-    const GURL& url,
+    const page_content_annotations::HistoryVisit& visit,
     const page_content_annotations::PageContentAnnotationsResult& result) {
+  // Ignore annotations from remote visits (navigation ID is 0).
+  if (result.GetType() !=
+          page_content_annotations::AnnotationType::kContentVisibility ||
+      visit.navigation_id == 0) {
+    return;
+  }
+
   // TODO: b/432359106 - Implement this using FetchAndRankHelper and
   // AuxiliarySearchDonor
 }
diff --git a/chrome/browser/auxiliary_search/auxiliary_search_donation_service.h b/chrome/browser/auxiliary_search/auxiliary_search_donation_service.h
index 02e10d8..f122f8a 100644
--- a/chrome/browser/auxiliary_search/auxiliary_search_donation_service.h
+++ b/chrome/browser/auxiliary_search/auxiliary_search_donation_service.h
@@ -12,7 +12,6 @@
 namespace page_content_annotations {
 class PageContentAnnotationsResult;
 }
-class GURL;
 
 // AuxiliarySearchDonationService manages donation of Chrome data to AppSearch.
 // Currently only donates browsing history data.
@@ -30,7 +29,7 @@
   //     ::PageContentAnnotationsService
   //     ::PageContentAnnotationsObserver
   void OnPageContentAnnotated(
-      const GURL& url,
+      const page_content_annotations::HistoryVisit& visit,
       const page_content_annotations::PageContentAnnotationsResult& result)
       override;
 
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarUtils.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarUtils.java
index f14ab23ce..e307b99 100644
--- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarUtils.java
+++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarUtils.java
@@ -152,7 +152,7 @@
      * therefore if the feature should be exposed to the user. If true, user flows such as keyboard
      * shortcuts, IPH, settings toggles, device policies, etc should be present. This value should
      * always return the same value for a device. Compatible devices include Desktop, large tablets,
-     * and foldables.
+     * and (unfolded) foldables.
      *
      * <p>Check this value when determining which user actions to expose to users for the Bookmark
      * Bar.
@@ -170,8 +170,7 @@
             return sDeviceBookmarkBarCompatibleForTesting;
         }
         return ChromeFeatureList.sAndroidBookmarkBar.isEnabled()
-                && (DeviceFormFactor.isNonMultiDisplayContextOnTablet(context)
-                        || DeviceInfo.isFoldable());
+                && DeviceFormFactor.isNonMultiDisplayContextOnTablet(context);
     }
 
     /**
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc
index 8e56f02..448b630b 100644
--- a/chrome/browser/browser_process_impl.cc
+++ b/chrome/browser/browser_process_impl.cc
@@ -259,12 +259,15 @@
 
 #if BUILDFLAG(IS_LINUX)
 #include "chrome/browser/browser_features.h"
-#include "components/os_crypt/async/browser/fallback_linux_key_provider.h"
 #include "components/os_crypt/async/browser/freedesktop_secret_key_provider.h"
 #include "components/os_crypt/async/browser/secret_portal_key_provider.h"
 #include "components/password_manager/core/browser/password_manager_switches.h"
 #endif
 
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+#include "components/os_crypt/async/browser/posix_key_provider.h"
+#endif
+
 #if BUILDFLAG(IS_MAC)
 #include "components/os_crypt/async/browser/keychain_key_provider.h"
 #endif
@@ -1404,15 +1407,25 @@
               base::FeatureList::IsEnabled(
                   features::kUseFreedesktopSecretKeyProviderForEncryption),
               l10n_util::GetStringUTF8(IDS_PRODUCT_NAME), nullptr));
-      providers.emplace_back(
-          /*precedence=*/5u,
-          std::make_unique<os_crypt_async::FallbackLinuxKeyProvider>(
-              base::FeatureList::IsEnabled(
-                  features::kUseFreedesktopSecretKeyProviderForEncryption)));
     }
   }
 #endif  // BUILDFLAG(IS_LINUX)
 
+#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+  // On Linux, this is used if the other key providers are disabled or not
+  // available. On other POSIX systems, this is the only key provider.
+#if BUILDFLAG(IS_LINUX)
+  const bool use_posix_key_provider_for_encryption =
+      base::FeatureList::IsEnabled(
+          features::kUseFreedesktopSecretKeyProviderForEncryption);
+#else
+  const bool use_posix_key_provider_for_encryption = true;
+#endif  // BUILDFLAG(IS_LINUX)
+  providers.emplace_back(
+      /*precedence=*/5u, std::make_unique<os_crypt_async::PosixKeyProvider>(
+                             use_posix_key_provider_for_encryption));
+#endif  // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
+
 #if BUILDFLAG(IS_MAC)
   if (base::FeatureList::IsEnabled(features::kUseKeychainKeyProvider)) {
     providers.emplace_back(std::make_pair(
diff --git a/chrome/browser/chrome_shared_array_buffer_browsertest.cc b/chrome/browser/chrome_shared_array_buffer_browsertest.cc
index a35cceb..6f18e838 100644
--- a/chrome/browser/chrome_shared_array_buffer_browsertest.cc
+++ b/chrome/browser/chrome_shared_array_buffer_browsertest.cc
@@ -60,9 +60,10 @@
     // the preference, so it can't create renderers with SABs enabled by policy.
     // Create a new browser that will pick up the preference and enable SABs for
     // new renderer processes.
-    Browser* new_browser = CreateBrowser(browser()->profile());
+    BrowserWindowInterface* const new_browser =
+        CreateBrowser(browser()->profile());
     CloseBrowserSynchronously(browser());
-    SelectFirstBrowser();
+    SetBrowser(new_browser);
     ASSERT_EQ(browser(), new_browser);
 
     // Clear existing spares and navigate the new browser to 'localhost', so the
diff --git a/chrome/browser/chromeos/app_mode/kiosk_app_level_logs_browsertest.cc b/chrome/browser/chromeos/app_mode/kiosk_app_level_logs_browsertest.cc
index 8041c07..5fd2499 100644
--- a/chrome/browser/chromeos/app_mode/kiosk_app_level_logs_browsertest.cc
+++ b/chrome/browser/chromeos/app_mode/kiosk_app_level_logs_browsertest.cc
@@ -16,6 +16,7 @@
 #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/common/pref_names.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "components/prefs/pref_service.h"
 #include "content/public/common/content_switches.h"
 #include "content/public/test/browser_test.h"
@@ -185,8 +186,9 @@
 
   void SetUpOnMainThread() override {
     KioskAppLevelLogsTestBase::SetUpOnMainThread();
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     ASSERT_TRUE(ash::kiosk::test::WaitKioskLaunched());
-    SelectFirstBrowser();
+    SetBrowser(browser_created_observer.Wait());
     ExpectOnlyKioskAppOpen();
   }
 
diff --git a/chrome/browser/chromeos/cros_apps/api/cros_apps_api_access_control_browsertest.cc b/chrome/browser/chromeos/cros_apps/api/cros_apps_api_access_control_browsertest.cc
index 419b2b9..39ae42a 100644
--- a/chrome/browser/chromeos/cros_apps/api/cros_apps_api_access_control_browsertest.cc
+++ b/chrome/browser/chromeos/cros_apps/api/cros_apps_api_access_control_browsertest.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/chrome_switches.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
@@ -86,9 +87,9 @@
 
     // Create the browser with a default WebContents for running the tests.
     Browser::CreateParams params(profile, /*user_gesture=*/true);
-    Browser::Create(params);
+    BrowserWindowInterface* const new_browser = Browser::Create(params);
     CHECK_EQ(1u, BrowserList::GetInstance()->size());
-    SelectFirstBrowser();
+    SetBrowser(new_browser);
     browser()->window()->Show();
 
     std::unique_ptr<content::WebContents> web_contents_to_add =
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn b/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
index 96f3bba..e0d861de 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
+++ b/chrome/browser/chromeos/extensions/vpn_provider/BUILD.gn
@@ -23,6 +23,7 @@
     "//base",
     "//chrome/browser/profiles:profile",
     "//chrome/common/extensions/api",
+    "//chromeos/ash/components/dbus/shill",
     "//chromeos/ash/components/login/login_state",
     "//chromeos/crosapi/mojom",
     "//components/keyed_service/content",
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
index 787c84fe3..459f426 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.cc
@@ -10,10 +10,12 @@
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
+#include "base/types/cxx23_to_underlying.h"
 #include "chrome/browser/ash/crosapi/crosapi_ash.h"
 #include "chrome/browser/ash/crosapi/crosapi_manager.h"
 #include "chrome/browser/ash/crosapi/vpn_service_ash.h"
 #include "chrome/common/extensions/api/vpn_provider.h"
+#include "chromeos/ash/components/dbus/shill/shill_third_party_vpn_driver_client.h"
 #include "content/public/browser/browser_context.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_event_histogram_value.h"
@@ -173,6 +175,19 @@
       ->DispatchEventToExtension(extension_id, std::move(event));
 }
 
+bool VpnService::OwnsActiveConfiguration(
+    const std::string& extension_id) const {
+  return GetActiveConfigurationObjectPath(extension_id).has_value();
+}
+
+std::optional<std::string> VpnService::GetActiveConfigurationObjectPath(
+    const std::string& extension_id) const {
+  // Peek into VpnServiceAsh directly (this call does not go through mojo).
+  return GetVpnService()
+      ->GetVpnServiceForExtension(extension_id)
+      ->GetActiveConfigurationObjectPath();
+}
+
 void VpnService::SendOnPlatformMessageToExtension(
     const std::string& extension_id,
     const std::string& configuration_name,
@@ -207,28 +222,58 @@
                                base::Value::Dict parameters,
                                SuccessCallback success,
                                FailureCallback failure) {
-  GetVpnServiceForExtension(extension_id)
-      ->SetParameters(std::move(parameters),
-                      AdaptCallback(std::move(success), std::move(failure)));
+  if (!OwnsActiveConfiguration(extension_id)) {
+    RunFailureCallback(std::move(failure), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  ash::ShillThirdPartyVpnDriverClient::Get()->SetParameters(
+      GetActiveConfigurationObjectPath(extension_id).value(),
+      std::move(parameters),
+      base::IgnoreArgs<const std::string&>(std::move(success)),
+      std::move(failure));
 }
 
 void VpnService::SendPacket(const std::string& extension_id,
                             const std::vector<char>& data,
                             SuccessCallback success,
                             FailureCallback failure) {
-  GetVpnServiceForExtension(extension_id)
-      ->SendPacket(std::vector<uint8_t>(data.begin(), data.end()),
-                   AdaptCallback(std::move(success), std::move(failure)));
+  if (!OwnsActiveConfiguration(extension_id)) {
+    RunFailureCallback(std::move(failure), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  if (data.empty()) {
+    RunFailureCallback(std::move(failure), /*error_name=*/{},
+                       "Can't send an empty packet.");
+    return;
+  }
+
+  ash::ShillThirdPartyVpnDriverClient::Get()->SendPacket(
+      GetActiveConfigurationObjectPath(extension_id).value(), data,
+      std::move(success), std::move(failure));
 }
 
 void VpnService::NotifyConnectionStateChanged(const std::string& extension_id,
                                               bool connection_success,
                                               SuccessCallback success,
                                               FailureCallback failure) {
-  GetVpnServiceForExtension(extension_id)
-      ->NotifyConnectionStateChanged(
-          connection_success,
-          AdaptCallback(std::move(success), std::move(failure)));
+  if (!OwnsActiveConfiguration(extension_id)) {
+    RunFailureCallback(std::move(failure), /*error_name=*/{},
+                       "Unauthorized access.");
+    return;
+  }
+
+  ash::ShillThirdPartyVpnDriverClient::Get()->UpdateConnectionState(
+      GetActiveConfigurationObjectPath(extension_id).value(),
+      connection_success
+          ? base::to_underlying(
+                extensions::api::vpn_provider::VpnConnectionState::kConnected)
+          : base::to_underlying(
+                extensions::api::vpn_provider::VpnConnectionState::kFailure),
+      std::move(success), std::move(failure));
 }
 
 void VpnService::Shutdown() {
@@ -276,7 +321,7 @@
 }
 
 // static
-crosapi::mojom::VpnService* VpnService::GetVpnService() {
+crosapi::VpnServiceAsh* VpnService::GetVpnService() {
   // CrosapiManager may not be initialized.
   // TODO(crbug.com/40225953): Assert it's only happening in tests.
   if (!crosapi::CrosapiManager::IsInitialized()) {
diff --git a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
index e5518a79..a6acdcfb 100644
--- a/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
+++ b/chrome/browser/chromeos/extensions/vpn_provider/vpn_service.h
@@ -39,6 +39,10 @@
 
 }  // namespace extensions
 
+namespace crosapi {
+class VpnServiceAsh;
+}
+
 namespace chromeos {
 
 class VpnServiceForExtension
@@ -125,7 +129,7 @@
   friend class VpnServiceForExtension;
   friend class VpnServiceFactory;
 
-  static crosapi::mojom::VpnService* GetVpnService();
+  static crosapi::VpnServiceAsh* GetVpnService();
 
   mojo::Remote<crosapi::mojom::VpnServiceForExtension>&
   GetVpnServiceForExtension(const std::string& extension_id);
@@ -134,6 +138,10 @@
   void SendToExtension(const std::string& extension_id,
                        std::unique_ptr<extensions::Event> event);
 
+  bool OwnsActiveConfiguration(const std::string& extension_id) const;
+  std::optional<std::string> GetActiveConfigurationObjectPath(
+      const std::string& extension_id) const;
+
   void SendOnPlatformMessageToExtension(const std::string& extension_id,
                                         const std::string& configuration_name,
                                         uint32_t platform_message);
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc
index 0abe25e..164c2ec 100644
--- a/chrome/browser/client_hints/client_hints_browsertest.cc
+++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -1843,9 +1843,10 @@
             expected_full_version_list);
 
   // Restart the browser, create a new browser to mock the restart process.
-  Browser* new_browser = CreateBrowser(browser()->profile());
+  BrowserWindowInterface* const new_browser =
+      CreateBrowser(browser()->profile());
   CloseBrowserSynchronously(browser());
-  SelectFirstBrowser();
+  SetBrowser(new_browser);
   ASSERT_EQ(browser(), new_browser);
 
   // First request with new browser should expect the high-entropy client hints
diff --git a/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc b/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc
index 593a97d..d9b01d3f 100644
--- a/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc
+++ b/chrome/browser/devtools/protocol/user_reidentification_issues_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_browser_test_harness.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/test/base/ui_test_utils.h"
 #include "components/fingerprinting_protection_filter/common/fingerprinting_protection_filter_features.h"
 #include "components/fingerprinting_protection_filter/interventions/common/interventions_features.h"
 #include "content/public/test/browser_test.h"
@@ -164,9 +165,10 @@
                        Enabled_Incognito_SubframeDocumentLoadIssueReported) {
   // Close normal browser and switch the test's browser instance to an incognito
   // instance.
-  Browser* incognito = CreateIncognitoBrowser(browser()->profile());
+  BrowserWindowInterface* const incognito =
+      CreateIncognitoBrowser(browser()->profile());
   CloseBrowserSynchronously(browser());
-  SelectFirstBrowser();
+  SetBrowser(incognito);
   ASSERT_EQ(browser(), incognito);
 
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/enterprise/signin/profile_management_disclaimer_service_browsertest.cc b/chrome/browser/enterprise/signin/profile_management_disclaimer_service_browsertest.cc
index 882420a..2f68520 100644
--- a/chrome/browser/enterprise/signin/profile_management_disclaimer_service_browsertest.cc
+++ b/chrome/browser/enterprise/signin/profile_management_disclaimer_service_browsertest.cc
@@ -269,9 +269,10 @@
   }
 
   void ReplaceCurrentBrowserWithNewOne() {
-    Browser* new_browser = CreateBrowser(browser()->profile());
+    BrowserWindowInterface* const new_browser =
+        CreateBrowser(browser()->profile());
     CloseBrowserSynchronously(browser());
-    SelectFirstBrowser();
+    SetBrowser(new_browser);
     ASSERT_EQ(browser(), new_browser);
   }
 
diff --git a/chrome/browser/extensions/api/automation/automation_apitest.cc b/chrome/browser/extensions/api/automation/automation_apitest.cc
index e5e88c4..b5e7449 100644
--- a/chrome/browser/extensions/api/automation/automation_apitest.cc
+++ b/chrome/browser/extensions/api/automation/automation_apitest.cc
@@ -742,12 +742,12 @@
   screen->SetDisplayForNewWindows(display2);
   // Run the test in the browser in the non-primary display.
   // Open a browser on the secondary display, which is default for new windows.
-  CreateBrowser(profile());
+  BrowserWindowInterface* const new_browser = CreateBrowser(profile());
   // Close the browser which was already opened on the primary display.
   CloseBrowserSynchronously(browser());
   // Sets browser() to return the one created above, instead of the one which
   // was closed.
-  SelectFirstBrowser();
+  SetBrowser(new_browser);
   // The test will run in browser().
   ASSERT_TRUE(
       CreateExtensionAndRunTest("desktop/hit_test.js", kPermissionsWindows))
diff --git a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
index 7509645..ee11cd44 100644
--- a/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
+++ b/chrome/browser/extensions/api/downloads/downloads_api_browsertest.cc
@@ -111,24 +111,15 @@
 namespace extensions {
 namespace downloads = api::downloads;
 
-// TODO(crbug.com/405219117): Enable more tests on desktop Android.
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-
 namespace {
 
 const char kFirstDownloadUrl[] = "/download1";
 const char kSecondDownloadUrl[] = "/download2";
 const int kDownloadSize = 1024 * 10;
 
-void OnFileDeleted(bool success) {}
+#if BUILDFLAG(ENABLE_EXTENSIONS)
 
-// Comparator that orders download items by their ID. Can be used with
-// std::sort.
-struct DownloadIdComparator {
-  bool operator() (DownloadItem* first, DownloadItem* second) {
-    return first->GetId() < second->GetId();
-  }
-};
+void OnFileDeleted(bool success) {}
 
 bool IsDownloadExternallyRemoved(download::DownloadItem* item) {
   return item->GetFileExternallyRemoved();
@@ -144,6 +135,16 @@
                      base::Unretained(prompt)));
 }
 
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+
+// Comparator that orders download items by their ID. Can be used with
+// std::sort.
+struct DownloadIdComparator {
+  bool operator()(DownloadItem* first, DownloadItem* second) {
+    return first->GetId() < second->GetId();
+  }
+};
+
 class DownloadsEventsListener : public EventRouter::TestObserver {
  public:
   explicit DownloadsEventsListener(Profile* profile)
@@ -374,11 +375,18 @@
     second_extension_ = LoadExtensionInternal(name, false);
   }
 
+  Profile* current_profile() { return current_profile_; }
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  Browser* current_browser() { return current_browser_; }
+
   content::RenderProcessHost* AddFilenameDeterminer() {
     ExtensionDownloadsEventRouter::SetDetermineFilenameTimeoutSecondsForTesting(
         2);
     // TODO(crbug.com/405219117): Add special navigation for Android here as
-    // NavigateToURLInNewTab() does not take a browser/profile.
+    // the call to chrome::AddSelectedTabWithURL() requires current_browser()
+    // but our usual replacement NavigateToURLInNewTab() does not take a browser
+    // or profile.
     content::WebContents* tab = chrome::AddSelectedTabWithURL(
         current_browser(), extension_->GetResourceURL("empty.html"),
         ui::PAGE_TRANSITION_LINK);
@@ -388,6 +396,7 @@
                            GetExtensionId());
     return tab->GetPrimaryMainFrame()->GetProcess();
   }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
   void RemoveFilenameDeterminer(content::RenderProcessHost* host) {
     EventRouter::Get(current_profile())
@@ -395,9 +404,6 @@
                               host, GetExtensionId());
   }
 
-  Browser* current_browser() { return current_browser_; }
-  Profile* current_profile() { return current_profile_; }
-
   // InProcessBrowserTest
   void SetUpOnMainThread() override {
     ExtensionApiTest::SetUpOnMainThread();
@@ -432,18 +438,25 @@
     second_extension_ = nullptr;
     current_profile_ = nullptr;
     incognito_profile_ = nullptr;
+#if BUILDFLAG(ENABLE_EXTENSIONS)
     current_browser_ = nullptr;
     incognito_browser_ = nullptr;
+#endif
     ExtensionApiTest::TearDownOnMainThread();
   }
 
   void GoOnTheRecord() {
+#if BUILDFLAG(ENABLE_EXTENSIONS)
     current_browser_ = browser();
-    current_profile_ = current_browser_->profile();
+#endif
+    current_profile_ = profile();
     if (events_listener_.get())
       events_listener_->UpdateProfile(current_profile());
   }
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  // TODO(crbug.com/405219117): Support incognito. This may require support for
+  // CreateBrowserWindow() with incognito profiles on Android.
   void GoOffTheRecord() {
     if (!incognito_browser_) {
       incognito_browser_ = CreateIncognitoBrowser();
@@ -458,6 +471,7 @@
     if (events_listener_.get())
       events_listener_->UpdateProfile(current_profile());
   }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
   bool WaitFor(const std::string& event_name, const std::string& json_args) {
     return events_listener_->WaitFor(current_profile(), event_name, json_args);
@@ -489,10 +503,8 @@
     return extension_->url().spec();
   }
   content::StoragePartitionConfig GetExtensionStoragePartitionConfig() {
-    return browser()
-        ->profile()
-        ->GetDownloadManager()
-        ->GetStoragePartitionConfigForSiteUrl(extension_->url());
+    return profile()->GetDownloadManager()->GetStoragePartitionConfigForSiteUrl(
+        extension_->url());
   }
   std::string GetExtensionId() {
     return extension_->id();
@@ -805,8 +817,10 @@
   raw_ptr<const Extension> second_extension_ = nullptr;
   raw_ptr<Profile> current_profile_ = nullptr;
   raw_ptr<Profile> incognito_profile_ = nullptr;
+#if BUILDFLAG(ENABLE_EXTENSIONS)
   raw_ptr<Browser> current_browser_ = nullptr;
   raw_ptr<Browser> incognito_browser_ = nullptr;
+#endif
   std::unique_ptr<DownloadsEventsListener> events_listener_;
 
   std::unique_ptr<net::test_server::ControllableHttpResponse> first_download_;
@@ -964,6 +978,10 @@
 
 }  // namespace
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+// The open dialog is not yet implemented on desktop Android. Also, Java-side
+// org.chromium.ui.permissions.ContextualNotificationPermissionRequester may
+// need to be initialized in android_browsertests for this test to pass.
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest, DownloadExtensionTest_Open) {
   platform_util::internal::DisableShellOperationsForTesting();
 
@@ -1028,6 +1046,7 @@
   EXPECT_TRUE(download_item->GetOpened());
 }
 
+// Flaky on desktop Android.
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_PauseResumeCancelErase) {
   DownloadItem* download_item = CreateFirstSlowTestDownload();
@@ -1119,6 +1138,7 @@
   ASSERT_TRUE(result_list[0].is_int());
   EXPECT_EQ(id, result_list[0].GetInt());
 }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_Open_Remove_Open) {
@@ -1162,8 +1182,11 @@
   return function;
 }
 
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+
 // Test downloads.getFileIcon() on in-progress, finished, cancelled and deleted
 // download items.
+// Flaky on desktop Android.
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_FileIcon_Active) {
   DownloadItem* download_item = CreateFirstSlowTestDownload();
@@ -1250,6 +1273,7 @@
   EXPECT_STREQ(errors::kInvalidId,
                error.c_str());
 }
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 // Test that we can acquire file icons for history downloads regardless of
 // whether they exist or not.  If the file doesn't exist we should receive a
@@ -1288,6 +1312,9 @@
   }
 }
 
+// TODO(crbug.com/405219117): Enable more tests on desktop Android.
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+
 // Test passing the empty query to search().
 IN_PROC_BROWSER_TEST_F(DownloadExtensionTest,
                        DownloadExtensionTest_SearchEmptyQuery) {
@@ -4586,8 +4613,6 @@
   ASSERT_TRUE(RunExtensionTest("downloads")) << message_;
 }
 
-// TODO(crbug.com/405219117): Enable more tests on desktop Android.
-#if BUILDFLAG(ENABLE_EXTENSIONS)
 TEST(ExtensionDetermineDownloadFilenameInternal,
      ExtensionDetermineDownloadFilenameInternal) {
   std::string winner_id;
@@ -4638,6 +4663,5 @@
             warnings.begin()->warning_type());
   EXPECT_EQ("incumbent", warnings.begin()->extension_id());
 }
-#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index c0a50bb..ebb7a16 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -6156,6 +6156,93 @@
   WaitForPreflightResponse();
 }
 
+// Tests that an extension can successfully use 'extraHeaders' and
+// 'declarativeNetRequest' (with header-dependent rules) while handling
+// 'onAuthRequired' for a CORS preflight request.
+// Regression test for crbug.com/444248440.
+IN_PROC_BROWSER_TEST_P(ProxyCORSWebRequestApiTestWithContextTypeMv3,
+                       PreflightOnAuthRequiredWithExtraHeadersDNR) {
+  static constexpr char kManifest[] = R"({
+    "name": "MV3 CORS Preflight webRequest.OnAuthRequired extraHeaders DNR",
+    "version": "0.1",
+    "manifest_version": 3,
+    "permissions": [
+      "webRequest",
+      "webRequestAuthProvider",
+      "declarativeNetRequest"
+    ],
+    "host_permissions": [ "http://127.0.0.1/*", "http://cors.test/*" ],
+    "background": { "service_worker": "background.js" },
+    "declarative_net_request": {
+      "rule_resources": [{
+        "id": "ruleset_1",
+        "enabled": true,
+        "path": "rules.json"
+      }]
+    }
+  })";
+
+  static constexpr char kBackgroundJs[] =
+      R"(chrome.webRequest.onAuthRequired.addListener(details => {
+             const authCredentials = { username: '%s', password: '%s' };
+             setTimeout(() => {
+               chrome.test.succeed();
+             }, 0);
+             return {authCredentials};
+           },
+           { urls: ['<all_urls>'] },
+           // 'extraHeaders' is necessary to hit the critical path.
+           ['blocking', 'extraHeaders']);)";
+
+  // Use a DNR rule that depends on response headers. By including
+  // 'responseHeaders' in the condition, the rule cannot be evaluated until
+  // headers are received.
+  // This ensures `RulesetManager::HasRulesets(kOnHeadersReceived)` returns
+  // true, forcing the call to `EvaluateRequestWithHeaders`.
+  static constexpr char kRulesJson[] = R"([
+    {
+      "id": 1,
+      "priority": 1,
+      "action": { "type": "block" },
+      "condition": {
+        "urlFilter": "*",
+        "responseHeaders": [{"header": "header-that-forces-evaluation"}]
+      }
+    }
+  ])";
+
+  TestExtensionDir test_dir;
+  test_dir.WriteManifest(kManifest);
+  test_dir.WriteFile(
+      FILE_PATH_LITERAL("background.js"),
+      base::StringPrintf(kBackgroundJs, kCORSProxyUser, kCORSProxyPass));
+  test_dir.WriteFile(FILE_PATH_LITERAL("rules.json"), kRulesJson);
+
+  const Extension* extension = LoadExtension(test_dir.UnpackedPath());
+  ASSERT_TRUE(extension) << message_;
+
+  ResultCatcher result_catcher;
+  preflight_waiter_ = std::make_unique<base::RunLoop>();
+
+  ASSERT_TRUE(NavigateToURL(GetActiveWebContents(),
+                            embedded_test_server()->GetURL("/empty.html")));
+
+  // Send a CORS preflight request which requires proxy auth.
+  // This triggers the sequence:
+  //   - Preflight
+  //   - Auth Challenge
+  //   - HandleAuthRequest (with extraHeaders)
+  //   - HandleResponseOrRedirectHeaders
+  //   - WebRequestEventRouter::OnHeadersReceived
+  //   - RulesetManager::HasRulesets(kOnHeadersReceived) == true
+  //   - RulesetManager::EvaluateRequestWithHeaders(nullptr)
+  //   - Graceful handling of headers == nullptr.
+  ExecuteCorsPreflightedRequest();
+
+  EXPECT_TRUE(result_catcher.GetNextResult());
+  WaitForPreflightResponse();
+}
+
 // Depends on declarativeWebRequest. crbug.com/332512510.
 class ExtensionWebRequestApiFencedFrameTest
     : public ExtensionWebRequestApiTest {
diff --git a/chrome/browser/file_system_access/file_system_access_features.cc b/chrome/browser/file_system_access/file_system_access_features.cc
index 30476e4a..2cc7e5e 100644
--- a/chrome/browser/file_system_access/file_system_access_features.cc
+++ b/chrome/browser/file_system_access/file_system_access_features.cc
@@ -12,7 +12,7 @@
 // already has permissions, which can happen the destination path was once
 // granted permission for a different file that has since been removed.
 BASE_FEATURE(kFileSystemAccessMoveWithOverwrite,
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Enables persistent permissions for the File System Access API.
 BASE_FEATURE(kFileSystemAccessPersistentPermissions,
diff --git a/chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_user_bypass_browsertest.cc b/chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_user_bypass_browsertest.cc
index fc014156..1b248b7a 100644
--- a/chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_user_bypass_browsertest.cc
+++ b/chrome/browser/fingerprinting_protection/fingerprinting_protection_filter_user_bypass_browsertest.cc
@@ -107,9 +107,10 @@
 
   // Close normal browser and switch the test's browser instance to an incognito
   // instance.
-  Browser* incognito = CreateIncognitoBrowser(browser()->profile());
+  BrowserWindowInterface* incognito =
+      CreateIncognitoBrowser(browser()->profile());
   CloseBrowserSynchronously(browser());
-  SelectFirstBrowser();
+  SetBrowser(incognito);
   ASSERT_EQ(browser(), incognito);
 
   // TODO(https://crbug.com/358371545): Test console messaging for subframe
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 4d71ea1..e587a24 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -10344,6 +10344,11 @@
     "expiry_milestone": 145
   },
   {
+    "name": "vids-app-preinstall",
+    "owners": [ "alancutter@chromium.org", "cros-ca-eng@google.com" ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "view-transition-on-navigation",
     "owners": [ "khushalsagar@chromium.org", "vmpstr@chromium.org", "chrishtr@chromium.org" ],
     "expiry_milestone" : 130
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 7d93033..a106f98c 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4316,6 +4316,10 @@
     "Displays an updated UI for video picture-in-picture controls from its 2024"
     "UI update";
 
+const char kVidsAppPreinstallName[] = "Vids app preinstall";
+const char kVidsAppPreinstallDescription[] =
+    "Preinstalls the Vids app on ChromeOS.";
+
 const char kV8VmFutureName[] = "Future V8 VM features";
 const char kV8VmFutureDescription[] =
     "This enables upcoming and experimental V8 VM features. "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 9f9043a..2bf60e5 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2500,6 +2500,9 @@
 extern const char kGroupPromoPrototypeCpaDescription[];
 #endif  // BUILDFLAG(IS_ANDROID)
 
+extern const char kVidsAppPreinstallName[];
+extern const char kVidsAppPreinstallDescription[];
+
 extern const char kV8VmFutureName[];
 extern const char kV8VmFutureDescription[];
 
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 54cc9ea..49e2878 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -1613,10 +1613,6 @@
             newStringCachedFeatureParam(
                     EDGE_TO_EDGE_USE_BACKUP_NAVBAR_INSETS, "e2e_backup_navbar_insets_oem_list", "");
 
-    public static final BooleanCachedFeatureParam sEdgeToEdgeUseBackupNavbarInsetsUseTappable =
-            newBooleanCachedFeatureParam(
-                    EDGE_TO_EDGE_USE_BACKUP_NAVBAR_INSETS, "use_tappable_element", true);
-
     public static final BooleanCachedFeatureParam sEdgeToEdgeUseBackupNavbarInsetsUseGestures =
             newBooleanCachedFeatureParam(
                     EDGE_TO_EDGE_USE_BACKUP_NAVBAR_INSETS, "use_gesture_insets", false);
@@ -1795,7 +1791,6 @@
                     sEdgeToEdgeUseBackupNavbarInsetsOemList,
                     sEdgeToEdgeUseBackupNavbarInsetsOemMinVersions,
                     sEdgeToEdgeUseBackupNavbarInsetsUseGestures,
-                    sEdgeToEdgeUseBackupNavbarInsetsUseTappable,
                     sLoadNativeEarlyConcurrentLoad,
                     sMagicStackAndroidShowAllModules,
                     sMaliciousApkDownloadCheckTelemetryOnly,
diff --git a/chrome/browser/glic/browser_ui/glic_border_view.cc b/chrome/browser/glic/browser_ui/glic_border_view.cc
index acae757..8579137 100644
--- a/chrome/browser/glic/browser_ui/glic_border_view.cc
+++ b/chrome/browser/glic/browser_ui/glic_border_view.cc
@@ -289,10 +289,21 @@
   }
 
   bool ShouldShowBorderAnimation() {
-    if (!context_access_indicator_enabled_ ||
-        !glic_focused_contents_in_current_view_) {
+    if (!glic_focused_contents_in_current_view_) {
       return false;
     }
+
+    // For multi-instance we rely on the sharing manager signal for everything
+    // else.
+    if (base::FeatureList::IsEnabled(features::kGlicMultiInstance)) {
+      return true;
+    }
+
+    // Remaining single instance checks.
+    if (!context_access_indicator_enabled_) {
+      return false;
+    }
+
     return IsGlicWindowShowing();
   }
 
diff --git a/chrome/browser/glic/service/glic_instance_impl.cc b/chrome/browser/glic/service/glic_instance_impl.cc
index 02a93c9..7568ffe5 100644
--- a/chrome/browser/glic/service/glic_instance_impl.cc
+++ b/chrome/browser/glic/service/glic_instance_impl.cc
@@ -9,6 +9,7 @@
 #include "base/functional/bind.h"
 #include "base/logging.h"
 #include "base/notimplemented.h"
+#include "base/task/sequenced_task_runner.h"
 #include "chrome/browser/contextual_cueing/contextual_cueing_service.h"
 #include "chrome/browser/contextual_cueing/contextual_cueing_service_factory.h"
 #include "chrome/browser/glic/fre/glic_fre_controller.h"
@@ -28,11 +29,13 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/common/actor_webui.mojom.h"
 #include "components/tabs/public/tab_interface.h"
+#include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "mojo/public/cpp/bindings/callback_helpers.h"
 #include "third_party/abseil-cpp/absl/functional/overload.h"
@@ -75,8 +78,7 @@
         content::WebContents::FromRenderFrameHost(source_render_frame_host));
     auto* glic_embedder = instance_->GetEmbedderForTab(source_tab);
 
-    // Ensure the previous side panel was active. If so, then deactivate it and
-    // open it in the new tab.
+    // Only bind if the previous instance was active.
     if (glic_embedder && glic_embedder->IsShowing()) {
       instance_->Show(GlicInstanceImpl::EmbedderType::kSidePanel, tab_to_bind);
     }
@@ -148,7 +150,14 @@
     embedder_to_show = GetActiveEmbedder();
   } else {
     DeactivateCurrentEmbedder();
-    embedder_to_show = CreateActiveEmbedderFor(new_key);
+    if (type == EmbedderType::kSidePanel) {
+      embedder_to_show = CreateActiveEmbedderForSidePanel(tab);
+    } else {
+      embedder_to_show =
+          CreateActiveEmbedderForFloaty(tab->GetBrowserWindowInterface());
+    }
+    CHECK(embedder_to_show);
+    host_.SetDelegate(embedder_to_show->GetHostEmbedderDelegate());
     SetActiveEmbedderAndNotifyStateChange(new_key);
   }
 
@@ -156,6 +165,10 @@
   embedder_to_show->Show();
 }
 
+void GlicInstanceImpl::Detach(tabs::TabInterface* tab) {
+  Show(EmbedderType::kFloating, tab);
+}
+
 void GlicInstanceImpl::Close(EmbedderType type, tabs::TabInterface* tab) {
   EmbedderKey key = GetEmbedderKey(type, tab);
   auto* embedder = GetEmbedderForKey(key);
@@ -300,10 +313,7 @@
 }
 
 void GlicInstanceImpl::UnbindTab(tabs::TabInterface* tab) {
-  if (active_embedder_key_.has_value() &&
-      active_embedder_key_.value() == EmbedderKey(tab)) {
-    DeactivateCurrentEmbedder();
-  }
+  MaybeDeactivateEmbedderAndCloseHostUi(EmbedderKey(tab));
   embedders_.erase(EmbedderKey(tab));
 }
 
@@ -446,28 +456,21 @@
   ClearActiveEmbedderAndNotifyStateChange();
 }
 
-GlicUiEmbedder* GlicInstanceImpl::CreateActiveEmbedderFor(
-    const EmbedderKey& key) {
-  GlicUiEmbedder* embedder_ptr = nullptr;
-  std::visit(absl::Overload{
-                 [&](FloatingEmbedderKey) {
-                   auto [entry_iter, _] = embedders_.try_emplace(key);
-                   entry_iter->second.embedder =
-                       std::make_unique<GlicFloatingUi>(profile_, *this);
-                   embedder_ptr = entry_iter->second.embedder.get();
-                 },
-                 [&](tabs::TabInterface* tab) {
-                   auto& entry = BindTab(tab);
-                   entry.embedder = std::make_unique<GlicSidePanelUi>(
-                       profile_, tab->GetWeakPtr(), *this);
-                   embedder_ptr = entry.embedder.get();
-                 },
-             },
-             key);
+GlicUiEmbedder* GlicInstanceImpl::CreateActiveEmbedderForSidePanel(
+    tabs::TabInterface* tab) {
+  auto& entry = BindTab(tab);
+  entry.embedder =
+      std::make_unique<GlicSidePanelUi>(profile_, tab->GetWeakPtr(), *this);
+  return entry.embedder.get();
+}
 
-  CHECK(embedder_ptr);
-  host_.SetDelegate(embedder_ptr->GetHostEmbedderDelegate());
-  return embedder_ptr;
+GlicUiEmbedder* GlicInstanceImpl::CreateActiveEmbedderForFloaty(
+    BrowserWindowInterface* browser) {
+  GlicInstanceImpl::EmbedderKey key = FloatingEmbedderKey();
+  auto [entry_iter, _] = embedders_.try_emplace(key);
+  entry_iter->second.embedder =
+      std::make_unique<GlicFloatingUi>(profile_, browser, *this);
+  return entry_iter->second.embedder.get();
 }
 
 void GlicInstanceImpl::ShowInactiveSidePanelEmbedderFor(
@@ -515,10 +518,6 @@
                       std::move(options));
 }
 
-void GlicInstanceImpl::Detach() {
-  Show(EmbedderType::kFloating, nullptr);
-}
-
 void GlicInstanceImpl::OnBoundTabDestroyed(tabs::TabInterface* tab,
                                            const InstanceId& instance_id) {
   UnbindTab(tab);
@@ -555,6 +554,16 @@
     // TODO: Figure out what else should go into host_.PanelWasClosed() and
     // maybe call it here.
     DeactivateCurrentEmbedder();
+    // Post a task to maybe activate another embedder. This is to avoid a race
+    // condition where the deactivation of an old embedder (e.g. during a tab
+    // switch) tries to show the new embedder before the browser's own tab
+    // activation logic has had a chance to run. By posting, we allow the
+    // synchronous activation logic to complete, and then this task will run
+    // and activate a foreground embedder only if one isn't already active.
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE,
+        base::BindOnce(&GlicInstanceImpl::MaybeActivateForegroundEmbedder,
+                       weak_ptr_factory_.GetWeakPtr()));
   }
 }
 
@@ -619,4 +628,20 @@
   return panel_state;
 }
 
+// If no embedder is active, finds an embedder associated with an active
+// tab and activates it. Note: The order is not guaranteed to be MRU.
+void GlicInstanceImpl::MaybeActivateForegroundEmbedder() {
+  if (active_embedder_key_.has_value()) {
+    return;
+  }
+  for (auto const& [key, entry] : embedders_) {
+    if (auto* tab = std::get_if<tabs::TabInterface*>(&key)) {
+      if (entry.embedder->IsShowing()) {
+        Show(EmbedderType::kSidePanel, *tab);
+        return;
+      }
+    }
+  }
+}
+
 }  // namespace glic
diff --git a/chrome/browser/glic/service/glic_instance_impl.h b/chrome/browser/glic/service/glic_instance_impl.h
index bb4c838..f241eba 100644
--- a/chrome/browser/glic/service/glic_instance_impl.h
+++ b/chrome/browser/glic/service/glic_instance_impl.h
@@ -99,8 +99,6 @@
   std::optional<std::string> conversation_id() const;
   base::CallbackListSubscription RegisterStateChange(
       StateChangeCallback callback) override;
-  // Opens the floating UI for this instance
-  void Detach() override;
 
   // Host::InstanceDelegate:
   void CreateTab(
@@ -148,6 +146,8 @@
   void WillCloseFor(tabs::TabInterface* tab) override;
   void Attach(tabs::TabInterface* tab) override;
   void NotifyPanelStateChanged() override;
+  // Opens the floating UI for this instance
+  void Detach(tabs::TabInterface* tab) override;
 
   // Host::InstanceInterface:
   mojom::PanelState GetPanelState() override;
@@ -191,7 +191,9 @@
   GlicUiEmbedder* GetActiveEmbedder();
   GlicUiEmbedder* GetEmbedderForKey(EmbedderKey key);
   void DeactivateCurrentEmbedder();
-  GlicUiEmbedder* CreateActiveEmbedderFor(const EmbedderKey& key);
+  GlicUiEmbedder* CreateActiveEmbedderForSidePanel(tabs::TabInterface* tab);
+  GlicUiEmbedder* CreateActiveEmbedderForFloaty(
+      BrowserWindowInterface* browser);
   void ShowInactiveSidePanelEmbedderFor(tabs::TabInterface* tab);
   void SetActiveEmbedderAndNotifyStateChange(
       std::optional<EmbedderKey> new_key);
@@ -207,6 +209,8 @@
           callback,
       std::vector<std::string> returned_suggestions);
   void MaybeDeactivateEmbedderAndCloseHostUi(EmbedderKey key);
+
+  void MaybeActivateForegroundEmbedder();
   EmbedderEntry& BindTab(tabs::TabInterface* tab);
 
   using StateChangeCallbackList =
diff --git a/chrome/browser/glic/service/glic_ui_embedder.h b/chrome/browser/glic/service/glic_ui_embedder.h
index a87a862..a32d0f8 100644
--- a/chrome/browser/glic/service/glic_ui_embedder.h
+++ b/chrome/browser/glic/service/glic_ui_embedder.h
@@ -29,7 +29,7 @@
     virtual void WillCloseFor(tabs::TabInterface* tab) = 0;
     virtual Host& host() = 0;
     virtual void Attach(tabs::TabInterface* tab) = 0;
-    virtual void Detach() = 0;
+    virtual void Detach(tabs::TabInterface* tab) = 0;
     // Called after the value of GetPanelState() changes.
     virtual void NotifyPanelStateChanged() = 0;
   };
diff --git a/chrome/browser/glic/widget/glic_floating_ui.cc b/chrome/browser/glic/widget/glic_floating_ui.cc
index 2f5acd5..26923c5 100644
--- a/chrome/browser/glic/widget/glic_floating_ui.cc
+++ b/chrome/browser/glic/widget/glic_floating_ui.cc
@@ -12,20 +12,32 @@
 #include "chrome/browser/glic/widget/glic_view.h"
 #include "chrome/browser/glic/widget/glic_widget.h"
 #include "chrome/browser/glic/widget/glic_window_animator.h"
-
-namespace {
-
-// constexpr static int kDraggableAreaHeight = 44;
-
-}  // namespace
+#include "chrome/common/chrome_features.h"
 
 namespace glic {
 
+// static
+gfx::Size GlicFloatingUi::GetDefaultSize() {
+  return {features::kGlicMultiInstanceFloatyWidth.Get(),
+          features::kGlicMultiInstanceFloatyHeight.Get()};
+}
+
+// end static
+
 GlicFloatingUi::GlicFloatingUi(Profile* profile,
+                               BrowserWindowInterface* browser,
+                               GlicUiEmbedder::Delegate& delegate)
+    : GlicFloatingUi(
+          profile,
+          GlicWidget::GetInitialBounds(browser,
+                                       GlicFloatingUi::GetDefaultSize()),
+          delegate) {}
+
+GlicFloatingUi::GlicFloatingUi(Profile* profile,
+                               gfx::Rect initial_bounds,
                                GlicUiEmbedder::Delegate& delegate)
     : profile_(profile), delegate_(delegate) {
-  LOG(ERROR) << "tnp: Floating UI created";
-  CreateAndSetupWidget();
+  CreateAndSetupWidget(initial_bounds);
   panel_state_.kind = mojom::PanelState_Kind::kDetached;
 }
 
@@ -39,10 +51,6 @@
   return panel_state_;
 }
 
-GlicWindowAnimator* GlicFloatingUi::window_animator() {
-  return glic_window_animator_.get();
-}
-
 GlicWidget* GlicFloatingUi::GetGlicWidget() const {
   return glic_widget_.get();
 }
@@ -54,9 +62,8 @@
   return nullptr;
 }
 
-void GlicFloatingUi::CreateAndSetupWidget() {
-  glic_widget_ =
-      GlicWidget::Create(profile_, gfx::Rect(10, 10, 400, 400), nullptr, true);
+void GlicFloatingUi::CreateAndSetupWidget(gfx::Rect initial_bounds) {
+  glic_widget_ = GlicWidget::Create(profile_, initial_bounds, nullptr, true);
   // TODO: Setup Hotkeys and AccessibilityText
 
   GetGlicWidget()->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
@@ -73,13 +80,11 @@
 void GlicFloatingUi::Resize(const gfx::Size& size,
                             base::TimeDelta duration,
                             base::OnceClosure callback) {
-  glic_size_ = size;
-
   // TODO: Don't animate while the user is manually resizing the widget.
   if (glic_window_animator_ && IsShowing()) {
     glic_window_animator_->AnimateSize(
-        GlicWidget::GetLastRequestedSizeClamped(GetGlicWidget(), glic_size_),
-        duration, std::move(callback));
+        GlicWidget::ClampSize(size, GetGlicWidget()), duration,
+        std::move(callback));
   } else {
     base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE, std::move(callback));
@@ -93,21 +98,6 @@
   }
 }
 
-// void GlicFloatingUi::SetDraggingAreasAndWatchForMouseEvents() {
-//   if (window_event_observer_) {
-//     return;
-//   }
-
-//   window_event_observer_ =
-//       std::make_unique<WindowEventObserver>(this, GetGlicView());
-
-//   if (!draggable_area_) {
-//     // Set the draggable area to the top bar of the window.
-//     GetGlicView()->SetDraggableAreas(
-//         {{0, 0, GetGlicView()->width(), kDraggableAreaHeight}});
-//   }
-// }
-
 void GlicFloatingUi::EnableDragResize(bool enabled) {
   NOTIMPLEMENTED();
 }
@@ -130,7 +120,6 @@
 }
 
 void GlicFloatingUi::Show() {
-  LOG(ERROR) << "tnp: Floating UI show";
   GetGlicWidget()->Show();
   GetGlicView()->SetWebContents(delegate_->host().webui_contents());
   GetGlicView()->UpdateBackgroundColor();
diff --git a/chrome/browser/glic/widget/glic_floating_ui.h b/chrome/browser/glic/widget/glic_floating_ui.h
index e722f90c..67fc84d 100644
--- a/chrome/browser/glic/widget/glic_floating_ui.h
+++ b/chrome/browser/glic/widget/glic_floating_ui.h
@@ -12,6 +12,8 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 
+class BrowserWindowInterface;
+
 namespace glic {
 
 class GlicWindowAnimator;
@@ -21,9 +23,16 @@
 // A stub implementation of GlicUiEmbedder for floating UIs.
 class GlicFloatingUi : public GlicUiEmbedder, public Host::EmbedderDelegate {
  public:
-  GlicFloatingUi(Profile* profile, GlicUiEmbedder::Delegate& delegate);
+  GlicFloatingUi(Profile* profile,
+                 BrowserWindowInterface* browser,
+                 GlicUiEmbedder::Delegate& delegate);
+  GlicFloatingUi(Profile* profile,
+                 gfx::Rect initial_bounds,
+                 GlicUiEmbedder::Delegate& delegate);
   ~GlicFloatingUi() override;
 
+  static gfx::Size GetDefaultSize();
+
   // GlicUiEmbedder:
   Host::EmbedderDelegate* GetHostEmbedderDelegate() override;
   void Show() override;
@@ -49,12 +58,10 @@
       mojom::WebClientHandler::SwitchConversationCallback callback) override;
   void ClosePanel() override;
 
-  GlicWindowAnimator* window_animator();
-
  private:
   GlicWidget* GetGlicWidget() const;
   GlicView* GetGlicView() const;
-  void CreateAndSetupWidget();
+  void CreateAndSetupWidget(gfx::Rect initial_bounds);
   // void SetDraggingAreasAndWatchForMouseEvents();
 
   // Used to monitor key and mouse events from native window.
@@ -63,7 +70,6 @@
 
   std::unique_ptr<GlicWindowAnimator> glic_window_animator_;
   std::unique_ptr<GlicWidget> glic_widget_;
-  std::optional<gfx::Size> glic_size_;
   mojom::PanelState panel_state_;
 
   raw_ptr<Profile> profile_;
diff --git a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
index b51f596..b4be3f1 100644
--- a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
+++ b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.cc
@@ -28,7 +28,6 @@
   // Using `new` to access a private constructor.
   auto inactive_side_panel =
       base::WrapUnique(new GlicInactiveSidePanelUi(tab, delegate));
-  inactive_side_panel->VisibilityChanged(/*visible=*/true);
 
   // Capture screenshot asynchronously and update the inactive panel.
   inactive_side_panel->inactive_view_controller_.CaptureScreenshot(
@@ -57,18 +56,11 @@
     base::WeakPtr<tabs::TabInterface> tab,
     GlicUiEmbedder::Delegate& delegate)
     : tab_(tab), delegate_(delegate) {
-  if (!tab_ || !tab_->GetTabFeatures()) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
     return;
   }
 
-  auto* glic_side_panel_coordinator =
-      tab_->GetTabFeatures()->glic_side_panel_coordinator();
-
-  panel_visibility_subscription_ =
-      glic_side_panel_coordinator->AddVisibilityCallback(
-          base::BindRepeating(&GlicInactiveSidePanelUi::VisibilityChanged,
-                              weak_ptr_factory_.GetWeakPtr()));
-
   auto view = inactive_view_controller_.CreateView();
   scoped_view_observation_.Observe(view.get());
   glic_side_panel_coordinator->SetContentsView(std::move(view));
@@ -96,24 +88,27 @@
 }
 
 bool GlicInactiveSidePanelUi::IsShowing() const {
-  return is_showing_;
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
+    return false;
+  }
+  return glic_side_panel_coordinator->IsShowing();
 }
 
 void GlicInactiveSidePanelUi::Show() {
-  if (!tab_ || !tab_->GetTabFeatures()) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
     return;
   }
-  SidePanelRegistry* registry = tab_->GetTabFeatures()->side_panel_registry();
-  SidePanelEntry* glic_entry =
-      registry->GetEntryForKey(SidePanelEntry::Key(SidePanelEntry::Id::kGlic));
-  if (glic_entry) {
-    registry->SetActiveEntry(glic_entry);
-  }
+  glic_side_panel_coordinator->Show();
 }
 
 void GlicInactiveSidePanelUi::Close() {
-  // TODO: implement close.
-  NOTIMPLEMENTED();
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
+    return;
+  }
+  glic_side_panel_coordinator->Close();
 }
 
 views::View* GlicInactiveSidePanelUi::GetView() {
@@ -135,8 +130,12 @@
   NOTREACHED() << "The embedder is already inactive.";
 }
 
-void GlicInactiveSidePanelUi::VisibilityChanged(bool visible) {
-  is_showing_ = visible;
+GlicSidePanelCoordinator* GlicInactiveSidePanelUi::GetGlicSidePanelCoordinator()
+    const {
+  if (!tab_ || !tab_->GetTabFeatures()) {
+    return nullptr;
+  }
+  return tab_->GetTabFeatures()->glic_side_panel_coordinator();
 }
 
 }  // namespace glic
diff --git a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
index fdd4042..3fc85dd 100644
--- a/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
+++ b/chrome/browser/glic/widget/glic_inactive_side_panel_ui.h
@@ -53,21 +53,18 @@
   void OnViewFocused(views::View* observed_view) override;
   void OnViewIsDeleting(views::View* observed_view) override;
 
-  void VisibilityChanged(bool visible);
-
  private:
   explicit GlicInactiveSidePanelUi(base::WeakPtr<tabs::TabInterface> tab,
                                    GlicUiEmbedder::Delegate& delegate);
+  GlicSidePanelCoordinator* GetGlicSidePanelCoordinator() const;
 
   InactiveViewController inactive_view_controller_;
   base::WeakPtr<tabs::TabInterface> tab_;
   raw_ref<GlicUiEmbedder::Delegate> delegate_;
-  bool is_showing_ = false;
 
   base::ScopedObservation<views::View, views::ViewObserver>
       scoped_view_observation_{this};
 
-  base::CallbackListSubscription panel_visibility_subscription_;
   base::WeakPtrFactory<GlicInactiveSidePanelUi> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/glic/widget/glic_side_panel_ui.cc b/chrome/browser/glic/widget/glic_side_panel_ui.cc
index 7337ded..4c291c1 100644
--- a/chrome/browser/glic/widget/glic_side_panel_ui.cc
+++ b/chrome/browser/glic/widget/glic_side_panel_ui.cc
@@ -27,15 +27,15 @@
                                  base::WeakPtr<tabs::TabInterface> tab,
                                  GlicUiEmbedder::Delegate& delegate)
     : profile_(profile), tab_(tab), delegate_(delegate) {
-  if (!tab_ || !tab_->GetTabFeatures()) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
     return;
   }
-  auto* glic_side_panel_coordinator =
-      tab_->GetTabFeatures()->glic_side_panel_coordinator();
 
   panel_visibility_subscription_ =
-      glic_side_panel_coordinator->AddVisibilityCallback(base::BindRepeating(
-          &GlicSidePanelUi::VisibilityChanged, weak_ptr_factory_.GetWeakPtr()));
+      glic_side_panel_coordinator->AddStateCallback(
+          base::BindRepeating(&GlicSidePanelUi::SidePanelStateChanged,
+                              weak_ptr_factory_.GetWeakPtr()));
 
   glic_side_panel_coordinator->SetContentsView(CreateView(profile_));
   panel_state_.kind = mojom::PanelState_Kind::kAttached;
@@ -81,7 +81,10 @@
 }
 
 void GlicSidePanelUi::Detach() {
-  delegate_->Detach();
+  if (!tab_) {
+    return;
+  }
+  delegate_->Detach(tab_.get());
 }
 
 void GlicSidePanelUi::SetMinimumWidgetSize(const gfx::Size& size) {
@@ -89,11 +92,11 @@
 }
 
 bool GlicSidePanelUi::IsShowing() const {
-  if (!tab_) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
     return false;
   }
-  // If this embedder is active, side panel must be showing.
-  return true;
+  return glic_side_panel_coordinator->IsShowing();
 }
 
 void GlicSidePanelUi::Focus() {
@@ -103,10 +106,11 @@
   }
 }
 
-void GlicSidePanelUi::VisibilityChanged(bool visible) {
+void GlicSidePanelUi::SidePanelStateChanged(
+    GlicSidePanelCoordinator::State state) {
   // Showing only happens through glic entrypoint, hiding can also be triggered
   // by side panel coordinator when replacing glic with another entry.
-  if (!visible && tab_) {
+  if (state != GlicSidePanelCoordinator::State::kShown && tab_) {
     delegate_->WillCloseFor(tab_.get());
   }
 }
@@ -119,26 +123,24 @@
 }
 
 void GlicSidePanelUi::Show() {
-  if (!tab_) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator) {
     return;
   }
   panel_state_.kind = mojom::PanelState_Kind::kAttached;
   delegate_->NotifyPanelStateChanged();
-  auto* side_panel_coordinator =
-      tab_->GetBrowserWindowInterface()->GetFeatures().side_panel_coordinator();
-  side_panel_coordinator->Show(SidePanelEntry::Id::kGlic);
+  glic_side_panel_coordinator->Show();
   Focus();
 }
 
 void GlicSidePanelUi::Close() {
-  if (!tab_ || !IsShowing()) {
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  if (!glic_side_panel_coordinator || !IsShowing()) {
     return;
   }
   panel_state_.kind = mojom::PanelState_Kind::kHidden;
   delegate_->NotifyPanelStateChanged();
-  auto* side_panel_coordinator =
-      tab_->GetBrowserWindowInterface()->GetFeatures().side_panel_coordinator();
-  side_panel_coordinator->Close();
+  glic_side_panel_coordinator->Close();
 }
 
 void GlicSidePanelUi::ClosePanel() {
@@ -152,8 +154,16 @@
 }
 
 views::View* GlicSidePanelUi::GetView() {
-  return tab_ ? tab_->GetTabFeatures()->glic_side_panel_coordinator()->GetView()
-              : nullptr;
+  auto* glic_side_panel_coordinator = GetGlicSidePanelCoordinator();
+  return glic_side_panel_coordinator ? glic_side_panel_coordinator->GetView()
+                                     : nullptr;
+}
+
+GlicSidePanelCoordinator* GlicSidePanelUi::GetGlicSidePanelCoordinator() const {
+  if (!tab_ || !tab_->GetTabFeatures()) {
+    return nullptr;
+  }
+  return tab_->GetTabFeatures()->glic_side_panel_coordinator();
 }
 
 }  // namespace glic
diff --git a/chrome/browser/glic/widget/glic_side_panel_ui.h b/chrome/browser/glic/widget/glic_side_panel_ui.h
index 52ede2d..9027a45 100644
--- a/chrome/browser/glic/widget/glic_side_panel_ui.h
+++ b/chrome/browser/glic/widget/glic_side_panel_ui.h
@@ -60,9 +60,10 @@
   bool IsShowing() const override;
   void ClosePanel() override;
 
-  void VisibilityChanged(bool visible);
+  void SidePanelStateChanged(GlicSidePanelCoordinator::State state);
 
  private:
+  GlicSidePanelCoordinator* GetGlicSidePanelCoordinator() const;
   base::CallbackListSubscription panel_visibility_subscription_;
   std::unique_ptr<views::View> CreateView(Profile* profile);
   mojom::PanelState panel_state_;
diff --git a/chrome/browser/glic/widget/glic_widget.cc b/chrome/browser/glic/widget/glic_widget.cc
index 7c7854c..3bcaa2d 100644
--- a/chrome/browser/glic/widget/glic_widget.cc
+++ b/chrome/browser/glic/widget/glic_widget.cc
@@ -9,15 +9,24 @@
 #include "chrome/browser/shell_integration_linux.h"
 #include "chrome/browser/themes/theme_service.h"
 #include "chrome/browser/themes/theme_service_factory.h"
+#include "chrome/browser/ui/browser_element_identifiers.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/views/chrome_widget_sublevel.h"
+#include "chrome/browser/ui/views/interaction/browser_elements_views.h"
+#include "chrome/browser/ui/views/tabs/glic_button.h"
 #include "chrome/common/chrome_features.h"
+#include "ui/base/base_window.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/color/color_provider_key.h"
+#include "ui/display/display.h"
+#include "ui/display/display_finder.h"
 #include "ui/display/screen.h"
 #include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/outsets.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/views/widget/native_widget.h"
+#include "ui/views/widget/widget.h"
 #include "ui/views/widget/widget_delegate.h"
 
 #if BUILDFLAG(IS_OZONE)
@@ -39,6 +48,7 @@
 
 constexpr float kGlicWidgetCornerRadius = 12;
 constexpr int kMaxWidgetSize = 16'384;
+constexpr int kInitialPositionBuffer = 4;
 
 // For resizeable windows, there may be an invisible border which affects the
 // widget size. Given a target rect, this method provides the outsets which
@@ -81,6 +91,58 @@
                          : views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
 }
 
+display::Display GetDisplayForOpeningDetached() {
+  // Get the Display for the most recently active browser. If there was no
+  // recently active browser, use the primary display.
+  BrowserWindowInterface* const bwi =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
+  ui::BaseWindow* const window = bwi ? bwi->GetWindow() : nullptr;
+  if (window) {
+    const std::optional<display::Display> widget_display =
+        views::Widget::GetWidgetForNativeWindow(window->GetNativeWindow())
+            ->GetNearestDisplay();
+    if (widget_display) {
+      return *widget_display;
+    }
+  }
+  return display::Screen::Get()->GetPrimaryDisplay();
+}
+
+std::optional<gfx::Rect> GetInitialDetachedBoundsFromBrowser(
+    BrowserWindowInterface* browser,
+    const gfx::Size& target_size) {
+  if (!browser) {
+    return std::nullopt;
+  }
+
+  // Set the origin so the top right of the glic widget meets the bottom left
+  // of the glic button.
+  GlicButton* glic_button = GlicButton::FromBrowser(browser);
+  if (!glic_button) {
+    return std::nullopt;
+  }
+  gfx::Rect glic_button_inset_bounds = glic_button->GetBoundsWithInset();
+
+  gfx::Point origin(glic_button_inset_bounds.x() - target_size.width() -
+                        kInitialPositionBuffer,
+                    glic_button_inset_bounds.bottom() + kInitialPositionBuffer);
+  gfx::Rect bounds = {origin, target_size};
+
+  return GlicWidget::IsWidgetLocationAllowed(bounds)
+             ? std::make_optional(bounds)
+             : std::nullopt;
+}
+
+gfx::Rect GetInitialDetachedBoundsNoBrowser(const gfx::Size& target_size) {
+  // Get the default position offset equal distances from the top right corner
+  // of the work area (which excludes system UI such as the taskbar).
+  display::Display display = GetDisplayForOpeningDetached();
+  gfx::Point top_right = display.work_area().top_right();
+  int initial_x =
+      top_right.x() - target_size.width() - kDefaultDetachedTopRightDistance;
+  int initial_y = top_right.y() + kDefaultDetachedTopRightDistance;
+  return {{initial_x, initial_y}, target_size};
+}
 }  // namespace
 
 class GlicWidgetDelegate : public views::WidgetDelegate {
@@ -122,32 +184,64 @@
 
 GlicWidget::~GlicWidget() = default;
 
-// static
+// Static
 gfx::Size GlicWidget::GetInitialSize() {
   return {features::kGlicInitialWidth.Get(),
           features::kGlicInitialHeight.Get()};
 }
 
-// static
-gfx::Size GlicWidget::GetLastRequestedSizeClamped(
-    const GlicWidget* glic_widget,
-    std::optional<gfx::Size> glic_size) {
-  gfx::Size min = GlicWidget::GetInitialSize();
+gfx::Rect GlicWidget::GetInitialBounds(BrowserWindowInterface* browser,
+                                       gfx::Size target_size) {
+  std::optional<gfx::Rect> bounds_with_browser =
+      GetInitialDetachedBoundsFromBrowser(browser, target_size);
+  return bounds_with_browser.value_or(
+      GetInitialDetachedBoundsNoBrowser(target_size));
+}
+
+gfx::Size GlicWidget::ClampSize(std::optional<gfx::Size> current_size,
+                                const GlicWidget* glic_widget) {
+  gfx::Size min = GetInitialSize();
   if (glic_widget) {
     gfx::Size widget_min = glic_widget->GetMinimumSize();
     if (!widget_min.IsEmpty()) {
       min = widget_min;
     }
   }
-
   constexpr gfx::Size max(kMaxWidgetSize, kMaxWidgetSize);
-  gfx::Size result = glic_size.value_or(min);
 
-  result.SetToMax(min);
-  result.SetToMin(max);
-  return result;
+  gfx::Size clamped_size = current_size.value_or(min);
+  clamped_size.SetToMax(min);
+  clamped_size.SetToMin(max);
+  return clamped_size;
 }
 
+bool GlicWidget::IsWidgetLocationAllowed(const gfx::Rect& bounds) {
+  const std::vector<display::Display>& displays =
+      display::Screen::Get()->GetAllDisplays();
+
+  // Calculate inset corners to allow part of the widget to be off screen.
+  std::array<gfx::Point, 4> inset_points = {
+      // top-left: Allow 40% on left and |kInitialPositionBuffer| on top.
+      gfx::Point(bounds.x() + bounds.width() * .4,
+                 bounds.y() + kInitialPositionBuffer),
+      // top-right: Allow 40% on right and |kInitialPositionBuffer| on top.
+      gfx::Point(bounds.right() - bounds.width() * .4,
+                 bounds.y() + kInitialPositionBuffer),
+      // bottom-left: Allow 40% on left and 70% on bottom.
+      gfx::Point(bounds.x() + bounds.width() * .4,
+                 bounds.bottom() - bounds.height() * .7),
+      // bottom-right: Allow 40% on right and 70% on bottom.
+      gfx::Point(bounds.right() - bounds.width() * .4,
+                 bounds.bottom() - bounds.height() * .7),
+  };
+  // Check that all four points are on an existing display.
+  return std::ranges::all_of(inset_points, [&](gfx::Point p) {
+    return display::FindDisplayContainingPoint(displays, p) != displays.end();
+  });
+}
+
+// End Static
+
 std::unique_ptr<GlicWidget> GlicWidget::Create(
     Profile* profile,
     const gfx::Rect& initial_bounds,
diff --git a/chrome/browser/glic/widget/glic_widget.h b/chrome/browser/glic/widget/glic_widget.h
index 6b3e57b5..0d8988a5 100644
--- a/chrome/browser/glic/widget/glic_widget.h
+++ b/chrome/browser/glic/widget/glic_widget.h
@@ -18,7 +18,12 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/widget/widget.h"
 
+class BrowserWindowInterface;
+
 namespace glic {
+// Distance the detached window should be from the top and the right of the
+// display when opened unassociated to a browser.
+inline constexpr static int kDefaultDetachedTopRightDistance = 48;
 
 class GlicView;
 
@@ -31,8 +36,20 @@
   GlicWidget& operator=(const GlicWidget&) = delete;
   ~GlicWidget() override;
 
+  // Returns the initial size for the single instance floating window.
   static gfx::Size GetInitialSize();
 
+  static gfx::Rect GetInitialBounds(BrowserWindowInterface* browser,
+                                    gfx::Size target_size);
+
+  // Return `current_size` or the default minimum size if not provided.
+  // The return value is clamped to fit between the minimum and maximum sizes.
+  static gfx::Size ClampSize(std::optional<gfx::Size> current_size,
+                             const GlicWidget* glic_widget);
+
+  // True if |bounds| is an allowed position the Widget can be shown in.
+  static bool IsWidgetLocationAllowed(const gfx::Rect& bounds);
+
   // Create a widget with the given bounds.
   static std::unique_ptr<GlicWidget> Create(
       Profile* profile,
diff --git a/chrome/browser/glic/widget/glic_window_controller.h b/chrome/browser/glic/widget/glic_window_controller.h
index 2559cb3f..45ae556 100644
--- a/chrome/browser/glic/widget/glic_window_controller.h
+++ b/chrome/browser/glic/widget/glic_window_controller.h
@@ -43,10 +43,6 @@
 }
 
 namespace glic {
-// Distance the detached window should be from the top and the right of the
-// display when opened unassociated to a browser.
-inline constexpr static int kDefaultDetachedTopRightDistance = 48;
-
 DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kGlicWidgetAttached);
 
 class GlicWidget;
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.cc b/chrome/browser/glic/widget/glic_window_controller_impl.cc
index 80b6bd9b2..cae7ed35 100644
--- a/chrome/browser/glic/widget/glic_window_controller_impl.cc
+++ b/chrome/browser/glic/widget/glic_window_controller_impl.cc
@@ -89,7 +89,6 @@
 
 // Default value for adding a buffer to the attachment zone.
 constexpr static int kAttachmentBuffer = 20;
-constexpr static int kInitialPositionBuffer = 4;
 constexpr static int kDraggableAreaHeight = 44;
 
 constexpr static base::TimeDelta kAnimationDuration = base::Milliseconds(300);
@@ -108,55 +107,6 @@
   return panel_state;
 }
 
-GlicButton* GetGlicButton(BrowserWindowInterface& browser) {
-  return BrowserElementsViews::From(&browser)->GetViewAs<glic::GlicButton>(
-      kGlicButtonElementId);
-}
-
-display::Display GetDisplayForOpeningDetached() {
-  // Get the Display for the most recently active browser. If there was no
-  // recently active browser, use the primary display.
-  BrowserWindowInterface* const bwi =
-      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
-  ui::BaseWindow* const window = bwi ? bwi->GetWindow() : nullptr;
-  if (window) {
-    const std::optional<display::Display> widget_display =
-        views::Widget::GetWidgetForNativeWindow(window->GetNativeWindow())
-            ->GetNearestDisplay();
-    if (widget_display) {
-      return *widget_display;
-    }
-  }
-  return display::Screen::Get()->GetPrimaryDisplay();
-}
-
-// True if |bounds| is an allowed position the Widget can be shown in.
-bool IsWidgetLocationAllowed(const gfx::Rect& bounds) {
-  const std::vector<display::Display>& displays =
-      display::Screen::Get()->GetAllDisplays();
-
-  // Calculate inset corners to allow part of the widget to be off screen.
-  std::array<gfx::Point, 4> inset_points = {
-      // top-left: Allow 40% on left and |kInitialPositionBuffer| on top.
-      gfx::Point(bounds.x() + bounds.width() * .4,
-                 bounds.y() + kInitialPositionBuffer),
-      // top-right: Allow 40% on right and |kInitialPositionBuffer| on top.
-      gfx::Point(bounds.right() - bounds.width() * .4,
-                 bounds.y() + kInitialPositionBuffer),
-      // bottom-left: Allow 40% on left and 70% on bottom.
-      gfx::Point(bounds.x() + bounds.width() * .4,
-                 bounds.bottom() - bounds.height() * .7),
-      // bottom-right: Allow 40% on right and 70% on bottom.
-      gfx::Point(bounds.right() - bounds.width() * .4,
-                 bounds.bottom() - bounds.height() * .7),
-  };
-
-  // Check that all four points are on an existing display.
-  return std::ranges::all_of(inset_points, [&](gfx::Point p) {
-    return display::FindDisplayContainingPoint(displays, p) != displays.end();
-  });
-}
-
 std::optional<int> GetOptionalIntPreference(PrefService* prefs,
                                             std::string_view path) {
   const PrefService::Preference& pref =
@@ -807,12 +757,12 @@
 }
 
 gfx::Rect GlicWindowControllerImpl::GetInitialBounds(Browser* browser) {
-  gfx::Size target_size =
-      GlicWidget::GetLastRequestedSizeClamped(GetGlicWidget(), glic_size_);
+  gfx::Size target_size = GlicWidget::ClampSize(glic_size_, GetGlicWidget());
 
   // Reset previous position if it results in an invalid location.
   if (previous_position_.has_value() &&
-      !IsWidgetLocationAllowed({previous_position_.value(), target_size})) {
+      !GlicWidget::IsWidgetLocationAllowed(
+          {previous_position_.value(), target_size})) {
     previous_position_.reset();
   }
   // Use the previous position if there is one.
@@ -820,45 +770,7 @@
     return {previous_position_.value(), target_size};
   }
 
-  std::optional<gfx::Rect> bounds_with_browser =
-      GetInitialDetachedBoundsFromBrowser(browser, target_size);
-  return bounds_with_browser.value_or(
-      GetInitialDetachedBoundsNoBrowser(target_size));
-}
-
-gfx::Rect GlicWindowControllerImpl::GetInitialDetachedBoundsNoBrowser(
-    const gfx::Size& target_size) {
-  // Get the default position offset equal distances from the top right corner
-  // of the work area (which excludes system UI such as the taskbar).
-  display::Display display = GetDisplayForOpeningDetached();
-  gfx::Point top_right = display.work_area().top_right();
-  int initial_x =
-      top_right.x() - target_size.width() - kDefaultDetachedTopRightDistance;
-  int initial_y = top_right.y() + kDefaultDetachedTopRightDistance;
-  return {{initial_x, initial_y}, target_size};
-}
-
-std::optional<gfx::Rect>
-GlicWindowControllerImpl::GetInitialDetachedBoundsFromBrowser(
-    Browser* browser,
-    const gfx::Size& target_size) {
-  if (!browser) {
-    return std::nullopt;
-  }
-
-  // Set the origin so the top right of glic meets the bottom left of the glic
-  // button.
-  GlicButton* glic_button = GetGlicButton(*browser);
-  CHECK(glic_button);
-  gfx::Rect glic_button_inset_bounds = glic_button->GetBoundsWithInset();
-
-  gfx::Point origin(glic_button_inset_bounds.x() - target_size.width() -
-                        kInitialPositionBuffer,
-                    glic_button_inset_bounds.bottom() + kInitialPositionBuffer);
-  gfx::Rect bounds = {origin, target_size};
-
-  return IsWidgetLocationAllowed(bounds) ? std::make_optional(bounds)
-                                         : std::nullopt;
+  return GlicWidget::GetInitialBounds(browser, target_size);
 }
 
 void GlicWindowControllerImpl::MaybeResetPanelPostionOnShow(
@@ -1048,7 +960,7 @@
 
   // Trigger custom event for testing.
   views::ElementTrackerViews::GetInstance()->NotifyCustomEvent(
-      kGlicWidgetAttached, GetGlicButton(*browser));
+      kGlicWidgetAttached, GlicButton::FromBrowser(browser));
   AfterViewShown();
 }
 
@@ -1070,8 +982,8 @@
   // animate this transition.
   if (in_resizable_state && !user_resizing_) {
     glic_window_animator_->AnimateSize(
-        GlicWidget::GetLastRequestedSizeClamped(GetGlicWidget(), glic_size_),
-        duration, std::move(callback));
+        GlicWidget::ClampSize(glic_size_, GetGlicWidget()), duration,
+        std::move(callback));
   } else {
     // If the glic window is closed, or the widget isn't ready (e.g. because
     // it's currently still animating closed) immediately post the callback.
@@ -1380,7 +1292,7 @@
     scoped_glic_button_indicator_.reset();
     return;
   }
-  GlicButton* glic_button = GetGlicButton(*browser);
+  GlicButton* glic_button = GlicButton::FromBrowser(browser);
   // If there isn't an existing scoped indicator for this button, create one.
   if (!scoped_glic_button_indicator_ ||
       scoped_glic_button_indicator_->GetGlicButton() != glic_button) {
@@ -1561,8 +1473,7 @@
   if (!IsDetached()) {
     return;
   }
-  const auto target_size =
-      GlicWidget::GetLastRequestedSizeClamped(GetGlicWidget(), glic_size_);
+  const auto target_size = GlicWidget::ClampSize(glic_size_, GetGlicWidget());
   if (target_size != glic_window_animator_->GetCurrentTargetBounds().size()) {
     glic_window_animator_->AnimateSize(
         target_size, animate ? kAnimationDuration : base::Milliseconds(0),
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.h b/chrome/browser/glic/widget/glic_window_controller_impl.h
index 313d27d..0e40e3f 100644
--- a/chrome/browser/glic/widget/glic_window_controller_impl.h
+++ b/chrome/browser/glic/widget/glic_window_controller_impl.h
@@ -187,16 +187,6 @@
   // on the Mac, all special activation and visibility properties are cleared.
   void SetGlicWindowToFloatingMode(bool floating);
 
-  // Return the default detached bounds which are just below the tab strip
-  // button on the active browser.
-  std::optional<gfx::Rect> GetInitialDetachedBoundsFromBrowser(
-      Browser* browser,
-      const gfx::Size& target_size);
-
-  // Return the default detached bounds when there is no active browser. The
-  // position is relative to the top right of the current display.
-  gfx::Rect GetInitialDetachedBoundsNoBrowser(const gfx::Size& target_size);
-
   // Check if the panel position should be reset based on `window_config_`.
   // Update `window_config_` that the panel was shown.
   void MaybeResetPanelPostionOnShow(mojom::InvocationSource source);
diff --git a/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc b/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc
index 4b2f2fb..0fa6c6f6 100644
--- a/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc
+++ b/chrome/browser/new_tab_page/ntp_promo/ntp_promo_interactive_uitest.cc
@@ -50,6 +50,10 @@
 #include "ui/views/interaction/polling_view_observer.h"
 #include "url/gurl.h"
 
+#if BUILDFLAG(IS_MAC)
+#include "base/mac/mac_util.h"
+#endif  // BUILDFLAG(IS_MAC)
+
 namespace {
 
 using ntp_promo::mojom::ShowNtpPromosResult;
@@ -253,15 +257,6 @@
     }
   }
 
-  auto WaitForAndScrollToElement(
-      const ui::ElementIdentifier& ntp_id,
-      const WebContentsInteractionTestUtil::DeepQuery& query) {
-    auto steps = Steps(WaitForElementExists(ntp_id, query),
-                       ScrollIntoView(ntp_id, query));
-    AddDescriptionPrefix(steps, __func__);
-    return steps;
-  }
-
   auto GetActionButtonPath() const {
     return GetFirstPromoPath() + kActionIconId;
   }
@@ -271,7 +266,7 @@
   auto WaitForPromoIcon(std::string_view expected_icon) {
     const auto path = GetPromoIconPath();
     auto steps = Steps(
-        WaitForAndScrollToElement(kNtpElementId, path),
+        WaitForElementVisible(kNtpElementId, path),
         // Verify the icon shows the correct image.
         CheckJsResultAt(kNtpElementId, path, "el => el.icon", expected_icon));
     AddDescriptionPrefix(steps, __func__);
@@ -285,16 +280,14 @@
       case Eligibility::kEligible:
         steps += WaitForPromoIcon(std::string("ntp-promo:") +
                                   std::string(expected_icon));
-        steps +=
-            WaitForAndScrollToElement(kNtpElementId, GetActionButtonPath());
+        steps += WaitForElementVisible(kNtpElementId, GetActionButtonPath());
         break;
       case Eligibility::kCompleted:
         steps += WaitForPromoIcon("cr:check");
         if (GetParam().promo_type == NtpBrowserPromoType::kSimple) {
-          steps += EnsureNotPresent(kNtpElementId, GetActionButtonPath());
+          steps += EnsureNotVisible(kNtpElementId, GetActionButtonPath());
         } else {
-          steps +=
-              WaitForAndScrollToElement(kNtpElementId, GetActionButtonPath());
+          steps += WaitForElementVisible(kNtpElementId, GetActionButtonPath());
         }
         break;
       case Eligibility::kIneligible:
@@ -381,6 +374,13 @@
     });
 
 IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, TestPromoEligible) {
+  // TODO(crbug.com/445214951): Flaky on mac-vm builder for macOS 15.
+#if BUILDFLAG(IS_MAC)
+  if (base::mac::MacOSMajorVersion() == 15 && base::mac::IsVirtualMachine()) {
+    GTEST_SKIP() << "Disabled on macOS Sequoia for virtual machines.";
+  }
+#endif  // BUILDFLAG(IS_MAC)
+
   InstallTestPromo(Eligibility::kEligible);
   RunTestSequence(
       InstrumentTab(kNtpElementId),
@@ -403,7 +403,13 @@
       CheckShowMetrics(ShowNtpPromosResult::kShown));
 }
 
-IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, TestPromoCompleted) {
+// TODO(crbug.com/448993914): Re-enable this test
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_TestPromoCompleted DISABLED_TestPromoCompleted
+#else
+#define MAYBE_TestPromoCompleted TestPromoCompleted
+#endif
+IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, MAYBE_TestPromoCompleted) {
   InstallTestPromo(Eligibility::kCompleted);
   RunTestSequence(
       InstrumentTab(kNtpElementId),
@@ -415,7 +421,7 @@
           Then(WaitForPromoVisible(Eligibility::kCompleted, kSignInIconName),
                VerifyTestPromoText(),
                CheckShowMetrics(ShowNtpPromosResult::kShown)),
-          Else(EnsureNotPresent(kNtpElementId, GetFirstPromoPath()),
+          Else(EnsureNotVisible(kNtpElementId, GetFirstPromoPath()),
                CheckShowMetrics(ShowNtpPromosResult::kNotShownNoPromos))));
 }
 
@@ -449,8 +455,8 @@
   InstallTestPromo(Eligibility::kEligible);
   RunTestSequence(InstrumentTab(kNtpElementId),
                   NavigateWebContents(kNtpElementId, GURL(kNtpURL)),
-                  WaitForAndScrollToElement(kNtpElementId, kPathToModules),
-                  EnsureNotPresent(kNtpElementId, GetFirstPromoPath()),
+                  WaitForElementVisible(kNtpElementId, kPathToModules),
+                  EnsureNotVisible(kNtpElementId, GetFirstPromoPath()),
                   CheckShowMetrics(ShowNtpPromosResult::kNotShownDueToPolicy));
 }
 
@@ -466,7 +472,7 @@
   InstallTestPromo(Eligibility::kEligible);
   RunTestSequence(InstrumentTab(kNtpElementId),
                   NavigateWebContents(kNtpElementId, GURL(kNtpURL)),
-                  WaitForAndScrollToElement(kNtpElementId, GetFirstPromoPath()),
+                  WaitForElementVisible(kNtpElementId, GetFirstPromoPath()),
                   EnsureNotVisible(kNtpElementId, kPathToModules),
                   CheckShowMetrics(ShowNtpPromosResult::kShown));
 }
@@ -476,7 +482,14 @@
 // or run these tests on ChromeOS.
 #if !BUILDFLAG(IS_CHROMEOS)
 
-IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, SigninPromoAppearsAndIsClickable) {
+// TODO(crbug.com/448993914): Re-enable this test
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_SigninPromoAppearsAndIsClickable \
+  DISABLED_SigninPromoAppearsAndIsClickable
+#else
+#define MAYBE_SigninPromoAppearsAndIsClickable SigninPromoAppearsAndIsClickable
+#endif
+IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, MAYBE_SigninPromoAppearsAndIsClickable) {
   ClearRegisteredPromosExcept(kNtpSignInPromoId);
   RunTestSequence(
       InstrumentTab(kNtpElementId),
@@ -500,7 +513,16 @@
 
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
-IN_PROC_BROWSER_TEST_P(NtpPromoUiTest, ExtensionsPromoAppearsAndIsClickable) {
+// TODO(crbug.com/448993914): Re-enable this test
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_ExtensionsPromoAppearsAndIsClickable \
+  DISABLED_ExtensionsPromoAppearsAndIsClickable
+#else
+#define MAYBE_ExtensionsPromoAppearsAndIsClickable \
+  ExtensionsPromoAppearsAndIsClickable
+#endif
+IN_PROC_BROWSER_TEST_P(NtpPromoUiTest,
+                       MAYBE_ExtensionsPromoAppearsAndIsClickable) {
   ClearRegisteredPromosExcept(kNtpExtensionsPromoId);
   RunTestSequence(
       InstrumentTab(kNtpElementId),
@@ -522,8 +544,16 @@
   // TODD(https://crbug.com/433607240): Check model, histograms.
 }
 
+// TODO(crbug.com/448993914): Re-enable this test
+#if BUILDFLAG(IS_MAC)
+#define MAYBE_CustomizationPromoAppearsAndIsClickable \
+  DISABLED_CustomizationPromoAppearsAndIsClickable
+#else
+#define MAYBE_CustomizationPromoAppearsAndIsClickable \
+  CustomizationPromoAppearsAndIsClickable
+#endif
 IN_PROC_BROWSER_TEST_P(NtpPromoUiTest,
-                       CustomizationPromoAppearsAndIsClickable) {
+                       MAYBE_CustomizationPromoAppearsAndIsClickable) {
   ClearRegisteredPromosExcept(kNtpCustomizationPromoId);
   RunTestSequence(
       InstrumentTab(kNtpElementId),
@@ -634,7 +664,8 @@
   RunTestSequence(
       InstrumentTab(kNtpElementId),
       NavigateWebContents(kNtpElementId, GURL(kNtpURL)),
-      WaitForAndScrollToElement(kNtpElementId, GetFirstPromoPath()),
+      WaitForElementVisible(kNtpElementId, GetFirstPromoPath()),
+      ScrollIntoView(kNtpElementId, GetPromosPath()),
       SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
                               "Screenshots not captured on this platform."),
       ScreenshotWebUi(kNtpElementId, GetPromosPath(),
diff --git a/chrome/browser/page_content_annotations/android/page_content_extraction_tab_model_observer_android.h b/chrome/browser/page_content_annotations/android/page_content_extraction_tab_model_observer_android.h
index be274ee2..afb9471 100644
--- a/chrome/browser/page_content_annotations/android/page_content_extraction_tab_model_observer_android.h
+++ b/chrome/browser/page_content_annotations/android/page_content_extraction_tab_model_observer_android.h
@@ -5,6 +5,7 @@
 #ifndef CHROME_BROWSER_PAGE_CONTENT_ANNOTATIONS_ANDROID_PAGE_CONTENT_EXTRACTION_TAB_MODEL_OBSERVER_ANDROID_H_
 #define CHROME_BROWSER_PAGE_CONTENT_ANNOTATIONS_ANDROID_PAGE_CONTENT_EXTRACTION_TAB_MODEL_OBSERVER_ANDROID_H_
 
+#include "base/memory/raw_ptr.h"
 #include "base/scoped_multi_source_observation.h"
 #include "base/scoped_observation.h"
 #include "base/supports_user_data.h"
@@ -49,7 +50,7 @@
  private:
   void RunStartupMetricsComputation();
 
-  raw_ptr<Profile> profile_;
+  const raw_ptr<Profile> profile_;
   const raw_ptr<PageContentExtractionService> service_;
 
   base::ScopedMultiSourceObservation<TabModel, TabModelObserver>
diff --git a/chrome/browser/page_content_annotations/annotate_page_content_request.cc b/chrome/browser/page_content_annotations/annotate_page_content_request.cc
index d6de0d9..f1c0111 100644
--- a/chrome/browser/page_content_annotations/annotate_page_content_request.cc
+++ b/chrome/browser/page_content_annotations/annotate_page_content_request.cc
@@ -6,7 +6,6 @@
 
 #include "base/feature_list.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/notimplemented.h"
 #include "base/task/task_traits.h"
 #include "base/task/thread_pool.h"
 #include "base/trace_event/trace_event.h"
@@ -61,10 +60,8 @@
   if (TabAndroid* tab = TabAndroid::FromWebContents(web_contents)) {
     return tab->GetAndroidId();
   }
-#else
-  // Implement an usable tab ID for other platforms.
-  NOTIMPLEMENTED();
 #endif
+  // TODO(440643544): Implement an usable tab ID for other platforms.
   return std::nullopt;
 }
 
diff --git a/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc b/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc
index f50bd46b7..0883ba4 100644
--- a/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc
+++ b/chrome/browser/page_content_annotations/page_content_annotations_service_browsertest.cc
@@ -77,7 +77,7 @@
     : public PageContentAnnotationsService::PageContentAnnotationsObserver {
  public:
   void OnPageContentAnnotated(
-      const GURL& url,
+      const HistoryVisit& visit,
       const PageContentAnnotationsResult& result) override {
     last_page_content_annotations_result_ = result;
   }
diff --git a/chrome/browser/page_content_annotations/page_content_extraction_service.cc b/chrome/browser/page_content_annotations/page_content_extraction_service.cc
index 9078e22..6d40050f71 100644
--- a/chrome/browser/page_content_annotations/page_content_extraction_service.cc
+++ b/chrome/browser/page_content_annotations/page_content_extraction_service.cc
@@ -45,12 +45,14 @@
 
 PageContentExtractionService::PageContentExtractionService(
     os_crypt_async::OSCryptAsync* os_crypt_async,
-    const base::FilePath& profile_path) {
-  if (base::FeatureList::IsEnabled(features::kPageContentCache)) {
-    page_content_cache_handler_ =
-        std::make_unique<PageContentCacheHandler>(os_crypt_async, profile_path);
-  }
-}
+    const base::FilePath& profile_path)
+    : is_page_content_cache_enabled_(
+          base::FeatureList::IsEnabled(features::kPageContentCache)),
+      page_content_cache_handler_(
+          is_page_content_cache_enabled_
+              ? std::make_unique<PageContentCacheHandler>(os_crypt_async,
+                                                          profile_path)
+              : nullptr) {}
 
 PageContentExtractionService::~PageContentExtractionService() {
   ClearAllUserData();
@@ -80,7 +82,7 @@
     observer.OnPageContentExtracted(page, page_content);
   }
 
-  if (!page_content_cache_handler_) {
+  if (!is_page_content_cache_enabled_) {
     return;
   }
 
@@ -102,7 +104,7 @@
 }
 
 void PageContentExtractionService::OnTabClosed(int64_t tab_id) {
-  if (page_content_cache_handler_) {
+  if (is_page_content_cache_enabled_) {
     page_content_cache_handler_->OnTabClosed(tab_id);
   }
 }
@@ -111,7 +113,7 @@
     std::optional<int64_t> tab_id,
     content::WebContents* web_contents,
     content::Visibility visibility) {
-  if (page_content_cache_handler_) {
+  if (is_page_content_cache_enabled_) {
     std::optional<ExtractedPageContentResult> extracted_result =
         GetCachedContentsFromWebContents(web_contents);
     if (extracted_result) {
@@ -125,14 +127,14 @@
 void PageContentExtractionService::OnNewNavigation(
     std::optional<int64_t> tab_id,
     content::WebContents* web_contents) {
-  if (page_content_cache_handler_) {
+  if (is_page_content_cache_enabled_) {
     page_content_cache_handler_->OnNewNavigation(
         tab_id, ToWebStateWrapper(web_contents));
   }
 }
 
 PageContentCache* PageContentExtractionService::GetPageContentCache() {
-  return page_content_cache_handler_
+  return is_page_content_cache_enabled_
              ? page_content_cache_handler_->page_content_cache()
              : nullptr;
 }
diff --git a/chrome/browser/page_content_annotations/page_content_extraction_service.h b/chrome/browser/page_content_annotations/page_content_extraction_service.h
index 74f6d95..9de0ce6 100644
--- a/chrome/browser/page_content_annotations/page_content_extraction_service.h
+++ b/chrome/browser/page_content_annotations/page_content_extraction_service.h
@@ -89,7 +89,8 @@
 
   base::ObserverList<Observer> observers_;
 
-  std::unique_ptr<PageContentCacheHandler> page_content_cache_handler_;
+  const bool is_page_content_cache_enabled_;
+  const std::unique_ptr<PageContentCacheHandler> page_content_cache_handler_;
 };
 
 }  // namespace page_content_annotations
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index 3c96fe1..b3a6a3d 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -47,12 +47,8 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/tabs/tab_enums.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/common/chrome_paths.h"
@@ -1263,7 +1259,7 @@
 
   // Zoom PDF via script.
 #if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
-  EXPECT_FALSE(ZoomBubbleCoordinator::From(browser())->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 #endif
   ASSERT_TRUE(content::ExecJs(extension_host,
                               "while (viewer.viewport.getZoom() < 1) {"
@@ -1275,7 +1271,7 @@
 
   watcher.Wait();
 #if defined(TOOLKIT_VIEWS) && !BUILDFLAG(IS_MAC)
-  EXPECT_FALSE(ZoomBubbleCoordinator::From(browser())->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 #endif
 }
 
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
index 6b258aa1..4826c2d 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -4295,9 +4295,10 @@
   void SetUpOnMainThread() override {
     // Close normal browser and switch the test's browser instance to an
     // incognito instance.
-    Browser* incognito = CreateIncognitoBrowser(browser()->profile());
+    BrowserWindowInterface* const incognito =
+        CreateIncognitoBrowser(browser()->profile());
     CloseBrowserSynchronously(browser());
-    SelectFirstBrowser();
+    SetBrowser(incognito);
     ASSERT_EQ(browser(), incognito);
 
     SearchPrefetchBaseBrowserTest::SetUpOnMainThread();
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn
index 59843eaa..d90f15b 100644
--- a/chrome/browser/resources/BUILD.gn
+++ b/chrome/browser/resources/BUILD.gn
@@ -62,6 +62,7 @@
       "privacy_sandbox:resources",
       "privacy_sandbox/internals:resources",
       "profile_internals:resources",
+      "reload_button:resources",
       "search_engine_choice:resources",
       "settings:resources",
       "settings_shared:resources",
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html
index f1f12388d..79c3955b 100644
--- a/chrome/browser/resources/ash/settings/os_languages_page/input_page.html
+++ b/chrome/browser/resources/ash/settings/os_languages_page/input_page.html
@@ -213,8 +213,7 @@
         </template>
         <template is="dom-if"
             if="[[hasOptionsPageInSettings_(item.id)]]">
-          <div class="internal-wrapper"
-              hidden="[[!item.hasOptionsPage]]">
+          <div class="internal-wrapper">
             <cr-icon-button class="subpage-arrow"
                 aria-label$="[[getOpenOptionsPageLabel_(
                 item.displayName)]]"
diff --git a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json.jinja2 b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json.jinja2
index 0ad66318..9fe13e8 100644
--- a/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json.jinja2
+++ b/chrome/browser/resources/chromeos/input_method/google_xkb_manifest.json.jinja2
@@ -56,8 +56,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us::eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_indonesian__",
@@ -68,8 +67,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us::ind"
+      ]
     },
     {
       "name": "__MSG_keyboard_filipino__",
@@ -80,8 +78,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us::fil"
+      ]
     },
     {
       "name": "__MSG_keyboard_malay__",
@@ -92,8 +89,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us::msa"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_international__",
@@ -105,8 +101,7 @@
       ],
       "layouts": [
         "us(intl)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_international_pc__",
@@ -118,8 +113,7 @@
       ],
       "layouts": [
         "us(intl_pc)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl_pc:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_netherlands__",
@@ -130,8 +124,7 @@
       ],
       "layouts": [
         "us(intl)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl:nld"
+      ]
     },
     {
       "name": "__MSG_keyboard_netherlands_us_international_pc__",
@@ -142,8 +135,7 @@
       ],
       "layouts": [
         "us(intl_pc)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl_pc:nld"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_extended__",
@@ -155,8 +147,7 @@
       ],
       "layouts": [
         "us(altgr-intl)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:altgr-intl:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_dvorak__",
@@ -168,8 +159,7 @@
       ],
       "layouts": [
         "us(dvorak)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:dvorak:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_dvp__",
@@ -181,8 +171,7 @@
       ],
       "layouts": [
         "us(dvp)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:dvp:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_colemak__",
@@ -194,8 +183,7 @@
       ],
       "layouts": [
         "us(colemak)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:colemak:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_workman__",
@@ -207,8 +195,7 @@
       ],
       "layouts": [
         "us(workman)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:workman:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_us_workman_international__",
@@ -220,8 +207,7 @@
       ],
       "layouts": [
         "us(workman-intl)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:workman-intl:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_belgian_dutch__",
@@ -231,8 +217,7 @@
       ],
       "layouts": [
         "be"
-      ],
-      "options_page": "hmm_options.html?code=xkb:be::nld"
+      ]
     },
     {
       "name": "__MSG_keyboard_french__",
@@ -243,8 +228,7 @@
       ],
       "layouts": [
         "fr(oss)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:fr::fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_french_bepo__",
@@ -255,8 +239,7 @@
       ],
       "layouts": [
         "fr(bepo)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:fr:bepo:fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_belgian_french__",
@@ -266,8 +249,7 @@
       ],
       "layouts": [
         "be"
-      ],
-      "options_page": "hmm_options.html?code=xkb:be::fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_faroese__",
@@ -277,8 +259,7 @@
       ],
       "layouts": [
         "fo"
-      ],
-      "options_page": "hmm_options.html?code=xkb:fo::fao"
+      ]
     },
     {
       "name": "__MSG_keyboard_canadian_french__",
@@ -289,8 +270,7 @@
       ],
       "layouts": [
         "ca"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ca::fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_swiss_french__",
@@ -301,8 +281,7 @@
       ],
       "layouts": [
         "ch(fr)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ch:fr:fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_canadian_multilingual__",
@@ -313,8 +292,7 @@
       ],
       "layouts": [
         "ca(multix)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ca:multix:fra"
+      ]
     },
     {
       "name": "__MSG_keyboard_german__",
@@ -327,8 +305,7 @@
       ],
       "layouts": [
         "de"
-      ],
-      "options_page": "hmm_options.html?code=xkb:de::ger"
+      ]
     },
     {
       "name": "__MSG_keyboard_german_neo_2__",
@@ -342,8 +319,7 @@
       ],
       "layouts": [
         "de(neo)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:de:neo:ger"
+      ]
     },
     {
       "name": "__MSG_keyboard_belgian_german__",
@@ -353,8 +329,7 @@
       ],
       "layouts": [
         "be"
-      ],
-      "options_page": "hmm_options.html?code=xkb:be::ger"
+      ]
     },
     {
       "name": "__MSG_keyboard_swiss__",
@@ -365,8 +340,7 @@
       ],
       "layouts": [
         "ch"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ch::ger"
+      ]
     },
     {
       "name": "__MSG_keyboard_japanese__",
@@ -377,8 +351,7 @@
       ],
       "layouts": [
         "jp"
-      ],
-      "options_page": "hmm_options.html?code=xkb:jp::jpn"
+      ]
     },
     {
       "name": "__MSG_keyboard_russian__",
@@ -388,8 +361,7 @@
       ],
       "layouts": [
         "ru"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ru::rus"
+      ]
     },
     {
       "name": "__MSG_keyboard_russian_phonetic__",
@@ -399,8 +371,7 @@
       ],
       "layouts": [
         "ru(phonetic)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ru:phonetic:rus"
+      ]
     },
     {
       "name": "__MSG_keyboard_brazilian__",
@@ -411,8 +382,7 @@
       ],
       "layouts": [
         "br"
-      ],
-      "options_page": "hmm_options.html?code=xkb:br::por"
+      ]
     },
     {
       "name": "__MSG_keyboard_portuguese_us_international__",
@@ -423,8 +393,7 @@
       ],
       "layouts": [
         "us(intl)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl:por"
+      ]
     },
     {
       "name": "__MSG_keyboard_portuguese_us_international_pc__",
@@ -435,8 +404,7 @@
       ],
       "layouts": [
         "us(intl_pc)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:us:intl_pc:por"
+      ]
     },
     {
       "name": "__MSG_keyboard_bulgarian__",
@@ -446,8 +414,7 @@
       ],
       "layouts": [
         "bg"
-      ],
-      "options_page": "hmm_options.html?code=xkb:bg::bul"
+      ]
     },
     {
       "name": "__MSG_keyboard_bulgarian_phonetic__",
@@ -457,8 +424,7 @@
       ],
       "layouts": [
         "bg(phonetic)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:bg:phonetic:bul"
+      ]
     },
     {
       "name": "__MSG_keyboard_canadian_english__",
@@ -469,8 +435,7 @@
       ],
       "layouts": [
         "ca(eng)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ca:eng:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_czech__",
@@ -480,8 +445,7 @@
       ],
       "layouts": [
         "cz"
-      ],
-      "options_page": "hmm_options.html?code=xkb:cz::cze"
+      ]
     },
     {
       "name": "__MSG_keyboard_czech_qwerty__",
@@ -492,8 +456,7 @@
       ],
       "layouts": [
         "cz(qwerty)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:cz:qwerty:cze"
+      ]
     },
     {
       "name": "__MSG_keyboard_estonian__",
@@ -503,8 +466,7 @@
       ],
       "layouts": [
         "ee"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ee::est"
+      ]
     },
     {
       "name": "__MSG_keyboard_spanish__",
@@ -515,8 +477,7 @@
       ],
       "layouts": [
         "es"
-      ],
-      "options_page": "hmm_options.html?code=xkb:es::spa"
+      ]
     },
     {
       "name": "__MSG_keyboard_catalan__",
@@ -527,8 +488,7 @@
       ],
       "layouts": [
         "es(cat)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:es:cat:cat"
+      ]
     },
     {
       "name": "__MSG_keyboard_danish__",
@@ -538,8 +498,7 @@
       ],
       "layouts": [
         "dk"
-      ],
-      "options_page": "hmm_options.html?code=xkb:dk::dan"
+      ]
     },
     {
       "name": "__MSG_keyboard_greek__",
@@ -549,8 +508,7 @@
       ],
       "layouts": [
         "gr"
-      ],
-      "options_page": "hmm_options.html?code=xkb:gr::gre"
+      ]
     },
     {
       "name": "__MSG_keyboard_hebrew__",
@@ -560,8 +518,7 @@
       ],
       "layouts": [
         "il"
-      ],
-      "options_page": "hmm_options.html?code=xkb:il::heb"
+      ]
     },
     {
       "name": "__MSG_keyboard_latin_american__",
@@ -573,8 +530,7 @@
       ],
       "layouts": [
         "latam"
-      ],
-      "options_page": "hmm_options.html?code=xkb:latam::spa"
+      ]
     },
     {
       "name": "__MSG_keyboard_lithuanian__",
@@ -584,8 +540,7 @@
       ],
       "layouts": [
         "lt"
-      ],
-      "options_page": "hmm_options.html?code=xkb:lt::lit"
+      ]
     },
     {
       "name": "__MSG_keyboard_latvian__",
@@ -595,8 +550,7 @@
       ],
       "layouts": [
         "lv(apostrophe)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:lv:apostrophe:lav"
+      ]
     },
     {
       "name": "__MSG_keyboard_croatian__",
@@ -606,8 +560,7 @@
       ],
       "layouts": [
         "hr"
-      ],
-      "options_page": "hmm_options.html?code=xkb:hr::scr"
+      ]
     },
     {
       "name": "__MSG_keyboard_uk__",
@@ -618,8 +571,7 @@
       ],
       "layouts": [
         "gb(extd)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:gb:extd:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_english_india__",
@@ -631,8 +583,7 @@
       ],
       "layouts": [
         "in(eng)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:in::eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_english_pakistan__",
@@ -644,8 +595,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=xkb:pk::eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_english_south_africa__",
@@ -657,8 +607,7 @@
       ],
       "layouts": [
         "gb(extd)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:za:gb:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_uk_dvorak__",
@@ -670,8 +619,7 @@
       ],
       "layouts": [
         "gb(dvorak)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:gb:dvorak:eng"
+      ]
     },
     {
       "name": "__MSG_keyboard_finnish__",
@@ -681,8 +629,7 @@
       ],
       "layouts": [
         "fi"
-      ],
-      "options_page": "hmm_options.html?code=xkb:fi::fin"
+      ]
     },
     {
       "name": "__MSG_keyboard_hungarian__",
@@ -692,8 +639,7 @@
       ],
       "layouts": [
         "hu"
-      ],
-      "options_page": "hmm_options.html?code=xkb:hu::hun"
+      ]
     },
     {
       "name": "__MSG_keyboard_hungarian_qwerty__",
@@ -703,8 +649,7 @@
       ],
       "layouts": [
         "hu(qwerty)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:hu:qwerty:hun"
+      ]
     },
     {
       "name": "__MSG_keyboard_italian__",
@@ -715,8 +660,7 @@
       ],
       "layouts": [
         "it"
-      ],
-      "options_page": "hmm_options.html?code=xkb:it::ita"
+      ]
     },
     {
       "name": "__MSG_keyboard_icelandic__",
@@ -726,8 +670,7 @@
       ],
       "layouts": [
         "is"
-      ],
-      "options_page": "hmm_options.html?code=xkb:is::ice"
+      ]
     },
     {
       "name": "__MSG_keyboard_norwegian__",
@@ -739,8 +682,7 @@
       ],
       "layouts": [
         "no"
-      ],
-      "options_page": "hmm_options.html?code=xkb:no::nob"
+      ]
     },
     {
       "name": "__MSG_keyboard_polish__",
@@ -750,8 +692,7 @@
       ],
       "layouts": [
         "pl"
-      ],
-      "options_page": "hmm_options.html?code=xkb:pl::pol"
+      ]
     },
     {
       "name": "__MSG_keyboard_portuguese__",
@@ -762,8 +703,7 @@
       ],
       "layouts": [
         "pt"
-      ],
-      "options_page": "hmm_options.html?code=xkb:pt::por"
+      ]
     },
     {
       "name": "__MSG_keyboard_romanian__",
@@ -773,8 +713,7 @@
       ],
       "layouts": [
         "ro"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ro::rum"
+      ]
     },
     {
       "name": "__MSG_keyboard_romanian_standard__",
@@ -784,8 +723,7 @@
       ],
       "layouts": [
         "ro(std)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ro:std:rum"
+      ]
     },
     {
       "name": "__MSG_keyboard_swedish__",
@@ -795,8 +733,7 @@
       ],
       "layouts": [
         "se"
-      ],
-      "options_page": "hmm_options.html?code=xkb:se::swe"
+      ]
     },
     {
       "name": "__MSG_keyboard_slovak__",
@@ -806,8 +743,7 @@
       ],
       "layouts": [
         "sk"
-      ],
-      "options_page": "hmm_options.html?code=xkb:sk::slo"
+      ]
     },
     {
       "name": "__MSG_keyboard_slovenian__",
@@ -817,8 +753,7 @@
       ],
       "layouts": [
         "si"
-      ],
-      "options_page": "hmm_options.html?code=xkb:si::slv"
+      ]
     },
     {
       "name": "__MSG_keyboard_serbian__",
@@ -828,8 +763,7 @@
       ],
       "layouts": [
         "rs"
-      ],
-      "options_page": "hmm_options.html?code=xkb:rs::srp"
+      ]
     },
     {
       "name": "__MSG_keyboard_turkish__",
@@ -839,8 +773,7 @@
       ],
       "layouts": [
         "tr"
-      ],
-      "options_page": "hmm_options.html?code=xkb:tr::tur"
+      ]
     },
     {
       "name": "__MSG_keyboard_turkish_f__",
@@ -850,8 +783,7 @@
       ],
       "layouts": [
         "tr(f)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:tr:f:tur"
+      ]
     },
     {
       "name": "__MSG_keyboard_ukrainian__",
@@ -861,8 +793,7 @@
       ],
       "layouts": [
         "ua"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ua::ukr"
+      ]
     },
     {
       "name": "__MSG_keyboard_belarusian__",
@@ -872,8 +803,7 @@
       ],
       "layouts": [
         "by"
-      ],
-      "options_page": "hmm_options.html?code=xkb:by::bel"
+      ]
     },
     {
       "name": "__MSG_keyboard_armenian_phonetic__",
@@ -883,8 +813,7 @@
       ],
       "layouts": [
         "am(phonetic)"
-      ],
-      "options_page": "hmm_options.html?code=xkb:am:phonetic:arm"
+      ]
     },
     {
       "name": "__MSG_keyboard_georgian__",
@@ -894,8 +823,7 @@
       ],
       "layouts": [
         "ge"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ge::geo"
+      ]
     },
     {
       "name": "__MSG_keyboard_mongolian__",
@@ -905,8 +833,7 @@
       ],
       "layouts": [
         "mn"
-      ],
-      "options_page": "hmm_options.html?code=xkb:mn::mon"
+      ]
     },
     {
       "name": "__MSG_keyboard_irish__",
@@ -916,8 +843,7 @@
       ],
       "layouts": [
         "ie"
-      ],
-      "options_page": "hmm_options.html?code=xkb:ie::ga"
+      ]
     },
     {
       "name": "__MSG_keyboard_maltese__",
@@ -927,8 +853,7 @@
       ],
       "layouts": [
         "mt"
-      ],
-      "options_page": "hmm_options.html?code=xkb:mt::mlt"
+      ]
     },
     {
       "name": "__MSG_keyboard_macedonian__",
@@ -938,8 +863,7 @@
       ],
       "layouts": [
         "mk"
-      ],
-      "options_page": "hmm_options.html?code=xkb:mk::mkd"
+      ]
     },
     {
       "name": "__MSG_keyboard_kazakh__",
@@ -949,8 +873,7 @@
       ],
       "layouts": [
         "kz"
-      ],
-      "options_page": "hmm_options.html?code=xkb:kz::kaz"
+      ]
     },
     {
       "name": "__MSG_inputmethod_pinyin__",
@@ -962,8 +885,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=zh-t-i0-pinyin"
+      ]
     },
     {
       "name": "__MSG_inputmethod_traditional_pinyin__",
@@ -975,8 +897,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=zh-hant-t-i0-pinyin"
+      ]
     },
     {
       "name": "__MSG_inputmethod_cangjie__",
@@ -1059,8 +980,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=zh-hant-t-i0-und"
+      ]
     },
     {
       "name": "__MSG_transliteration_am__",
@@ -1229,8 +1149,7 @@
       "language": "ko",
       "layouts": [
         "us"
-      ],
-      "options_page": "hmm_options.html?code=ko-t-i0-und"
+      ]
     },
     {
       "name": "__MSG_inputmethod_mozc_us__",
@@ -1239,8 +1158,7 @@
       "language": "ja",
       "layouts": [
         "us"
-      ],
-      "options_page": "mozc_option.html"
+      ]
     },
     {
       "name": "__MSG_inputmethod_mozc_jp__",
@@ -1249,8 +1167,7 @@
       "language": "ja",
       "layouts": [
         "jp"
-      ],
-      "options_page": "mozc_option.html"
+      ]
     },
     {
       "name": "__MSG_keyboard_bengali_phonetic__",
@@ -1442,8 +1359,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "LEGACY-required-otherwise-options-does-not-load.html"
+      ]
     },
     {
       "name": "__MSG_keyboard_vietnamese_viqr__",
@@ -1463,8 +1379,7 @@
       ],
       "layouts": [
         "us"
-      ],
-      "options_page": "LEGACY-required-otherwise-options-does-not-load.html"
+      ]
     },
     {
       "name": "__MSG_keyboard_arabic__",
diff --git a/chrome/browser/resources/new_tab_page/modules/tab_groups/module.css b/chrome/browser/resources/new_tab_page/modules/tab_groups/module.css
index 0ce01de..352dad0 100644
--- a/chrome/browser/resources/new_tab_page/modules/tab_groups/module.css
+++ b/chrome/browser/resources/new_tab_page/modules/tab_groups/module.css
@@ -162,7 +162,6 @@
 }
 
 cr-icon {
-  --iron-icon-fill-color: currentColor;
   width: 20px;
   height: 20px;
   flex-shrink: 0;
diff --git a/chrome/browser/resources/new_tab_page/modules/tab_groups/module.html b/chrome/browser/resources/new_tab_page/modules/tab_groups/module.html
index adc8121c..1d0ccec7 100644
--- a/chrome/browser/resources/new_tab_page/modules/tab_groups/module.html
+++ b/chrome/browser/resources/new_tab_page/modules/tab_groups/module.html
@@ -73,7 +73,7 @@
             class="create-new-tab-group"
             @click="${() => this.onCreateNewTabGroupClick_(false)}">
           <div class="row-content">
-            <cr-icon id="createNewsTabGroupIcon"
+            <cr-icon id="createNewTabGroupIcon"
                 icon="tab_groups:create_new_tab_group" slot="icon">
             </cr-icon>
             <div id="createNewTabGroupText" class="tab-group-title">
diff --git a/chrome/browser/resources/omnibox_popup/BUILD.gn b/chrome/browser/resources/omnibox_popup/BUILD.gn
index d91610f..cab2412 100644
--- a/chrome/browser/resources/omnibox_popup/BUILD.gn
+++ b/chrome/browser/resources/omnibox_popup/BUILD.gn
@@ -8,10 +8,15 @@
 
 build_webui("build") {
   grd_prefix = "omnibox_popup"
-  static_files = [ "omnibox_popup.html" ]
+  static_files = [
+    "omnibox_popup.html",
+    "omnibox_popup_full.html",
+  ]
   ts_files = [
     "app.html.ts",
     "app.ts",
+    "full_app.html.ts",
+    "full_app.ts",
     "omnibox_popup.ts",
   ]
   css_files = [ "app.css" ]
diff --git a/chrome/browser/resources/omnibox_popup/app.css b/chrome/browser/resources/omnibox_popup/app.css
index 7154441b..2b70777a1 100644
--- a/chrome/browser/resources/omnibox_popup/app.css
+++ b/chrome/browser/resources/omnibox_popup/app.css
@@ -21,10 +21,11 @@
   font-size: 14.6px; /* closely resembles the omnibox input font size. */
   /* Colors used in the cr-searchbox results dropdown */
   --color-searchbox-answer-icon-background: var(--color-omnibox-answer-icon-g-m3-background);
-  --color-searchbox-answer-icon-foreground: var(--color-omnibox-results-starter-pack-icon);
-  --color-searchbox-results-action-chip-focus-outline: var(--color-omnibox-results-button-icon-selected);
+  --color-searchbox-answer-icon-foreground: var(--color-omnibox-answer-icon-g-m3-foreground);
+  --color-searchbox-results-action-chip-focus-outline: var(--color-omnibox-results-focus-indicator);
   --color-searchbox-results-action-chip: var(--color-omnibox-results-button-border);
   --color-searchbox-results-action-chip-icon: var(--color-omnibox-results-button-icon);
+  --color-searchbox-results-action-chip-icon-selected: var(--color-omnibox-results-button-icon-selected);
   --color-searchbox-results-background: var(--color-omnibox-results-background);
   --color-searchbox-results-background-hovered: var(--color-omnibox-results-background-hovered);
   --color-searchbox-results-background-selected: var(--color-omnibox-results-background-selected);
@@ -39,6 +40,7 @@
   --color-searchbox-results-icon-container-background: unset;
   --color-searchbox-results-icon-focused-outline: var(--color-omnibox-results-focus-indicator);
   --color-searchbox-results-icon-selected: var(--color-omnibox-results-icon-selected);
+  --color-searchbox-results-starter-pack-icon: var(--color-omnibox-results-starter-pack-icon);
   --color-searchbox-results-typed-prefix: unset;
   --color-searchbox-results-url-selected: var(--color-omnibox-results-url-selected);
   --color-searchbox-results-url: var(--color-omnibox-results-url);
diff --git a/chrome/browser/resources/omnibox_popup/full_app.html.ts b/chrome/browser/resources/omnibox_popup/full_app.html.ts
new file mode 100644
index 0000000..fa054b76
--- /dev/null
+++ b/chrome/browser/resources/omnibox_popup/full_app.html.ts
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html} from '//resources/lit/v3_0/lit.rollup.js';
+
+import type {OmniboxFullAppElement} from './full_app.js';
+
+export function getHtml(this: OmniboxFullAppElement) {
+  // clang-format off
+  return html`<!--_html_template_start_-->
+<cr-searchbox></cr-searchbox>
+<!--_html_template_end_-->`;
+  // clang-format on
+}
diff --git a/chrome/browser/resources/omnibox_popup/full_app.ts b/chrome/browser/resources/omnibox_popup/full_app.ts
new file mode 100644
index 0000000..e5da124
--- /dev/null
+++ b/chrome/browser/resources/omnibox_popup/full_app.ts
@@ -0,0 +1,49 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '//resources/cr_components/searchbox/searchbox.js';
+import '/strings.m.js';
+
+import {EventTracker} from '//resources/js/event_tracker.js';
+import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
+
+import {getHtml} from './full_app.html.js';
+
+export class OmniboxFullAppElement extends CrLitElement {
+  static get is() {
+    return 'omnibox-full-app';
+  }
+
+  override render() {
+    return getHtml.bind(this)();
+  }
+
+  private isDebug_: boolean =
+      new URLSearchParams(window.location.search).has('debug');
+  private eventTracker_ = new EventTracker();
+
+  override connectedCallback() {
+    super.connectedCallback();
+
+    if (!this.isDebug_) {
+      this.eventTracker_.add(
+          document.documentElement, 'contextmenu', (e: Event) => {
+            e.preventDefault();
+          });
+    }
+  }
+
+  override disconnectedCallback() {
+    super.disconnectedCallback();
+    this.eventTracker_.removeAll();
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'omnibox-full-app': OmniboxFullAppElement;
+  }
+}
+
+customElements.define(OmniboxFullAppElement.is, OmniboxFullAppElement);
diff --git a/chrome/browser/resources/omnibox_popup/omnibox_popup.ts b/chrome/browser/resources/omnibox_popup/omnibox_popup.ts
index 2de456e..87b50d7b 100644
--- a/chrome/browser/resources/omnibox_popup/omnibox_popup.ts
+++ b/chrome/browser/resources/omnibox_popup/omnibox_popup.ts
@@ -3,3 +3,4 @@
 // found in the LICENSE file.
 
 import './app.js';
+import './full_app.js';
diff --git a/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html b/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html
new file mode 100644
index 0000000..23517b7
--- /dev/null
+++ b/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html
@@ -0,0 +1,30 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+<head>
+  <meta charset="utf-8">
+  <title>Omnibox Popup</title>
+  <link rel="stylesheet" href="//resources/css/text_defaults_md.css">
+  <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome">
+  <style>
+    html {
+      height: auto;
+      overflow: hidden;
+
+      /* Note: Needed to prevent a horizontal scrollbar when this UI is shown
+         via OmniboxPopupPresenter (not reproducible in a tab). */
+      max-width: 100vw;
+    }
+
+    body {
+      background-color: var(--color-omnibox-results-background);
+      height: auto;
+      margin: 0;
+      overflow: hidden;
+    }
+  </style>
+</head>
+<body>
+  <omnibox-full-app></omnibox-full-app>
+</body>
+<script type="module" src="omnibox_popup.js"></script>
+</html>
diff --git a/chrome/browser/resources/preinstalled_web_apps/internal b/chrome/browser/resources/preinstalled_web_apps/internal
index 656ac90..73cc53e 160000
--- a/chrome/browser/resources/preinstalled_web_apps/internal
+++ b/chrome/browser/resources/preinstalled_web_apps/internal
@@ -1 +1 @@
-Subproject commit 656ac90405cdbb7d7ab05c54a1628c6d7418832e
+Subproject commit 73cc53e1db0fddd9fb797c40c6085579b27e7bf3
diff --git a/chrome/browser/resources/preinstalled_web_apps/resources.grd b/chrome/browser/resources/preinstalled_web_apps/resources.grd
index 104274a..c381d755 100644
--- a/chrome/browser/resources/preinstalled_web_apps/resources.grd
+++ b/chrome/browser/resources/preinstalled_web_apps/resources.grd
@@ -23,6 +23,7 @@
         <include name="IDR_PREINSTALLED_WEB_APPS_GEMINI_ICON_192_PNG" file="internal/gemini_192.png" type="BINDATA" />
         <include name="IDR_PREINSTALLED_WEB_APPS_GOOGLE_CALENDAR_ICON_192_PNG" file="internal/google_calendar_192.png" type="BINDATA" />
         <include name="IDR_PREINSTALLED_WEB_APPS_NOTEBOOK_LM_ICON_512_PNG" file="internal/notebook_lm_512.png" type="BINDATA" />
+        <include name="IDR_PREINSTALLED_WEB_APPS_VIDS_ICON_144_PNG" file="internal/vids_144.png" type="BINDATA" />
       </if>
     </includes>
   </release>
diff --git a/chrome/browser/resources/reload_button/BUILD.gn b/chrome/browser/resources/reload_button/BUILD.gn
new file mode 100644
index 0000000..5124fd8
--- /dev/null
+++ b/chrome/browser/resources/reload_button/BUILD.gn
@@ -0,0 +1,30 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//ui/webui/resources/tools/build_webui.gni")
+
+assert(!is_android)
+
+build_webui("build") {
+  grd_prefix = "reload_button"
+
+  static_files = [
+    "reload_button.html",
+    "reload_button.css",
+  ]
+
+  ts_files = [
+    "app.ts",
+    "app.html.ts",
+  ]
+  css_files = [ "app.css" ]
+
+  webui_context_type = "trusted"
+
+  ts_deps = [
+    "//third_party/lit/v3_0:build_ts",
+    "//ui/webui/resources/cr_elements:build_ts",
+    "//ui/webui/resources/js:build_ts",
+  ]
+}
diff --git a/chrome/browser/resources/reload_button/DIR_METADATA b/chrome/browser/resources/reload_button/DIR_METADATA
new file mode 100644
index 0000000..15e6292
--- /dev/null
+++ b/chrome/browser/resources/reload_button/DIR_METADATA
@@ -0,0 +1,4 @@
+buganizer_public: {
+  component_id: 1456991
+}
+team_email: "chrome-waap-eng@google.com"
diff --git a/chrome/browser/resources/reload_button/OWNERS b/chrome/browser/resources/reload_button/OWNERS
new file mode 100644
index 0000000..d000fa86
--- /dev/null
+++ b/chrome/browser/resources/reload_button/OWNERS
@@ -0,0 +1 @@
+file://chrome/browser/ui/webui/reload_button/OWNERS
diff --git a/chrome/browser/resources/reload_button/app.css b/chrome/browser/resources/reload_button/app.css
new file mode 100644
index 0000000..5c40df2
--- /dev/null
+++ b/chrome/browser/resources/reload_button/app.css
@@ -0,0 +1,19 @@
+/* Copyright 2025 The Chromium Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* #css_wrapper_metadata_start
+ * #type=style-lit
+ * #scheme=relative
+ * #import=//resources/cr_elements/cr_icons_lit.css.js
+ * #include=cr-icons-lit
+ * #css_wrapper_metadata_end */
+
+cr-icon-button {
+  --cr-icon-button-icon-size: 20px;
+  --cr-icon-button-margin-end: 0;
+  --cr-icon-button-margin-start: 0;
+  --cr-icon-button-size: 32px;
+  --cr-icon-button-fill-color: var(--color-toolbar-button-icon);
+}
+
diff --git a/chrome/browser/resources/reload_button/app.html.ts b/chrome/browser/resources/reload_button/app.html.ts
new file mode 100644
index 0000000..b4b35a7
--- /dev/null
+++ b/chrome/browser/resources/reload_button/app.html.ts
@@ -0,0 +1,15 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import {html} from '//resources/lit/v3_0/lit.rollup.js';
+
+import type {ReloadButtonAppElement} from './app.js';
+
+export function getHtml(this: ReloadButtonAppElement) {
+  return html`<!--_html_template_start_-->
+<cr-icon-button class="${this.reloadOrStopIcon_}"
+    @click="${this.onReloadOrStopClick_}">
+</cr-icon-button>
+<!--_html_template_end_-->`;
+}
diff --git a/chrome/browser/resources/reload_button/app.ts b/chrome/browser/resources/reload_button/app.ts
new file mode 100644
index 0000000..d637e83
--- /dev/null
+++ b/chrome/browser/resources/reload_button/app.ts
@@ -0,0 +1,53 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import '//resources/cr_elements/cr_button/cr_button.js';
+import '//resources/cr_elements/cr_icon_button/cr_icon_button.js';
+import '//resources/cr_elements/icons.html.js';
+
+import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js';
+
+import {getCss} from './app.css.js';
+import {getHtml} from './app.html.js';
+
+export class ReloadButtonAppElement extends CrLitElement {
+  static get is() {
+    return 'reload-button-app';
+  }
+
+  static override get styles() {
+    return getCss();
+  }
+
+  override render() {
+    return getHtml.bind(this)();
+  }
+
+  static override get properties() {
+    return {
+      reloadOrStopIcon_: {state: true, type: String},
+    };
+  }
+
+  protected accessor reloadOrStopIcon_: string = 'icon-refresh';
+
+  protected setReloadStopState(isLoading: boolean) {
+    this.reloadOrStopIcon_ = isLoading ? 'icon-clear' : 'icon-refresh';
+  }
+
+  // TODO(crbug.com/444358999): implement the reload logic
+  protected onReloadOrStopClick_(_: Event) {
+    this.reloadOrStopIcon_ = this.reloadOrStopIcon_ === 'icon-refresh' ?
+        'icon-clear' :
+        'icon-refresh';
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'reload-button-app': ReloadButtonAppElement;
+  }
+}
+
+customElements.define(ReloadButtonAppElement.is, ReloadButtonAppElement);
diff --git a/chrome/browser/resources/reload_button/reload_button.css b/chrome/browser/resources/reload_button/reload_button.css
new file mode 100644
index 0000000..4b0ed503
--- /dev/null
+++ b/chrome/browser/resources/reload_button/reload_button.css
@@ -0,0 +1,13 @@
+/* Copyright 2025 The Chromium Authors
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file. */
+
+/* #css_wrapper_metadata_start
+ * #type=style-lit
+ * #scheme=relative
+ * #css_wrapper_metadata_end */
+
+body {
+  margin: 0;
+  overflow: hidden;
+}
diff --git a/chrome/browser/resources/reload_button/reload_button.html b/chrome/browser/resources/reload_button/reload_button.html
new file mode 100644
index 0000000..78cd854
--- /dev/null
+++ b/chrome/browser/resources/reload_button/reload_button.html
@@ -0,0 +1,8 @@
+<!doctype html>
+<html dir="$i18n{textdirection}" lang="$i18n{language}">
+  <meta charset="utf-8">
+  <link rel="stylesheet" href="chrome://theme/colors.css?sets=ui,chrome">
+  <link rel="stylesheet" href="reload_button.css">
+  <reload-button-app></reload-button-app>
+  <script type="module" src="app.js"></script>
+</html>
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.html b/chrome/browser/resources/settings/privacy_page/cookies_page.html
index 6bd53628..b59fd01 100644
--- a/chrome/browser/resources/settings/privacy_page/cookies_page.html
+++ b/chrome/browser/resources/settings/privacy_page/cookies_page.html
@@ -205,7 +205,7 @@
     </template>
     <settings-do-not-track-toggle id="doNotTrack" prefs="{{prefs}}">
     </settings-do-not-track-toggle>
-    <cr-link-row id="site-data-trigger" class="hr"
+    <cr-link-row id="siteDataTrigger" class="hr"
         on-click="onSiteDataClick_" label="$i18n{cookiePageAllSitesLink}"
         role-description="$i18n{subpageArrowRoleDescription}">
     </cr-link-row>
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.ts b/chrome/browser/resources/settings/privacy_page/cookies_page.ts
index 621a29f..49f05fb6 100644
--- a/chrome/browser/resources/settings/privacy_page/cookies_page.ts
+++ b/chrome/browser/resources/settings/privacy_page/cookies_page.ts
@@ -239,7 +239,7 @@
     return new Map([
       [
         `${routes.SITE_SETTINGS_ALL.path}_${routes.COOKIES.path}`,
-        '#site-data-trigger',
+        '#siteDataTrigger',
       ],
     ]);
   }
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.html b/chrome/browser/resources/settings/privacy_page/personalization_options.html
index 4eea720d..7adae56 100644
--- a/chrome/browser/resources/settings/privacy_page/personalization_options.html
+++ b/chrome/browser/resources/settings/privacy_page/personalization_options.html
@@ -18,7 +18,7 @@
         padding: var(--settings-signin-choice-padding, 10px 0px 10px);
       }
 
-      #label-wrapper {
+      #labelWrapper {
         margin-inline-end: 20px;
       }
 
@@ -28,7 +28,7 @@
     <div id="chromeSigninUserChoiceSetting" class="hr cr-row" role="group"
         hidden="[[!chromeSigninUserChoiceInfo_.shouldShowSettings]]"
         aria-label="$i18n{chromeSigninChoiceTitle}">
-      <div id="label-wrapper" class="flex">
+      <div id="labelWrapper" class="flex">
           <div>
             $i18n{chromeSigninChoiceTitle}
           </div>
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html
index c5d1b69..b43bf69 100644
--- a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html
+++ b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.html
@@ -42,13 +42,13 @@
         text-align: start;
       }
 
-      #site-header,
-      #user-display-name-header,
-      #user-name-header {
+      #siteHeader,
+      #userDisplayNameHeader,
+      #userNameHeader {
         font-weight: bold;
       }
 
-      #site-header {
+      #siteHeader {
         margin-inline-start: 1rem;
       }
 
@@ -82,13 +82,13 @@
 
           <div id="credentials">
             <div id="header" class="list-item column-header">
-              <div class="site" id="site-header">
+              <div class="site" id="siteHeader">
                 $i18n{securityKeysCredentialWebsiteLabel}
               </div>
-              <div class="user-display-name" id="user-display-name-header">
+              <div class="user-display-name" id="userDisplayNameHeader">
                 $i18n{securityKeysCredentialDisplayNameLabel}
               </div>
-              <div class="user-name" id="user-name-header">
+              <div class="user-name" id="userNameHeader">
                 $i18n{securityKeysCredentialUsernameLabel}
               </div>
               <div class="icon-placeholder"></div>
diff --git a/chrome/browser/resources/side_panel/read_anything/app.ts b/chrome/browser/resources/side_panel/read_anything/app.ts
index c1dcceca..b842cd1 100644
--- a/chrome/browser/resources/side_panel/read_anything/app.ts
+++ b/chrome/browser/resources/side_panel/read_anything/app.ts
@@ -508,8 +508,9 @@
   protected onKeyDown_(e: KeyboardEvent) {
     if (e.key === 'k') {
       e.stopPropagation();
+      e.preventDefault();
+      this.speechController_.onPlayPauseKeyPress(this.$.container);
     }
-    this.speechController_.onPlayPauseKeyPress(this.$.container);
   }
 }
 
diff --git a/chrome/browser/resources/tab_search/split_view/app.ts b/chrome/browser/resources/tab_search/split_view/app.ts
index e86a8c4..1f2af3ac 100644
--- a/chrome/browser/resources/tab_search/split_view/app.ts
+++ b/chrome/browser/resources/tab_search/split_view/app.ts
@@ -11,7 +11,7 @@
 import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
 
 import type {SelectableLazyListElement} from '../selectable_lazy_list.js';
-import {normalizeURL, TabData, TabItemType} from '../tab_data.js';
+import {getDisplayHostnameForUrl, normalizeURL, TabData, TabItemType} from '../tab_data.js';
 import type {ProfileData, Tab, TabsRemovedInfo, TabUpdateInfo} from '../tab_search.mojom-webui.js';
 import type {TabSearchApiProxy} from '../tab_search_api_proxy.js';
 import {TabSearchApiProxyImpl} from '../tab_search_api_proxy.js';
@@ -210,8 +210,9 @@
 
   private getTabData_(tab: Tab, inActiveWindow: boolean, type: TabItemType):
       TabData {
-    const tabData =
-        new TabData(tab, type, new URL(normalizeURL(tab.url.url)).hostname);
+    const displayUrl =
+        getDisplayHostnameForUrl(new URL(normalizeURL(tab.url.url)));
+    const tabData = new TabData(tab, type, displayUrl);
 
     if (type === TabItemType.OPEN_TAB) {
       tabData.inActiveWindow = inActiveWindow;
diff --git a/chrome/browser/resources/tab_search/tab_data.ts b/chrome/browser/resources/tab_search/tab_data.ts
index 56f4a5d..5eb3d2e 100644
--- a/chrome/browser/resources/tab_search/tab_data.ts
+++ b/chrome/browser/resources/tab_search/tab_data.ts
@@ -118,6 +118,18 @@
   return url || 'about:blank';
 }
 
+export function getDisplayHostnameForUrl(url: URL): string {
+  if (url.protocol === 'blob:') {
+    return loadTimeData.getString('blobUrlSource');
+  } else if (url.protocol === 'file:') {
+    return loadTimeData.getString('fileUrlSource');
+  } else if (url.protocol === 'about:' && url.pathname === 'blank') {
+    return 'about:blank';
+  } else {
+    return url.hostname;
+  }
+}
+
 export function getTitle(data: TabData|TabGroupData): string|undefined {
   if (data.type === TabItemType.RECENTLY_CLOSED_TAB_GROUP) {
     return undefined;
diff --git a/chrome/browser/resources/tab_search/tab_search_page.ts b/chrome/browser/resources/tab_search/tab_search_page.ts
index 3dbd50776..c45a68c 100644
--- a/chrome/browser/resources/tab_search/tab_search_page.ts
+++ b/chrome/browser/resources/tab_search/tab_search_page.ts
@@ -26,7 +26,7 @@
 import {search} from './search.js';
 import type {SelectableLazyListElement} from './selectable_lazy_list.js';
 import {NO_SELECTION, selectorNavigationKeys} from './selectable_lazy_list.js';
-import {ariaLabel, getHostname, getTabGroupTitle, getTitle, type ItemData, normalizeURL, TabData, TabGroupData, TabItemType, tokenEquals, tokenToString} from './tab_data.js';
+import {ariaLabel, getDisplayHostnameForUrl, getHostname, getTabGroupTitle, getTitle, type ItemData, normalizeURL, TabData, TabGroupData, TabItemType, tokenEquals, tokenToString} from './tab_data.js';
 import type {ProfileData, RecentlyClosedTab, Tab, TabGroup, TabsRemovedInfo, TabUpdateInfo} from './tab_search.mojom-webui.js';
 import {TabSearchSection} from './tab_search.mojom-webui.js';
 import type {TabSearchApiProxy} from './tab_search_api_proxy.js';
@@ -661,22 +661,12 @@
     return ariaLabel(tabData);
   }
 
-  private getDisplayHostnameForUrl_(url: URL): string {
-    if (url.protocol === 'blob:') {
-      return loadTimeData.getString('blobUrlSource');
-    } else if (url.protocol === 'file:') {
-      return loadTimeData.getString('fileUrlSource');
-    } else {
-      return url.hostname;
-    }
-  }
-
   private tabData_(
       tab: Tab|RecentlyClosedTab, inActiveWindow: boolean, type: TabItemType,
       tabGroupsMap: Map<string, TabGroup>): TabData {
     const tabData = new TabData(
         tab, type,
-        this.getDisplayHostnameForUrl_(new URL(normalizeURL(tab.url.url))));
+        getDisplayHostnameForUrl(new URL(normalizeURL(tab.url.url))));
 
     if (tab.groupId) {
       tabData.tabGroup = tabGroupsMap.get(tokenToString(tab.groupId));
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
index ff457271..ef64efc1 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.cc
@@ -266,6 +266,11 @@
   content_analysis_request_.set_is_content_encrypted(is_content_encrypted);
 }
 
+void BinaryUploadService::Request::set_is_content_too_large(
+    bool is_content_too_large) {
+  is_content_too_large_ = is_content_too_large;
+}
+
 void BinaryUploadService::Request::set_blocking(bool blocking) {
   content_analysis_request_.set_blocking(blocking);
 }
@@ -382,6 +387,14 @@
   image_paste_ = image_paste;
 }
 
+bool BinaryUploadService::Request::is_content_too_large() const {
+  return is_content_too_large_;
+}
+
+bool BinaryUploadService::Request::is_content_encrypted() const {
+  return content_analysis_request_.is_content_encrypted();
+}
+
 void BinaryUploadService::Request::StartRequest() {
   if (!request_start_callback_.is_null()) {
     std::move(request_start_callback_).Run(*this);
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
index e660612..d436f79 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h
@@ -194,6 +194,7 @@
         enterprise_connectors::ContentAnalysisRequest::Reason reason);
     void set_require_metadata_verdict(bool require_metadata_verdict);
     void set_is_content_encrypted(bool is_content_encrypted);
+    void set_is_content_too_large(bool is_content_too_large);
     void set_blocking(bool blocking);
     void add_local_ips(const std::string& ip_address);
     void set_referrer_chain(const google::protobuf::RepeatedPtrField<
@@ -220,6 +221,8 @@
     base::optional_ref<const std::string> password() const;
     enterprise_connectors::ContentAnalysisRequest::Reason reason() const;
     bool blocking() const;
+    bool is_content_encrypted() const;
+    bool is_content_too_large() const;
 
     // Called when beginning to try upload.
     void StartRequest();
@@ -259,6 +262,8 @@
     std::string access_token_;
 
     bool image_paste_ = false;
+
+    bool is_content_too_large_ = false;
   };
 
   // A class to encapsulate the a request acknowledgement. This class will
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc
index d26093f..f14f5b2 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service.cc
@@ -433,6 +433,9 @@
     if (result == Result::FILE_ENCRYPTED) {
       request->set_is_content_encrypted(true);
     }
+    if (result == Result::FILE_TOO_LARGE) {
+      request->set_is_content_too_large(true);
+    }
   }
 
   if (!request->IsAuthRequest() && data.size == 0) {
@@ -619,10 +622,17 @@
     *response.add_results() = std::move(tag_and_result.second);
   }
 
-  // Set `result` to be unknown, if the request is terminated with incomplete
+  // Set `result` to be INCOMPLETE_RESPONSE, if the request is terminated with incomplete
   // response.
-  Result result = ResponseIsComplete(request_id) ? Result::SUCCESS
-                                                 : Result::INCOMPLETE_RESPONSE;
+  Result result = Result::SUCCESS;
+  if (!ResponseIsComplete(request_id)) {
+    result = Result::INCOMPLETE_RESPONSE;
+  } else if (request->is_content_too_large()) {
+    result = Result::FILE_TOO_LARGE;
+  } else if (request->is_content_encrypted()) {
+    result = Result::FILE_ENCRYPTED;
+  }
+
   FinishRequest(request, result, std::move(response));
 }
 
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc
index b10d438..e5e7159 100644
--- a/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc
+++ b/chrome/browser/safe_browsing/cloud_content_scanning/cloud_binary_upload_service_unittest.cc
@@ -288,6 +288,39 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
+TEST_F(CloudBinaryUploadServiceTest, PassesForLargeFile) {
+  BinaryUploadService::Result scanning_result;
+  enterprise_connectors::ContentAnalysisResponse scanning_response;
+
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+
+  base::FilePath file_path = temp_dir.GetPath().AppendASCII("normal.doc");
+  ASSERT_TRUE(base::WriteFile(file_path, "test"));
+
+  ExpectNetworkResponse(/*should_succeed=*/true,
+                        enterprise_connectors::ContentAnalysisResponse());
+
+  std::unique_ptr<MockRequest> request = MakeRequest(
+      &scanning_result, &scanning_response, /*is_advanced_protection*/ false);
+  request->set_analysis_connector(
+      enterprise_connectors::AnalysisConnector::FILE_ATTACHED);
+  ON_CALL(*request, GetRequestData(_))
+      .WillByDefault(
+          [file_path](BinaryUploadService::Request::DataCallback callback) {
+            BinaryUploadService::Request::Data data;
+            data.path = file_path;
+            data.size = 4;  // Must not be zero.
+            std::move(callback).Run(BinaryUploadService::Result::FILE_TOO_LARGE,
+                                    std::move(data));
+          });
+  UploadForDeepScanning(std::move(request));
+
+  content::RunAllTasksUntilIdle();
+
+  EXPECT_EQ(scanning_result, BinaryUploadService::Result::FILE_TOO_LARGE);
+}
+
 TEST_F(CloudBinaryUploadServiceTest, FailsForLargeFile) {
   BinaryUploadService::Result scanning_result;
   enterprise_connectors::ContentAnalysisResponse scanning_response;
@@ -397,7 +430,7 @@
   // instead.
   content::RunAllTasksUntilIdle();
 
-  EXPECT_EQ(scanning_result, BinaryUploadService::Result::SUCCESS);
+  EXPECT_EQ(scanning_result, BinaryUploadService::Result::FILE_ENCRYPTED);
 }
 
 TEST_F(CloudBinaryUploadServiceTest, Succeeds) {
diff --git a/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc b/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc
index ccf58c94..57f7983 100644
--- a/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc
+++ b/chrome/browser/search_engine_choice/search_engine_choice_dialog_browsertest.cc
@@ -201,8 +201,10 @@
     SessionRestoreTestHelper restore_observer;
 
     // Create a new window, which should trigger session restore.
+    ui_test_utils::BrowserCreatedObserver browser_created_observer;
     chrome::NewEmptyWindow(profile);
     tab_waiter.Wait();
+    SetBrowser(browser_created_observer.Wait());
 
     for (Browser* new_browser : *BrowserList::GetInstance()) {
       WaitForTabsToLoad(new_browser);
@@ -211,7 +213,6 @@
     restore_observer.Wait();
     keep_alive.reset();
     profile_keep_alive.reset();
-    SelectFirstBrowser();
   }
 
   void WaitForTabsToLoad(Browser* browser) {
diff --git a/chrome/browser/tab/BUILD.gn b/chrome/browser/tab/BUILD.gn
index b89794c5..fafd647 100644
--- a/chrome/browser/tab/BUILD.gn
+++ b/chrome/browser/tab/BUILD.gn
@@ -232,6 +232,7 @@
     "tab_state_storage_database.cc",
     "tab_state_storage_service.cc",
     "tab_storage_package.cc",
+    "tab_storage_packager.cc",
     "tab_storage_util.cc",
     "web_contents_state.cc",
   ]
diff --git a/chrome/browser/tab/tab_state_storage_service.cc b/chrome/browser/tab/tab_state_storage_service.cc
index 2a01bd7..869b6a87 100644
--- a/chrome/browser/tab/tab_state_storage_service.cc
+++ b/chrome/browser/tab/tab_state_storage_service.cc
@@ -56,8 +56,7 @@
     return;
   }
 
-  packager_->Package(tab);
-  std::unique_ptr<StoragePackage> package = packager_->ReleasePackage();
+  std::unique_ptr<StoragePackage> package = packager_->Package(tab);
   DCHECK(package) << "Packager should return a package";
 
   int storage_id = GetStorageId(tab);
@@ -69,8 +68,8 @@
     return;
   }
 
-  packager_->Package(collection, *this);
-  std::unique_ptr<StoragePackage> package = packager_->ReleasePackage();
+  std::unique_ptr<StoragePackage> package =
+      packager_->Package(collection, *this);
   DCHECK(package) << "Packager should return a package";
 
   int storage_id = GetStorageId(collection);
diff --git a/chrome/browser/tab/tab_storage_packager.cc b/chrome/browser/tab/tab_storage_packager.cc
new file mode 100644
index 0000000..a76d28b
--- /dev/null
+++ b/chrome/browser/tab/tab_storage_packager.cc
@@ -0,0 +1,56 @@
+// Copyright 2025 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/tab/tab_storage_packager.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/token.h"
+#include "chrome/browser/tab/collection_storage_package.h"
+#include "chrome/browser/tab/storage_id_mapping.h"
+#include "chrome/browser/tab/storage_package.h"
+#include "chrome/browser/tab/tab_storage_package.h"
+#include "components/tabs/public/direct_child_walker.h"
+
+namespace tabs {
+
+// Crawls the direct children of a TabCollection and adds them to the list of
+// children.
+class ChildProcessor : public DirectChildWalker::Processor {
+ public:
+  ChildProcessor(tabs_pb::Children& children_proto, StorageIdMapping& mapping)
+      : children_proto_(children_proto), mapping_(mapping) {}
+
+  void ProcessTab(const TabInterface* tab) override {
+    children_proto_->add_storage_id(mapping_->GetStorageId(tab));
+  }
+
+  void ProcessCollection(const TabCollection* collection) override {
+    children_proto_->add_storage_id(mapping_->GetStorageId(collection));
+  }
+
+ private:
+  raw_ref<tabs_pb::Children> children_proto_;
+  raw_ref<StorageIdMapping> mapping_;
+};
+
+TabStoragePackager::TabStoragePackager() = default;
+TabStoragePackager::~TabStoragePackager() = default;
+
+std::unique_ptr<StoragePackage> TabStoragePackager::Package(
+    const TabCollection* collection,
+    StorageIdMapping& mapping) {
+  tabs_pb::Children children_proto;
+
+  ChildProcessor processor(children_proto, mapping);
+  DirectChildWalker walker(collection, &processor);
+  walker.Walk();
+
+  // TODO(https://crbug.com/448875689): Fill this package with collection
+  // specific data.
+  return std::make_unique<CollectionStoragePackage>(std::move(children_proto));
+}
+
+}  // namespace tabs
diff --git a/chrome/browser/tab/tab_storage_packager.h b/chrome/browser/tab/tab_storage_packager.h
index 4552756..a77fceb 100644
--- a/chrome/browser/tab/tab_storage_packager.h
+++ b/chrome/browser/tab/tab_storage_packager.h
@@ -17,28 +17,21 @@
 // This class is used to package tab data for use in the background thread.
 class TabStoragePackager {
  public:
-  TabStoragePackager() = default;
-  virtual ~TabStoragePackager() = default;
+  TabStoragePackager();
+  virtual ~TabStoragePackager();
 
   TabStoragePackager(const TabStoragePackager&) = delete;
   TabStoragePackager& operator=(const TabStoragePackager&) = delete;
 
-  // Packages the tab's data for later use. After packaging a tab, its data
-  // is available via the #ReleasePackage() method.
-  virtual void Package(const TabInterface* tab) = 0;
+  // Packages the tab's data for later use.
+  virtual std::unique_ptr<StoragePackage> Package(const TabInterface* tab) = 0;
 
-  // Packages an aribtrtary tab collection's state for later use. Conceptually
+  // Packages an arbitrary tab collection's state for later use. Conceptually
   // just this collection is represented by the package, not parents or
-  // children's data. However the identity and order of children shold be
-  // captured in this package. After packaging, its is available via the
-  // #ReleasePackage() method.
-  virtual void Package(const TabCollection* collection,
-                       StorageIdMapping& mapping) = 0;
-
-  // Allows the unique ownership of the underlying StoragePackage to be
-  // transferred out of the packager. After this call, the stored package will
-  // be null.
-  virtual std::unique_ptr<StoragePackage> ReleasePackage() = 0;
+  // children's data. However the identity and order of children should be
+  // captured in this package.
+  std::unique_ptr<StoragePackage> Package(const TabCollection* collection,
+                                          StorageIdMapping& mapping);
 };
 
 }  // namespace tabs
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 7ea9f0e..dba688925 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -1556,6 +1556,8 @@
       "//chrome/browser/ui/webui/password_manager:mojo_bindings",
       "//chrome/browser/ui/webui/password_manager:password_manager_ui_handler",
       "//chrome/browser/ui/webui/privacy_sandbox",
+      "//chrome/browser/ui/webui/reload_button",
+      "//chrome/browser/ui/webui/reload_button:impl",
       "//chrome/browser/ui/webui/searchbox",
       "//chrome/browser/ui/webui/settings",
       "//chrome/browser/ui/webui/settings:impl",
@@ -3829,6 +3831,8 @@
       "views/frame/immersive_mode_controller_stub.h",
       "views/frame/main_container_view.cc",
       "views/frame/main_container_view.h",
+      "views/frame/main_region_view.cc",
+      "views/frame/main_region_view.h",
       "views/frame/multi_contents_background_view.cc",
       "views/frame/multi_contents_background_view.h",
       "views/frame/multi_contents_drop_target_view.cc",
@@ -3964,6 +3968,8 @@
       "views/omnibox/omnibox_popup_view_views.h",
       "views/omnibox/omnibox_popup_view_webui.cc",
       "views/omnibox/omnibox_popup_view_webui.h",
+      "views/omnibox/omnibox_popup_webui_content.cc",
+      "views/omnibox/omnibox_popup_webui_content.h",
       "views/omnibox/omnibox_result_view.cc",
       "views/omnibox/omnibox_result_view.h",
       "views/omnibox/omnibox_row_grouped_view.cc",
@@ -4687,7 +4693,6 @@
       # componentized:
       # c/b/ui/browser.h, browser_finder.h, browser_window.h.
       # c/b/ui/passwords/passwords_model_delegate.h, passwords_client_ui_delegate.h.
-      "//chrome/browser/ui/views/zoom",
       "//chrome/browser/ui/webauthn:impl",
       "//chrome/browser/ui/webui/app_service_internals",
       "//chrome/browser/ui/webui/autofill_ml_internals",
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 dfbb5d0..016a8b1 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
@@ -4,6 +4,9 @@
 
 package org.chromium.chrome.browser.ui.edge_to_edge;
 
+import static androidx.core.view.WindowInsetsCompat.Type.systemBars;
+import static androidx.core.view.WindowInsetsCompat.Type.tappableElement;
+
 import static org.chromium.build.NullUtil.assumeNonNull;
 
 import android.app.Activity;
@@ -878,7 +881,7 @@
 
     private static Insets getSystemInsets(
             WindowInsetsCompat windowInsets, boolean hasSeenNonZeroNavigationBarInsets) {
-        Insets systemBarInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
+        Insets systemBarInsets = windowInsets.getInsets(systemBars() + tappableElement());
 
         if (!EdgeToEdgeUtils.isUseBackupNavbarInsetsEnabled()) return systemBarInsets;
 
@@ -891,8 +894,6 @@
                             windowInsets,
                             BackupNavbarInsetsCallSite.EDGE_TO_EDGE_CONTROLLER,
                             EdgeToEdgeFieldTrialImpl.getBackupNavbarInsetsOverrides(),
-                            ChromeFeatureList.sEdgeToEdgeUseBackupNavbarInsetsUseTappable
-                                    .getValue(),
                             ChromeFeatureList.sEdgeToEdgeUseBackupNavbarInsetsUseGestures
                                     .getValue());
             // If applicable, apply backup navbar insets to the left, right, and bottom (not the
diff --git a/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java b/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java
index 3e45238..475cec9c 100644
--- a/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java
+++ b/chrome/browser/ui/android/edge_to_edge/internal/junit/src/org/chromium/chrome/browser/ui/edge_to_edge/EdgeToEdgeControllerTest.java
@@ -1127,21 +1127,19 @@
                         .expectNoRecords(
                                 "Android.EdgeToEdge.BackupNavbarInsets.EdgeToEdgeController")
                         .build()) {
-            when(mInsetObserver.getLastRawWindowInsets())
-                    .thenReturn(SYSTEM_BARS_WITH_TAPPABLE_NAVBAR);
-            mEdgeToEdgeControllerImpl.handleWindowInsets(
-                    mViewMock, SYSTEM_BARS_WITH_TAPPABLE_NAVBAR);
+            when(mInsetObserver.getLastRawWindowInsets()).thenReturn(SYSTEM_BARS_WINDOW_INSETS);
+            mEdgeToEdgeControllerImpl.handleWindowInsets(mViewMock, SYSTEM_BARS_WINDOW_INSETS);
         }
-        assertFalse(mEdgeToEdgeControllerImpl.isDrawingToEdge());
+        assertTrue(mEdgeToEdgeControllerImpl.isDrawingToEdge());
         assertEquals(
                 "The controller should be using the system bar insets.",
-                Insets.of(0, TOP_INSET, 0, BOTTOM_INSET),
+                Insets.of(0, TOP_INSET, 0, 0),
                 mEdgeToEdgeControllerImpl.getAppliedContentViewPaddingForTesting());
         changeObserver.verify(
-                "The system bars are providing a bottom inset and the controller should be drawing"
-                        + " toEdge.",
+                "The system bars are providing a bottom inset and the controller should be"
+                        + " drawing toEdge.",
                 BOTTOM_INSET,
-                /* isDrawingToEdge= */ false,
+                /* isDrawingToEdge= */ true,
                 /* isPageOptInToEdge= */ false);
 
         try (var watcher =
@@ -1150,9 +1148,9 @@
                                 "Android.EdgeToEdge.BackupNavbarInsets.EdgeToEdgeController")
                         .build()) {
             when(mInsetObserver.getLastRawWindowInsets())
-                    .thenReturn(SYSTEM_BARS_WITH_TAPPABLE_MISSING_NAVBAR);
+                    .thenReturn(GESTURE_NAV_INSETS_MISSING_NAVBAR);
             mEdgeToEdgeControllerImpl.handleWindowInsets(
-                    mViewMock, SYSTEM_BARS_WITH_TAPPABLE_MISSING_NAVBAR);
+                    mViewMock, GESTURE_NAV_INSETS_MISSING_NAVBAR);
         }
         assertFalse(mEdgeToEdgeControllerImpl.isDrawingToEdge());
         assertEquals(
@@ -1169,10 +1167,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.EDGE_TO_EDGE_USE_BACKUP_NAVBAR_INSETS,
-        ChromeFeatureList.EDGE_TO_EDGE_MONITOR_CONFIGURATIONS
-    })
+    @EnableFeatures(ChromeFeatureList.EDGE_TO_EDGE_MONITOR_CONFIGURATIONS)
     public void handleWindowInsets_useTappableElementForBackupInsets() {
         TestChangeObserver changeObserver = new TestChangeObserver();
         mEdgeToEdgeControllerImpl.registerObserver(changeObserver);
@@ -1204,9 +1199,8 @@
 
         try (var watcher =
                 HistogramWatcher.newBuilder()
-                        .expectIntRecord(
-                                "Android.EdgeToEdge.BackupNavbarInsets.EdgeToEdgeController",
-                                EdgeToEdgeManager.BackupNavbarInsetsSource.TAPPABLE_ELEMENT)
+                        .expectNoRecords(
+                                "Android.EdgeToEdge.BackupNavbarInsets.EdgeToEdgeController")
                         .build()) {
             when(mInsetObserver.getLastRawWindowInsets())
                     .thenReturn(SYSTEM_BARS_WITH_TAPPABLE_MISSING_NAVBAR);
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 7c40380..e8334edd 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2957,6 +2957,9 @@
       <message name="IDS_CONTEXTMENU_UNPIN" desc="This string is shown in the context menu to remove an existing Custom Tile.">
         Unpin
       </message>
+      <message name="IDS_CONTEXTMENU_VIEW_PAGE_SOURCE" desc="This string is shown in the context menu to display non-editable HTML source code for the current page. [CHAR_LIMIT=30]">
+        View page source
+      </message>
       <message name="IDS_CONTEXTMENU_INSPECT_ELEMENT" desc="This string is shown in the context menu to inspect an element in a web page using the developer tools. [CHAR_LIMIT=30]">
         Inspect
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_VIEW_PAGE_SOURCE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_VIEW_PAGE_SOURCE.png.sha1
new file mode 100644
index 0000000..c87050c7
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_CONTEXTMENU_VIEW_PAGE_SOURCE.png.sha1
@@ -0,0 +1 @@
+2b40272d24724c59b42e353249a1f7761ad901db
\ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java
index 17be8c45..3dfa94c 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionsMenuCoordinator.java
@@ -147,7 +147,11 @@
                                         }
                                     });
                             if (mShouldShowMenuOnInit) {
-                                mExtensionsMenuButton.showMenu();
+                                if (mExtensionsMenuButton.getHost().isMenuShowing()) {
+                                    mExtensionsMenuButton.dismiss();
+                                } else {
+                                    mExtensionsMenuButton.showMenu();
+                                }
                                 mShouldShowMenuOnInit = false;
                             }
                         },
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
index 822147b..0c8c0a33 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java
@@ -9,6 +9,8 @@
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider.ControlsPosition;
 import org.chromium.chrome.browser.browser_controls.TopControlLayer;
 import org.chromium.chrome.browser.browser_controls.TopControlsStacker;
 import org.chromium.chrome.browser.browser_controls.TopControlsStacker.TopControlVisibility;
@@ -25,17 +27,21 @@
     private final ToolbarProgressBar mProgressBarView;
     private final LoadProgressViewBinder mLoadProgressViewBinder;
     private final TopControlsStacker mTopControlsStacker;
+    private final BrowserControlsStateProvider mBrowserControls;
 
     /**
      * @param tabSupplier An observable supplier of the current {@link Tab}.
      * @param progressBarView Toolbar progress bar view.
      * @param topControlsStacker TopControlsStacker to manage the view's y-offset.
+     * @param browserControlsStateProvider BrowserControlsStateProvider to provide control position.
      */
     public LoadProgressCoordinator(
             ObservableSupplier<@Nullable Tab> tabSupplier,
             ToolbarProgressBar progressBarView,
-            TopControlsStacker topControlsStacker) {
+            TopControlsStacker topControlsStacker,
+            BrowserControlsStateProvider browserControlsStateProvider) {
         mProgressBarView = progressBarView;
+        mBrowserControls = browserControlsStateProvider;
         mModel = new PropertyModel(LoadProgressProperties.ALL_KEYS);
         mMediator = new LoadProgressMediator(tabSupplier, mModel);
         mLoadProgressViewBinder = new LoadProgressViewBinder();
@@ -85,6 +91,7 @@
     public int getTopControlVisibility() {
         // TODO(crbug.com/417238089): Possibly add way to notify stacker of visibility changes.
         return mProgressBarView.getVisibility() == View.VISIBLE
+                        && mBrowserControls.getControlsPosition() == ControlsPosition.TOP
                 ? TopControlVisibility.VISIBLE
                 : TopControlVisibility.HIDDEN;
     }
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 7fccc25..414e21d 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
@@ -39,6 +39,8 @@
 import org.chromium.build.annotations.Initializer;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider.ControlsPosition;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.browser_controls.TopControlLayer;
 import org.chromium.chrome.browser.browser_controls.TopControlsStacker;
@@ -105,8 +107,9 @@
     private final Callback<Boolean> mOnXrSpaceModeChanged = this::onXrSpaceModeChanged;
     private @Nullable ObservableSupplier<Boolean> mXrSpaceModeObservableSupplier;
     private @Nullable ObservableSupplierImpl<Integer> mHeightChangedSupplier;
-    private @Nullable TopControlsStacker mTopControlsStacker;
+    private TopControlsStacker mTopControlsStacker;
     private ToolbarDataProvider mToolbarDataProvider;
+    private BrowserControlsStateProvider mBrowserControls;
 
     /**
      * Constructs a new control container.
@@ -356,10 +359,12 @@
 
         // When app header state available, set the state accordingly.
         if (appHeaderState != null && appHeaderState.isInDesktopWindow()) {
+            int topInset =
+                    Math.max(0, appHeaderState.getAppHeaderHeight() - mToolbar.getTabStripHeight());
             backgroundDrawable.setLayerInset(
                     backgroundTabImageIndex,
                     appHeaderState.getLeftPadding(),
-                    0,
+                    topInset,
                     appHeaderState.getRightPadding(),
                     0);
         }
@@ -379,6 +384,7 @@
      * @param layoutStateProviderSupplier Used to check the current layout type.
      * @param fullscreenManager Used to check whether in fullscreen.
      * @param topControlsStacker The TopControlsStacker for |this| to query layer states.
+     * @param browserControlsStateProvider BrowserControlsStateProvider to provide control position.
      */
     @Initializer
     public void setPostInitializationDependencies(
@@ -393,11 +399,13 @@
             OneshotSupplier<LayoutStateProvider> layoutStateProviderSupplier,
             FullscreenManager fullscreenManager,
             TopControlsStacker topControlsStacker,
-            ToolbarDataProvider toolbarDataProvider) {
+            ToolbarDataProvider toolbarDataProvider,
+            BrowserControlsStateProvider browserControlsStateProvider) {
         mToolbar = toolbar;
         mIncognito = isIncognito;
         mTopControlsStacker = topControlsStacker;
         mToolbarDataProvider = toolbarDataProvider;
+        mBrowserControls = browserControlsStateProvider;
         mToolbarDataProvider.addToolbarDataProviderObserver(this);
 
         BooleanSupplier isVisible = () -> this.getVisibility() == View.VISIBLE;
@@ -985,6 +993,7 @@
     public int getTopControlVisibility() {
         // TODO(crbug.com/417238089): Possibly add way to notify stacker of visibility changes.
         return isToolbarContainerFullyVisible()
+                        && mBrowserControls.getControlsPosition() == ControlsPosition.TOP
                 ? TopControlVisibility.VISIBLE
                 : TopControlVisibility.HIDDEN;
     }
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
index eca96d1..db31c41 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/ToolbarControlContainerTest.java
@@ -42,6 +42,7 @@
 import org.chromium.base.test.util.HistogramWatcher;
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.browser_controls.TopControlsStacker;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -115,6 +116,7 @@
     @Mock private IncognitoStateProvider mIncognitoStateProvider;
     @Mock private NewTabPageDelegate mNewTabPageDelegate;
     @Mock private TopControlsStacker mTopControlsStacker;
+    @Mock private BrowserControlsStateProvider mBrowserControls;
 
     private final Supplier<Tab> mTabSupplier = () -> mTab;
     private final ObservableSupplierImpl<Boolean> mCompositorInMotionSupplier =
@@ -480,10 +482,11 @@
         // This is needed for the control container to read the height of the toolbar.
         controlContainer.setToolbarForTesting(mToolbar);
 
-        // Set app header with 10px padding on left, 20px on right, and 50px height.
-        doReturn(50).when(mToolbar).getTabStripHeight();
+        // Set app header with 10px padding on left, 20px on right, and 100px height. Set tab strip
+        // height to 80px. Top inset should be 100 - 80 = 20.
+        doReturn(80).when(mToolbar).getTabStripHeight();
         var appHeaderState =
-                new AppHeaderState(new Rect(0, 0, 100, 50), new Rect(10, 0, 80, 50), true);
+                new AppHeaderState(new Rect(0, 0, 100, 100), new Rect(10, 0, 80, 100), true);
         controlContainer.onAppHeaderStateChanged(appHeaderState);
         assertNotNull(
                 "Control container background is null after app header state change.",
@@ -499,6 +502,20 @@
                 "Right padding for tab drawable is wrong.",
                 20,
                 background.getLayerInsetRight(tabDrawableIndex));
+        assertEquals(
+                "Top inset for tab drawable is wrong.",
+                20,
+                background.getLayerInsetTop(tabDrawableIndex));
+
+        // Set app header with 40px height, and tab strip with 50px height.
+        // Top inset should be max(0, 40 - 50) = 0.
+        appHeaderState = new AppHeaderState(new Rect(0, 0, 100, 40), new Rect(10, 0, 80, 40), true);
+        controlContainer.onAppHeaderStateChanged(appHeaderState);
+        background = (LayerDrawable) controlContainer.getBackground();
+        assertEquals(
+                "Top inset for tab drawable should be 0.",
+                0,
+                background.getLayerInsetTop(tabDrawableIndex));
 
         controlContainer.onAppHeaderStateChanged(new AppHeaderState());
         background = (LayerDrawable) controlContainer.getBackground();
@@ -510,6 +527,10 @@
                 "Right padding for tab drawable is wrong.",
                 0,
                 background.getLayerInsetRight(tabDrawableIndex));
+        assertEquals(
+                "Top inset for tab drawable should be 0.",
+                0,
+                background.getLayerInsetTop(tabDrawableIndex));
     }
 
     @Test
@@ -578,7 +599,8 @@
                 mLayoutStateProviderSupplier,
                 mFullscreenManager,
                 mTopControlsStacker,
-                mToolbarDataProvider);
+                mToolbarDataProvider,
+                mBrowserControls);
 
         ToolbarPhone toolbarPhone = controlContainer.findViewById(R.id.toolbar);
         doReturn(mLocationBarCoordinatorPhone).when(mLocationBarCoordinator).getPhoneCoordinator();
@@ -649,7 +671,8 @@
                 mLayoutStateProviderSupplier,
                 mFullscreenManager,
                 mTopControlsStacker,
-                mToolbarDataProvider);
+                mToolbarDataProvider,
+                mBrowserControls);
         ToolbarControlContainer.ToolbarViewResourceCoordinatorLayout toolbarContainer =
                 controlContainer.findViewById(R.id.toolbar_container);
         toolbarContainer.setVisibility(View.GONE);
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
index 47c7589f..e0642b3f 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TopToolbarCoordinator.java
@@ -21,6 +21,7 @@
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider;
 import org.chromium.chrome.browser.browser_controls.BrowserControlsVisibilityManager;
 import org.chromium.chrome.browser.browser_controls.BrowserStateBrowserControlsVisibilityDelegate;
 import org.chromium.chrome.browser.browser_controls.TopControlsStacker;
@@ -152,6 +153,7 @@
      * @param homeButtonDisplay The {@link HomeButtonDisplay} to manage the display and behavior of
      *     home button(s). Should be null on custom tabs.
      * @param topControlsStacker The TopControlsStacker for child objects to check state from.
+     * @param browserControlsStateProvider BrowserControlsStateProvider instance.
      */
     public TopToolbarCoordinator(
             ToolbarControlContainer controlContainer,
@@ -188,7 +190,8 @@
             @Nullable ForwardButtonCoordinator forwardButtonCoordinator,
             @Nullable HomeButtonDisplay homeButtonDisplay,
             @Nullable ExtensionToolbarCoordinator extensionToolbarCoordinator,
-            TopControlsStacker topControlsStacker) {
+            TopControlsStacker topControlsStacker,
+            BrowserControlsStateProvider browserControlsStateProvider) {
         mToolbarLayout = toolbarLayout;
         mMenuButtonCoordinator = browsingModeMenuButtonCoordinator;
         mControlContainer = controlContainer;
@@ -244,7 +247,8 @@
                 layoutStateProviderSupplier,
                 fullscreenManager,
                 topControlsStacker,
-                toolbarDataProvider);
+                toolbarDataProvider,
+                browserControlsStateProvider);
         mToolbarLayout.initialize(
                 toolbarDataProvider,
                 tabController,
diff --git a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
index a59039f0..08774b0a 100644
--- a/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
+++ b/chrome/browser/ui/ash/desks/desks_client_browsertest.cc
@@ -1870,6 +1870,7 @@
 
   // Enter overview, head over to the desks templates grid and launch the
   // template.
+  ui_test_utils::BrowserCreatedObserver browser_created_observer;
   ash::ToggleOverview();
   ash::WaitForOverviewEnterAnimation();
 
@@ -1878,10 +1879,11 @@
 
   // Wait for the tabs to load.
   content::RunAllTasksUntilIdle();
+  const BrowserWindowInterface* new_browser = browser_created_observer.Wait();
 
   EXPECT_EQ(4u, BrowserList::GetInstance()->size());
   aura::Window* new_browser_window =
-      BrowserList::GetInstance()->get(3)->window()->GetNativeWindow();
+      new_browser->GetWindow()->GetNativeWindow();
 
   // Tests that the stacking is correct while in overview. The parent has other
   // children for overview mode windows, but the first three app windows should
diff --git a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
index 625a673a..f0eff59 100644
--- a/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
+++ b/chrome/browser/ui/ash/projector/projector_navigation_throttle_browsertest.cc
@@ -158,14 +158,14 @@
   }
 
   browser_destroyed_observer.Wait();
-  browser_created_observer.Wait();
+  BrowserWindowInterface* const swa_browser = browser_created_observer.Wait();
 
   // During the navigation, we closed the previous browser to prevent dangling
   // about:blank pages and opened a new app browser for the Projector SWA.
   // There is still only one browser available.
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
-  // Select the first available browser, which should be the SWA.
-  SelectFirstBrowser();
+  // Set the default browser to the swa browser.
+  SetBrowser(swa_browser);
   Browser* app_browser =
       FindSystemWebAppBrowser(profile(), SystemWebAppType::PROJECTOR);
   // Projector SWA is now open.
@@ -267,14 +267,14 @@
       WindowOpenDisposition::CURRENT_TAB,
       ui_test_utils::BrowserTestWaitFlags::BROWSER_TEST_WAIT_FOR_BROWSER);
   browser_destroyed_observer.Wait();
-  browser_created_observer.Wait();
+  BrowserWindowInterface* const swa_browser = browser_created_observer.Wait();
 
   // During the navigation, we closed the previous browser to prevent dangling
   // blank redirect pages and opened a new app browser for the Projector SWA.
   // There is still only one browser available.
   EXPECT_EQ(BrowserList::GetInstance()->size(), 1u);
-  // Select the first available browser, which should be the SWA.
-  SelectFirstBrowser();
+  // Set the default browser to the swa browser.
+  SetBrowser(swa_browser);
   Browser* app_browser =
       FindSystemWebAppBrowser(profile(), SystemWebAppType::PROJECTOR);
 
diff --git a/chrome/browser/ui/ash/system/DEPS b/chrome/browser/ui/ash/system/DEPS
index 4648560..58ff959 100644
--- a/chrome/browser/ui/ash/system/DEPS
+++ b/chrome/browser/ui/ash/system/DEPS
@@ -30,6 +30,7 @@
   "+chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h",
   "+chrome/browser/ui/browser.h",
   "+chrome/browser/ui/browser_navigator_params.h",
+  "+chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h",
   "+chrome/browser/ui/chrome_pages.h",
   "+chrome/browser/ui/managed_ui.h",
   "+chrome/browser/ui/scoped_tabbed_browser_displayer.h",
diff --git a/chrome/browser/ui/ash/system/system_tray_tray_cast_browsertest_media_router_chromeos.cc b/chrome/browser/ui/ash/system/system_tray_tray_cast_browsertest_media_router_chromeos.cc
index 64a85c8e..93007ccb 100644
--- a/chrome/browser/ui/ash/system/system_tray_tray_cast_browsertest_media_router_chromeos.cc
+++ b/chrome/browser/ui/ash/system/system_tray_tray_cast_browsertest_media_router_chromeos.cc
@@ -26,6 +26,7 @@
 #include "chrome/browser/media/router/discovery/access_code/access_code_cast_feature.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/ash/cast_config/cast_config_controller_media_router.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/media_router/access_code_cast/access_code_cast_integration_browsertest.h"
 #include "chromeos/ash/components/login/auth/public/key.h"
@@ -458,7 +459,7 @@
   SetupUserProfile(account_id2_, /* allow_access_code */ true);
 
   // Show the first cast dialog from the browser.
-  SelectFirstBrowser();
+  SetBrowser(GetLastActiveBrowserWindowInterfaceWithAnyProfile());
   EnableAccessCodeCasting();
   ASSERT_TRUE(ShowDialog());
 
diff --git a/chrome/browser/ui/browser_finder_chromeos_browsertest.cc b/chrome/browser/ui/browser_finder_chromeos_browsertest.cc
index 3e301e2..9fdb4742 100644
--- a/chrome/browser/ui/browser_finder_chromeos_browsertest.cc
+++ b/chrome/browser/ui/browser_finder_chromeos_browsertest.cc
@@ -33,7 +33,9 @@
     desks_controller->NewDesk(ash::DesksCreationRemovalSource::kButton);
   }
 
-  void ActivateBrowser(Browser* browser) { browser->window()->Activate(); }
+  void ActivateBrowser(BrowserWindowInterface* browser) {
+    browser->GetWindow()->Activate();
+  }
 
   Browser* CreateTestBrowser() {
     Browser* new_browser = CreateBrowser(browser()->profile());
@@ -52,10 +54,10 @@
   auto* desk_2 = desks_controller->desks()[1].get();
   auto* desk_3 = desks_controller->desks()[2].get();
 
-  Browser* browser_1 = CreateTestBrowser();
+  BrowserWindowInterface* const browser_1 = CreateTestBrowser();
   CloseBrowserSynchronously(browser());
-  SelectFirstBrowser();
-  auto* window_1 = browser_1->window()->GetNativeWindow();
+  SetBrowser(browser_1);
+  auto* window_1 = browser_1->GetWindow()->GetNativeWindow();
   EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
   EXPECT_TRUE(desk_1->is_active());
   EXPECT_TRUE(desks_controller->BelongsToActiveDesk(window_1));
@@ -104,10 +106,10 @@
   auto* desk_2 = desks_controller->desks()[1].get();
   auto* desk_3 = desks_controller->desks()[2].get();
 
-  Browser* browser_1 = CreateTestBrowser();
+  BrowserWindowInterface* const browser_1 = CreateTestBrowser();
   CloseBrowserSynchronously(browser());
-  SelectFirstBrowser();
-  auto* window_1 = browser_1->window()->GetNativeWindow();
+  SetBrowser(browser_1);
+  auto* window_1 = browser_1->GetWindow()->GetNativeWindow();
   EXPECT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
   EXPECT_TRUE(desk_1->is_active());
   EXPECT_TRUE(desks_controller->BelongsToActiveDesk(window_1));
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h
index 05853001..adc73d3 100644
--- a/chrome/browser/ui/browser_list.h
+++ b/chrome/browser/ui/browser_list.h
@@ -56,8 +56,6 @@
   bool empty() const { return browsers_.empty(); }
   size_t size() const { return browsers_.size(); }
 
-  Browser* get(size_t index) const { return browsers_[index]; }
-
   // Enumerate the current browser and the new browser in-order.
   void ForEachCurrentAndNewBrowser(
       base::FunctionRef<void(Browser*)> on_browser);
diff --git a/chrome/browser/ui/browser_window/internal/BUILD.gn b/chrome/browser/ui/browser_window/internal/BUILD.gn
index 30ef0d4c..02df6b9 100644
--- a/chrome/browser/ui/browser_window/internal/BUILD.gn
+++ b/chrome/browser/ui/browser_window/internal/BUILD.gn
@@ -160,6 +160,7 @@
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindowEnumerator.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowCreatorBridge.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowInterfaceIteratorAndroid.java",
+      "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraints.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerFactory.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImpl.java",
@@ -203,6 +204,7 @@
     sources = [
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/AndroidBrowserWindowCreateParamsImplUnitTest.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/BrowserWindowCreatorBridgeUnitTest.java",
+      "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraintsUnitTest.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImplUnitTest.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskTrackerImplUnitTest.java",
       "android/java/src/org/chromium/chrome/browser/ui/browser_window/PendingActionManagerUnitTest.java",
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraints.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraints.java
new file mode 100644
index 0000000..561b18f
--- /dev/null
+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraints.java
@@ -0,0 +1,90 @@
+// Copyright 2025 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.ui.browser_window;
+
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.WindowInsets;
+import android.view.WindowManager;
+
+import androidx.annotation.RequiresApi;
+
+import org.chromium.base.Log;
+import org.chromium.build.annotations.NullMarked;
+import org.chromium.ui.display.DisplayAndroid;
+import org.chromium.ui.display.DisplayUtil;
+
+/** Contains logic for constraints on a {@link ChromeAndroidTask}'s bounds. */
+@NullMarked
+final class ChromeAndroidTaskBoundsConstraints {
+    private static final String TAG = "CATBoundsConstraints";
+
+    /**
+     * The minimal size of a task, for both width and height.
+     *
+     * <p>The Android framework defines the minimal size for framework APIs [1], so the minimal size
+     * here must be no smaller than that.
+     *
+     * <p>Note: Apps don't have access to the Android framework's minimal size as it's not public.
+     *
+     * <p>[1] <a
+     * href="https://cs.android.com/android/platform/superproject/main/+/main:frameworks/base/core/res/res/values/dimens.xml;l=792;drc=37507ae292eef969c507d9438a4692539035f764">Link
+     * to Android framework's minimal size definition</a>
+     */
+    static final int MINIMAL_TASK_SIZE_DP = 220;
+
+    private ChromeAndroidTaskBoundsConstraints() {}
+
+    /**
+     * Applies all constraints on {@code inputBoundsInPx} and returns the adjusted bounds.
+     *
+     * @param inputBoundsInPx The input bounds in pixels.
+     * @param displayAndroid The display the {@code inputBoundsInPx} is for.
+     * @param windowManager The {@link WindowManager} bound to the underlying display of the
+     *     provided {@code displayAndroid}.
+     * @return The adjusted bounds in pixels.
+     */
+    static Rect apply(
+            Rect inputBoundsInPx, DisplayAndroid displayAndroid, WindowManager windowManager) {
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+            Log.w(TAG, "apply() requires Android R+; returning input bounds");
+            return inputBoundsInPx;
+        }
+
+        // 1. Get the max and min sizes.
+        Rect maxBoundsInPx = getMaxBoundsInPx(windowManager);
+        int minWidthAndHeightInPx = DisplayUtil.dpToPx(displayAndroid, MINIMAL_TASK_SIZE_DP);
+
+        // 2. Clamp the input bounds so that it's fully within the max bounds.
+        Rect boundsWithinMaxBoundsInPx = DisplayUtil.clampRect(inputBoundsInPx, maxBoundsInPx);
+        int adjustedLeftInPx = boundsWithinMaxBoundsInPx.left;
+        int adjustedTopInPx = boundsWithinMaxBoundsInPx.top;
+
+        // 3. Make sure the bounds are no smaller than the min size.
+        int adjustedWidthInPx = Math.max(boundsWithinMaxBoundsInPx.width(), minWidthAndHeightInPx);
+        int adjustedHeightInPx =
+                Math.max(boundsWithinMaxBoundsInPx.height(), minWidthAndHeightInPx);
+
+        // 4. Return the adjusted bounds.
+        return new Rect(
+                adjustedLeftInPx,
+                adjustedTopInPx,
+                /* right= */ adjustedLeftInPx + adjustedWidthInPx,
+                /* bottom= */ adjustedTopInPx + adjustedHeightInPx);
+    }
+
+    /** Returns the maximum bounds in pixels. */
+    @RequiresApi(api = Build.VERSION_CODES.R)
+    static Rect getMaxBoundsInPx(WindowManager windowManager) {
+        var insets =
+                windowManager
+                        .getMaximumWindowMetrics()
+                        .getWindowInsets()
+                        .getInsets(WindowInsets.Type.tappableElement());
+        Rect fullscreenBounds = windowManager.getMaximumWindowMetrics().getBounds();
+        return new Rect(
+                0, insets.top, fullscreenBounds.right, fullscreenBounds.bottom - insets.bottom);
+    }
+}
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraintsUnitTest.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraintsUnitTest.java
new file mode 100644
index 0000000..5d6c9ee
--- /dev/null
+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskBoundsConstraintsUnitTest.java
@@ -0,0 +1,107 @@
+// Copyright 2025 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.ui.browser_window;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.when;
+
+import static org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.DEFAULT_FULL_SCREEN_BOUNDS_IN_PX;
+import static org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX;
+import static org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.DEFAULT_MAX_TAPPABLE_INSETS_IN_PX;
+
+import android.annotation.SuppressLint;
+import android.graphics.Rect;
+import android.os.Build;
+import android.view.WindowManager;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.ui.display.DisplayAndroid;
+import org.chromium.ui.display.DisplayUtil;
+
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(sdk = Build.VERSION_CODES.R)
+@SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+public class ChromeAndroidTaskBoundsConstraintsUnitTest {
+
+    private static final float TEST_DIP_SCALE = 2.0f;
+
+    @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private DisplayAndroid mMockDisplayAndroid;
+    @Mock private WindowManager mMockWindowManager;
+
+    @Before
+    public void setUp() {
+        ChromeAndroidTaskUnitTestSupport.mockMaxWindowMetrics(
+                mMockWindowManager,
+                DEFAULT_FULL_SCREEN_BOUNDS_IN_PX,
+                DEFAULT_MAX_TAPPABLE_INSETS_IN_PX);
+        when(mMockDisplayAndroid.getDipScale()).thenReturn(TEST_DIP_SCALE);
+    }
+
+    @Test
+    public void apply_clampsInputBoundsThatAreTooLarge() {
+        // Arrange: create a Rect that's larger than the maximized size.
+        Rect inputBoundsInPx = new Rect(DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX);
+        inputBoundsInPx.offset(/* dx= */ 0, /* dy= */ 10);
+
+        // Act.
+        Rect adjustedBoundsInPx =
+                ChromeAndroidTaskBoundsConstraints.apply(
+                        inputBoundsInPx, mMockDisplayAndroid, mMockWindowManager);
+
+        // Assert.
+        assertEquals(DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX, adjustedBoundsInPx);
+    }
+
+    @Test
+    public void apply_clampsInputBoundsThatAreTooSmall() {
+        // Arrange: create a Rect that's smaller than the smallest size.
+        int minSizeInPx =
+                DisplayUtil.dpToPx(
+                        mMockDisplayAndroid,
+                        ChromeAndroidTaskBoundsConstraints.MINIMAL_TASK_SIZE_DP);
+        int leftInPx = DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX.centerX();
+        int topInPx = DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX.centerY();
+        Rect inputBoundsInPx =
+                new Rect(
+                        leftInPx,
+                        topInPx,
+                        /* right= */ leftInPx + minSizeInPx - 10,
+                        /* bottom= */ topInPx + minSizeInPx - 10);
+
+        // Act.
+        Rect adjustedBoundsInPx =
+                ChromeAndroidTaskBoundsConstraints.apply(
+                        inputBoundsInPx, mMockDisplayAndroid, mMockWindowManager);
+
+        // Assert.
+        Rect expectedBoundsInPx =
+                new Rect(
+                        leftInPx,
+                        topInPx,
+                        /* right= */ leftInPx + minSizeInPx,
+                        /* bottom= */ topInPx + minSizeInPx);
+        assertEquals(expectedBoundsInPx, adjustedBoundsInPx);
+    }
+
+    @Test
+    public void getMaxBoundsInPx() {
+        // Act.
+        Rect maxBounds = ChromeAndroidTaskBoundsConstraints.getMaxBoundsInPx(mMockWindowManager);
+
+        // Assert.
+        assertEquals(DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX, maxBounds);
+    }
+}
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java
index 433b2182..bbbdf03 100644
--- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java
+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImpl.java
@@ -18,7 +18,6 @@
 import android.view.Window;
 import android.view.WindowInsets;
 import android.view.WindowInsetsController;
-import android.view.WindowManager;
 
 import androidx.annotation.GuardedBy;
 import androidx.annotation.RequiresApi;
@@ -856,8 +855,10 @@
         if (activity == null) return false;
         if (activity.isInMultiWindowMode()) {
             // Desktop windowing mode is also a multi-window mode.
-            return getCurrentBoundsInPxLocked(activityWindowAndroid)
-                    .equals(getMaxBoundsInPx(activity.getWindowManager()));
+            Rect maxBoundsInPx =
+                    ChromeAndroidTaskBoundsConstraints.getMaxBoundsInPx(
+                            activity.getWindowManager());
+            return getCurrentBoundsInPxLocked(activityWindowAndroid).equals(maxBoundsInPx);
         } else {
             // In non-multi-window mode, Chrome is maximized by default.
             return true;
@@ -963,8 +964,9 @@
         if (isRestoredInternalLocked(activityWindowAndroid)) {
             mRestoredBoundsInPx = getCurrentBoundsInPxLocked(activityWindowAndroid);
         }
-        Rect maximizedBounds = getMaxBoundsInPx(activity.getWindowManager());
-        setBoundsInPxLocked(activity, activityWindowAndroid.getDisplay(), maximizedBounds);
+        Rect maxBoundsInPx =
+                ChromeAndroidTaskBoundsConstraints.getMaxBoundsInPx(activity.getWindowManager());
+        setBoundsInPxLocked(activity, activityWindowAndroid.getDisplay(), maxBoundsInPx);
     }
 
     @GuardedBy("mActivityWindowAndroidLock")
@@ -1001,19 +1003,12 @@
         Rect boundsInPx =
                 DisplayUtil.scaleToEnclosingRect(
                         boundsInDp, activityWindowAndroid.getDisplay().getDipScale());
-        setBoundsInPxLocked(activity, activityWindowAndroid.getDisplay(), boundsInPx);
-    }
-
-    @RequiresApi(api = VERSION_CODES.R)
-    private static Rect getMaxBoundsInPx(WindowManager windowManager) {
-        var insets =
-                windowManager
-                        .getMaximumWindowMetrics()
-                        .getWindowInsets()
-                        .getInsets(WindowInsets.Type.tappableElement());
-        var fullscreenBounds = windowManager.getMaximumWindowMetrics().getBounds();
-        return new Rect(
-                0, insets.top, fullscreenBounds.right, fullscreenBounds.bottom - insets.bottom);
+        Rect adjustedBoundsInPx =
+                ChromeAndroidTaskBoundsConstraints.apply(
+                        boundsInPx,
+                        activityWindowAndroid.getDisplay(),
+                        activity.getWindowManager());
+        setBoundsInPxLocked(activity, activityWindowAndroid.getDisplay(), adjustedBoundsInPx);
     }
 
     @Nullable Rect getRestoredBoundsInPxForTesting() {
diff --git a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImplUnitTest.java b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImplUnitTest.java
index 8f63b97..e37fb46 100644
--- a/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImplUnitTest.java
+++ b/chrome/browser/ui/browser_window/internal/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskImplUnitTest.java
@@ -6,6 +6,7 @@
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
@@ -21,22 +22,17 @@
 import static org.mockito.Mockito.when;
 
 import static org.chromium.build.NullUtil.assertNonNull;
+import static org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX;
+import static org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX;
 
 import android.annotation.SuppressLint;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.content.res.Configuration;
-import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.Build;
-import android.view.Window;
-import android.view.WindowInsets;
-import android.view.WindowInsetsController;
-import android.view.WindowManager;
 import android.view.WindowMetrics;
 
-import androidx.core.view.WindowInsetsControllerCompat;
-
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -60,6 +56,8 @@
 import org.chromium.chrome.browser.tab.TabLaunchType;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskImpl.State;
+import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.ActivityWindowAndroidMocks;
+import org.chromium.chrome.browser.ui.browser_window.ChromeAndroidTaskUnitTestSupport.ChromeAndroidTaskWithMockDeps;
 import org.chromium.chrome.browser.ui.browser_window.PendingActionManager.PendingAction;
 import org.chromium.ui.display.DisplayUtil;
 import org.chromium.ui.mojom.WindowShowState;
@@ -67,36 +65,57 @@
 import java.util.Arrays;
 
 @RunWith(BaseRobolectricTestRunner.class)
+@Config(sdk = Build.VERSION_CODES.R)
 public class ChromeAndroidTaskImplUnitTest {
 
     @Rule public FakeTimeTestRule mFakeTimeTestRule = new FakeTimeTestRule();
     @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
-    private static ChromeAndroidTaskImpl createChromeAndroidTask() {
-        return createChromeAndroidTask(/* taskId= */ 1);
+    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+    private static ChromeAndroidTaskWithMockDeps createChromeAndroidTaskWithMockDeps(int taskId) {
+        return createChromeAndroidTaskWithMockDeps(taskId, /* isPendingTask= */ false);
     }
 
-    private static ChromeAndroidTaskImpl createChromeAndroidTask(int taskId) {
-        var chromeAndroidTask =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(taskId)
-                        .mChromeAndroidTask;
-        assert chromeAndroidTask instanceof ChromeAndroidTaskImpl;
-        return (ChromeAndroidTaskImpl) chromeAndroidTask;
+    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+    private static ChromeAndroidTaskWithMockDeps createChromeAndroidTaskWithMockDeps(
+            int taskId, boolean isPendingTask) {
+        var chromeAndroidTaskWithMockDeps =
+                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
+                        taskId, /* mockNatives= */ true, isPendingTask);
+        var activityWindowAndroidMocks = chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks;
+        mockDesktopWindowingMode(activityWindowAndroidMocks);
+
+        return chromeAndroidTaskWithMockDeps;
+    }
+
+    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+    private static ActivityWindowAndroidMocks createActivityWindowAndroidMocks(int taskId) {
+        var activityWindowAndroidMocks =
+                ChromeAndroidTaskUnitTestSupport.createActivityWindowAndroidMocks(taskId);
+        mockDesktopWindowingMode(activityWindowAndroidMocks);
+        return activityWindowAndroidMocks;
+    }
+
+    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+    private static void mockDesktopWindowingMode(
+            ActivityWindowAndroidMocks activityWindowAndroidMocks) {
+        ChromeAndroidTaskUnitTestSupport.mockDesktopWindowingMode(activityWindowAndroidMocks);
+
+        // Move mock Activity to the "resumed" state.
+        var mockActivity = activityWindowAndroidMocks.mMockActivity;
+        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.CREATED);
+        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.RESUMED);
     }
 
     @Test
     public void constructor_withActivity_setsActivityWindowAndroid() {
         // Arrange.
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(/* taskId= */ 1);
-        var profile = mock(Profile.class);
-        var tabModel = mock(TabModel.class);
-        when(tabModel.getProfile()).thenReturn(profile);
-
-        // Act.
-        var chromeAndroidTask =
-                new ChromeAndroidTaskImpl(
-                        BrowserWindowType.NORMAL, activityWindowAndroid, tabModel);
+                chromeAndroidTaskWithMockDeps
+                        .mActivityWindowAndroidMocks
+                        .mMockActivityWindowAndroid;
 
         // Assert.
         assertEquals(activityWindowAndroid, chromeAndroidTask.getActivityWindowAndroid());
@@ -105,9 +124,7 @@
     @Test
     public void constructor_withActivity_registersActivityLifecycleObservers() {
         // Arrange & Act.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var mockActivityLifecycleDispatcher =
                 chromeAndroidTaskWithMockDeps
                         .mActivityWindowAndroidMocks
@@ -123,9 +140,7 @@
     @Test
     public void constructor_withActivity_setsTabModelRefAndRegistersTabModelObserver() {
         // Arrange & Act.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var mockTabModel = chromeAndroidTaskWithMockDeps.mMockTabModel;
@@ -156,39 +171,31 @@
     @Test
     public void getProfile_returnsInitialProfile() {
         // Arrange.
-        var profile = mock(Profile.class);
-        var tabModel = mock(TabModel.class);
-        when(tabModel.getProfile()).thenReturn(profile);
-        var chromeAndroidTask =
-                new ChromeAndroidTaskImpl(
-                        BrowserWindowType.NORMAL,
-                        ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(1),
-                        tabModel);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var initialProfile = chromeAndroidTaskWithMockDeps.mMockProfile;
 
         // Act & Assert.
         assertEquals(
                 "The returned Profile should be the same as the one from the constructor.",
-                profile,
+                initialProfile,
                 chromeAndroidTask.getProfile());
     }
 
     @Test
     public void didAddTab_withDifferentProfile_throwsAssertionError() {
         // Arrange.
-        var initialProfile = mock(Profile.class, "InitialProfile");
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask =
+                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var initialProfile = chromeAndroidTaskWithMockDeps.mMockProfile;
+
         var differentProfile = mock(Profile.class, "DifferentProfile");
         var tabWithDifferentProfile = mock(Tab.class);
         when(tabWithDifferentProfile.getProfile()).thenReturn(differentProfile);
-        var tabModel = mock(TabModel.class);
-        when(tabModel.getProfile()).thenReturn(initialProfile);
-
-        var chromeAndroidTask =
-                new ChromeAndroidTaskImpl(
-                        BrowserWindowType.NORMAL,
-                        ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(1),
-                        tabModel);
 
         // Act & Assert.
+        assertNotEquals(initialProfile, differentProfile);
         assertThrows(
                 AssertionError.class,
                 () ->
@@ -203,7 +210,7 @@
     public void getId_returnsTaskId() {
         // Arrange.
         int taskId = 1;
-        var chromeAndroidTask = createChromeAndroidTask(taskId);
+        var chromeAndroidTask = createChromeAndroidTaskWithMockDeps(taskId).mChromeAndroidTask;
 
         // Act & Assert.
         assertEquals(taskId, (int) chromeAndroidTask.getId());
@@ -212,9 +219,10 @@
     @Test
     public void setActivityWindowAndroid_refAlreadyExists_throwsException() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        int taskId = 1;
+        var chromeAndroidTask = createChromeAndroidTaskWithMockDeps(taskId).mChromeAndroidTask;
         var newActivityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(/* taskId= */ 1);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
 
         // Act & Assert.
         assertThrows(
@@ -232,7 +240,7 @@
         var task = new ChromeAndroidTaskImpl(/* pendingId= */ 1, mockParams);
         int taskId = 2;
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
 
         // Act.
         task.setActivityWindowAndroid(activityWindowAndroid, mock(TabModel.class));
@@ -247,9 +255,9 @@
     public void setActivityWindowAndroid_previousRefCleared_setsNewRef() {
         // Arrange.
         int taskId = 1;
-        var chromeAndroidTask = createChromeAndroidTask(taskId);
+        var chromeAndroidTask = createChromeAndroidTaskWithMockDeps(taskId).mChromeAndroidTask;
         var newActivityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         chromeAndroidTask.clearActivityWindowAndroid();
 
         // Act.
@@ -264,9 +272,8 @@
             setActivityWindowAndroid_previousRefCleared_registersNewActivityLifecycleObservers() {
         // Arrange.
         int taskId = 1;
-        var chromeAndroidTask = createChromeAndroidTask(taskId);
-        var newActivityWindowAndroidMocks =
-                ChromeAndroidTaskUnitTestSupport.createActivityWindowAndroidMocks(taskId);
+        var chromeAndroidTask = createChromeAndroidTaskWithMockDeps(taskId).mChromeAndroidTask;
+        var newActivityWindowAndroidMocks = createActivityWindowAndroidMocks(taskId);
         chromeAndroidTask.clearActivityWindowAndroid();
 
         // Act.
@@ -285,14 +292,12 @@
             setActivityWindowAndroid_previousRefCleared_setsNewTabModelRefAndRegistersTabModelObserver() {
         // Arrange.
         int taskId = 1;
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(taskId);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(taskId);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var oldMockTabModel = chromeAndroidTaskWithMockDeps.mMockTabModel;
 
-        var newActivityWindowAndroidMocks =
-                ChromeAndroidTaskUnitTestSupport.createActivityWindowAndroidMocks(taskId);
+        var newActivityWindowAndroidMocks = createActivityWindowAndroidMocks(taskId);
         var newMockTabModel = mock(TabModel.class);
 
         // Act.
@@ -313,9 +318,10 @@
     public void
             setActivityWindowAndroid_previousRefCleared_newRefHasDifferentTaskId_throwsException() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var newActivityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(/* taskId= */ 2);
+                createActivityWindowAndroidMocks(/* taskId= */ 2).mMockActivityWindowAndroid;
         chromeAndroidTask.clearActivityWindowAndroid();
 
         // Act & Assert.
@@ -330,12 +336,13 @@
     public void setActivityWindowAndroid_calledAfterTaskDestroyed_throwsException() {
         // Arrange.
         int taskId = 1;
-        var chromeAndroidTask = createChromeAndroidTask(taskId);
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         chromeAndroidTask.destroy();
 
         // Act & Assert.
         var newActivityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         assertThrows(
                 AssertionError.class,
                 () ->
@@ -346,21 +353,19 @@
     @Test
     public void getActivityWindowAndroid_calledAfterTaskDestroyed_throwsException() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         chromeAndroidTask.destroy();
 
         // Act & Assert.
-        assertThrows(AssertionError.class, () -> chromeAndroidTask.getActivityWindowAndroid());
+        assertThrows(AssertionError.class, chromeAndroidTask::getActivityWindowAndroid);
     }
 
     @Test
     public void clearActivityWindowAndroid_unregistersActivityLifecycleObservers() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var mockActivityLifecycleDispatcher =
                 chromeAndroidTaskWithMockDeps
                         .mActivityWindowAndroidMocks
@@ -379,9 +384,7 @@
     @Test
     public void clearActivityWindowAndroid_unregistersTabModelObserverAndClearTabModelRef() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var mockTabModel = chromeAndroidTaskWithMockDeps.mMockTabModel;
@@ -397,7 +400,8 @@
     @Test
     public void addFeature_addsFeatureToInternalFeatureList() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var mockFeature1 = mock(ChromeAndroidTaskFeature.class);
         var mockFeature2 = mock(ChromeAndroidTaskFeature.class);
 
@@ -414,7 +418,8 @@
     @Test
     public void addFeature_invokesOnAddedToTaskForFeature() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var mockFeature = mock(ChromeAndroidTaskFeature.class);
 
         // Act.
@@ -427,7 +432,8 @@
     @Test
     public void addFeature_calledAfterTaskDestroyed_throwsException() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         chromeAndroidTask.destroy();
 
         // Act & Assert.
@@ -438,9 +444,7 @@
     @Test
     public void getOrCreateNativeBrowserWindowPtr_returnsPtrValueForAliveTask() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
         // Act.
@@ -472,18 +476,20 @@
     @Test
     public void getOrCreateNativeBrowserWindowPtr_calledAfterTaskDestroyed_throwsException() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         chromeAndroidTask.destroy();
 
         // Act & Assert.
-        assertThrows(
-                AssertionError.class, () -> chromeAndroidTask.getOrCreateNativeBrowserWindowPtr());
+        assertThrows(AssertionError.class, chromeAndroidTask::getOrCreateNativeBrowserWindowPtr);
     }
 
     @Test
     public void destroy_clearsActivityWindowAndroid() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                (ChromeAndroidTaskImpl)
+                        createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
 
         // Act.
         chromeAndroidTask.destroy();
@@ -495,7 +501,8 @@
     @Test
     public void destroy_destroysAllFeatures() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var mockFeature1 = mock(ChromeAndroidTaskFeature.class);
         var mockFeature2 = mock(ChromeAndroidTaskFeature.class);
         chromeAndroidTask.addFeature(mockFeature1);
@@ -513,9 +520,7 @@
     @Test
     public void destroy_destroysAndroidBrowserWindow() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var mockAndroidBrowserWindowNatives =
                 assertNonNull(chromeAndroidTaskWithMockDeps.mMockAndroidBrowserWindowNatives);
@@ -531,7 +536,8 @@
     @Test
     public void destroy_setsStateToDestroyed() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         assertFalse(chromeAndroidTask.isDestroyed());
 
         // Act.
@@ -553,7 +559,8 @@
         // its onTaskRemoved() method. No feature should do this in production, but there is nothing
         // preventing this at compile time. Besides ChromeAndroidTask#addFeature(), the feature
         // could also call other ChromeAndroidTask APIs that require the Task state to be "ALIVE".
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var mockFeature = mock(ChromeAndroidTaskFeature.class);
         doAnswer(
                         invocation -> {
@@ -565,17 +572,14 @@
         chromeAndroidTask.addFeature(mockFeature);
 
         // Act & Assert.
-        assertThrows(AssertionError.class, () -> chromeAndroidTask.destroy());
+        assertThrows(AssertionError.class, chromeAndroidTask::destroy);
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void onConfigurationChanged_windowBoundsChanged_invokesOnTaskBoundsChangedForFeature() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
@@ -601,14 +605,11 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void
             onConfigurationChanged_windowBoundsDoesNotChangeInPxOrDp_doesNotInvokeOnTaskBoundsChangedForFeature() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
@@ -640,14 +641,11 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void
             onConfigurationChanged_windowBoundsChangesInPxButNotInDp_doesNotInvokeOnTaskBoundsChangedForFeature() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
@@ -685,9 +683,7 @@
     @Test
     public void onTopResumedActivityChanged_activityIsTopResumed_updatesLastActivatedTime() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         long elapsedRealTime = TimeUtils.elapsedRealtimeMillis();
@@ -703,9 +699,7 @@
     public void
             onTopResumedActivityChanged_activityIsNotTopResumed_doesNotUpdateLastActivatedTime() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         long elapsedRealTime1 = TimeUtils.elapsedRealtimeMillis();
@@ -723,7 +717,9 @@
     @Test
     public void onTopResumedActivityChanged_invokesOnTaskFocusChangedForFeature() {
         // Arrange.
-        var chromeAndroidTask = createChromeAndroidTask();
+        var chromeAndroidTask =
+                (ChromeAndroidTaskImpl)
+                        createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
         var mockFeature = mock(ChromeAndroidTaskFeature.class);
         chromeAndroidTask.addFeature(mockFeature);
 
@@ -739,24 +735,11 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void maximize_maximizeToMaximizedBounds() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
-        var mockWindowManager =
-                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockWindowManager;
-        var mockActivity = chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity;
-
-        // Mock isInMultiWindowMode() to return true.
-        when(mockActivity.isInMultiWindowMode()).thenReturn(true);
-
-        // Mock getMaximizedBounds().
-        var maximizedBounds = mockMaximizedBounds(mockWindowManager);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
         // Act.
         chromeAndroidTask.maximize();
@@ -766,50 +749,27 @@
         verify(apiDelegate).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
 
         var capturedBounds = boundsCaptor.getValue();
-        assertEquals("Not moving to target bound", maximizedBounds, capturedBounds);
+        assertEquals(
+                "Not moving to target bound",
+                DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX,
+                capturedBounds);
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void isMaximized_falseWhenNotMaximized() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
         var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
-        var mockWindowManager =
-                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockWindowManager;
-
-        // Mock isInMultiWindowMode() to return true.
-        var mockWindowMetrics = mock(WindowMetrics.class);
-        when(chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity
-                        .isInMultiWindowMode())
-                .thenReturn(true);
-
-        // Mock getBounds() to return non-maximized bounds.
-        var currentBounds = new Rect(0, 0, 800, 600);
-        when(mockWindowManager.getCurrentWindowMetrics()).thenReturn(mockWindowMetrics);
-        when(mockWindowMetrics.getBounds()).thenReturn(currentBounds);
-
-        // Mock getMaximizedBounds().
-        mockMaximizedBounds(mockWindowManager);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1).mChromeAndroidTask;
 
         // Act & Assert.
         assertFalse(chromeAndroidTask.isMaximized());
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void getBoundsInDp_convertsBoundsInPxToDp() {
         // Arrange: ChromeAndroidTask
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
 
         // Arrange: scaling factor
         float dipScale = 2.0f;
@@ -817,72 +777,31 @@
                 chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
         when(mockDisplayAndroid.getDipScale()).thenReturn(dipScale);
 
-        // Arrange: bounds in pixels
-        Rect boundsInPx = new Rect(10, 20, 800, 600);
-        var mockWindowMetrics = mock(WindowMetrics.class);
-        when(mockWindowMetrics.getBounds()).thenReturn(boundsInPx);
-        var mockWindowManager =
-                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockWindowManager;
-        when(mockWindowManager.getCurrentWindowMetrics()).thenReturn(mockWindowMetrics);
-
         // Act
         Rect boundsInDp = chromeAndroidTask.getBoundsInDp();
 
         // Assert
-        Rect expectedBoundsInDp = DisplayUtil.scaleToEnclosingRect(boundsInPx, 1.0f / dipScale);
+        Rect expectedBoundsInDp =
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
         assertEquals(expectedBoundsInDp, boundsInDp);
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void getRestoredBoundsInDp_convertsBoundsInPxToDp() {
         // 1. Arrange: Create a ChromeAndroidTask with mock dependencies.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var mockDisplayAndroid =
                 chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
-        var mockWindowManager =
-                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockWindowManager;
-        var mockActivity = chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity;
 
         // 2. Arrange: scaling factor
         float dipScale = 2.0f;
         when(mockDisplayAndroid.getDipScale()).thenReturn(dipScale);
 
-        // 3. Arrange: Mock isRestoredInternalLocked() to return true before maximize().
-        // 3.1. Mock isMinimizedInternalLocked() to be false. (Assuming task is visible)
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.CREATED);
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.RESUMED);
-        assertFalse("Task is minimized", chromeAndroidTask.isMinimized());
-
-        // 3.2. Mock isMaximizedInternalLocked() to be false.
-        when(chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity
-                        .isInMultiWindowMode())
-                .thenReturn(true);
-
-        Rect currentBoundsInPx = new Rect(0, 0, 800, 600);
-        var mockCurrentWindowMetrics = mock(WindowMetrics.class);
-        when(mockCurrentWindowMetrics.getBounds()).thenReturn(currentBoundsInPx);
-        when(mockWindowManager.getCurrentWindowMetrics()).thenReturn(mockCurrentWindowMetrics);
-
-        Rect maxBoundsInPx = new Rect(0, 0, 1920, 1080);
-        var mockMaxWindowMetrics = mock(WindowMetrics.class);
-        when(mockMaxWindowMetrics.getBounds()).thenReturn(maxBoundsInPx);
-        when(mockWindowManager.getMaximumWindowMetrics()).thenReturn(mockMaxWindowMetrics);
-
-        var mockMaxWindowInsets = mock(WindowInsets.class);
-        when(mockMaxWindowMetrics.getWindowInsets()).thenReturn(mockMaxWindowInsets);
-        when(mockMaxWindowInsets.getInsets(WindowInsets.Type.tappableElement()))
-                .thenReturn(Insets.of(0, 0, 0, 0));
+        // 3. Arrange: check the default test setup.
+        assertFalse("Task shouldn't be minimized", chromeAndroidTask.isMinimized());
         assertFalse("Task shouldn't be maximized", chromeAndroidTask.isMaximized());
-
-        // 3.3. Mock isFullscreenInternalLocked() to be false.
-        when(mockActivity.getWindow()).thenReturn(mock(Window.class));
-        when(mockMaxWindowInsets.isVisible(WindowInsets.Type.statusBars())).thenReturn(true);
         assertFalse("Task shouldn't be full-screen", chromeAndroidTask.isFullscreen());
 
         // 4. Arrange: Call maximize(). This should set mRestoredBounds to the current bounds.
@@ -893,7 +812,8 @@
 
         // 6. Assert
         Rect expectedBoundsInDp =
-                DisplayUtil.scaleToEnclosingRect(currentBoundsInPx, 1.0f / dipScale);
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
         assertEquals(
                 "restored bounds should be the current bounds in dp",
                 expectedBoundsInDp,
@@ -902,14 +822,10 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void setBoundsInDp_setsNewBoundsInPx() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
         var displayAndroid =
                 chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
@@ -917,7 +833,10 @@
         when(displayAndroid.getDipScale()).thenReturn(dipScale);
 
         // Act.
-        Rect newBoundsInDp = new Rect(10, 20, 800, 600);
+        Rect newBoundsInDp =
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
+        newBoundsInDp.offset(/* dx= */ 10, /* dy= */ 10);
         chromeAndroidTask.setBoundsInDp(newBoundsInDp);
 
         // Assert.
@@ -932,61 +851,98 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
+    public void setBoundsInDp_clampsBoundsThatAreTooLarge() {
+        // Arrange
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
+        var displayAndroid =
+                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
+        float dipScale = 2.0f;
+        when(displayAndroid.getDipScale()).thenReturn(dipScale);
+
+        // Act: set new bounds that are larger than the maximized bounds.
+        Rect newBoundsInDp =
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
+        newBoundsInDp.offset(/* dx= */ 0, /* dy= */ 500);
+        chromeAndroidTask.setBoundsInDp(newBoundsInDp);
+
+        // Assert
+        var boundsCaptor = ArgumentCaptor.forClass(Rect.class);
+        verify(apiDelegate).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
+        assertEquals(
+                "Bounds that are too large should be clamped to the maximized bounds",
+                DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX,
+                boundsCaptor.getValue());
+    }
+
+    @Test
+    @Config(sdk = Build.VERSION_CODES.BAKLAVA)
+    public void setBoundsInDp_clampsBoundsThatAreTooSmall() {
+        // Arrange
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
+        var displayAndroid =
+                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
+        float dipScale = 2.0f;
+        when(displayAndroid.getDipScale()).thenReturn(dipScale);
+
+        // Act: set new bounds that are smaller than the minimum size.
+        Rect maxBoundsInDp =
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
+        Rect newBoundsInDp =
+                new Rect(
+                        maxBoundsInDp.centerX(),
+                        maxBoundsInDp.centerY(),
+                        /* right= */ maxBoundsInDp.centerX()
+                                + ChromeAndroidTaskBoundsConstraints.MINIMAL_TASK_SIZE_DP
+                                - 10,
+                        /* bottom= */ maxBoundsInDp.centerY()
+                                + ChromeAndroidTaskBoundsConstraints.MINIMAL_TASK_SIZE_DP
+                                - 10);
+        chromeAndroidTask.setBoundsInDp(newBoundsInDp);
+
+        // Assert
+        Rect expectedBoundsInDp =
+                new Rect(
+                        maxBoundsInDp.centerX(),
+                        maxBoundsInDp.centerY(),
+                        /* right= */ maxBoundsInDp.centerX()
+                                + ChromeAndroidTaskBoundsConstraints.MINIMAL_TASK_SIZE_DP,
+                        /* bottom= */ maxBoundsInDp.centerY()
+                                + ChromeAndroidTaskBoundsConstraints.MINIMAL_TASK_SIZE_DP);
+        Rect expectedBoundsInPx = DisplayUtil.scaleToEnclosingRect(expectedBoundsInDp, dipScale);
+        var boundsCaptor = ArgumentCaptor.forClass(Rect.class);
+        verify(apiDelegate).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
+        assertEquals(
+                "Bounds that are too small should be adjusted to the minimum size",
+                expectedBoundsInPx,
+                boundsCaptor.getValue());
+    }
+
+    @Test
+    @Config(sdk = Build.VERSION_CODES.BAKLAVA)
     public void restore_restoresToPreviousBounds() {
         // Arrange
-        int taskId = 1;
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(taskId);
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
         var chromeAndroidTask =
                 (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
-        var mockActivity = chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity;
-        var mockWindowManager =
-                chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockWindowManager;
-        var mockWindow = mock(Window.class);
-        when(mockActivity.getWindow()).thenReturn(mockWindow);
-        var mockWindowInsetsController = mock(WindowInsetsController.class);
-        when(mockWindow.getInsetsController()).thenReturn(mockWindowInsetsController);
-        when(mockWindowInsetsController.getSystemBarsBehavior())
-                .thenReturn(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
 
-        // Mock isRestoredInternalLocked() to return true before maximize().
-        // 1. Mock isMinimizedInternalLocked() to be false. (Assuming task is visible)
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.CREATED);
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.RESUMED);
-        assertFalse("Task is minimized", chromeAndroidTask.isMinimized());
-
-        // 2. Mock isMaximizedInternalLocked() to be false.
-        // Mock isInMultiWindowMode() to return true.
-        var mockWindowMetrics = mock(WindowMetrics.class);
-        when(mockWindowManager.getCurrentWindowMetrics()).thenReturn(mockWindowMetrics);
-        when(chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity
-                        .isInMultiWindowMode())
-                .thenReturn(true);
-
-        var restoredBounds = new Rect(0, 0, 800, 600);
-        when(mockWindowMetrics.getBounds()).thenReturn(restoredBounds);
-
-        var mockMaxWindowMetrics = mock(WindowMetrics.class);
-        var mockMaxWindowInsets = mock(WindowInsets.class);
-        when(mockWindowManager.getMaximumWindowMetrics()).thenReturn(mockMaxWindowMetrics);
-        when(mockMaxWindowMetrics.getWindowInsets()).thenReturn(mockMaxWindowInsets);
-        when(mockMaxWindowInsets.getInsets(WindowInsets.Type.tappableElement()))
-                .thenReturn(Insets.of(0, 0, 0, 0));
-        when(mockMaxWindowMetrics.getBounds()).thenReturn(new Rect(0, 0, 1920, 1080));
-        assertFalse("Task is maximized", chromeAndroidTask.isMaximized());
-
-        // 3. Mock isFullscreenInternalLocked() to be false.
-        when(mockMaxWindowInsets.isVisible(WindowInsets.Type.statusBars())).thenReturn(true);
-        assertFalse("Task is fullscreen", chromeAndroidTask.isFullscreen());
+        // Check the default test setup.
+        assertFalse("Task shouldn't be minimized", chromeAndroidTask.isMinimized());
+        assertFalse("Task shouldn't be maximized", chromeAndroidTask.isMaximized());
+        assertFalse("Task shouldn't be fullscreen", chromeAndroidTask.isFullscreen());
 
         // Call maximize(). This should set mRestoredBounds to the current bounds.
         chromeAndroidTask.maximize();
 
         assertEquals(
                 "restored bounds should be set to the current bounds",
-                restoredBounds,
+                DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX,
                 chromeAndroidTask.getRestoredBoundsInPxForTesting());
 
         // Act
@@ -997,22 +953,19 @@
         verify(apiDelegate, times(2)).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
 
         var capturedBounds = boundsCaptor.getValue();
-        assertEquals("Not moving to target bound", restoredBounds, capturedBounds);
+        assertEquals(
+                "Not moving to target bound", DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX, capturedBounds);
     }
 
     @Test
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void minimize_alreadyMinimized_doesNotMinimizeAgain() {
         // Arrange.
-        var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1);
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTaskWithMockDeps = createChromeAndroidTaskWithMockDeps(/* taskId= */ 1);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         var activity = chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockActivity;
 
         // Mock isMinimized() to return true.
-        ApplicationStatus.onStateChangeForTesting(activity, ActivityState.CREATED);
+        ApplicationStatus.onStateChangeForTesting(activity, ActivityState.PAUSED);
         ApplicationStatus.onStateChangeForTesting(activity, ActivityState.STOPPED);
         assertTrue("Task is minimized", chromeAndroidTask.isMinimized());
 
@@ -1105,7 +1058,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void maximize_whenPending_enqueuesPendingAction() {
         // Arrange.
         var mockParams =
@@ -1122,7 +1074,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void minimize_whenPending_enqueuesPendingAction() {
         // Arrange.
         var mockParams =
@@ -1226,7 +1177,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void isMaximized_whenPending_withPendingMaximize_returnsTrue() {
         // Arrange.
         var mockParams =
@@ -1240,7 +1190,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void isMaximized_whenPending_withMaximizedStateInCreateParams_returnsTrue() {
         // Arrange.
         var mockParams =
@@ -1253,7 +1202,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void
             isMaximized_whenPending_withDefaultStateInCreateParams_withoutPendingMaximize_returnsFalse() {
         // Arrange.
@@ -1266,7 +1214,6 @@
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void isMinimized_whenPending_withPendingMinimize_returnsTrue() {
         // Arrange.
         var mockParams =
@@ -1461,12 +1408,10 @@
         int taskId = 2;
         // Arrange: Setup WindowAndroid.
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         var mockActivity = activityWindowAndroid.getActivity().get();
         var mockActivityManager =
                 (ActivityManager) mockActivity.getSystemService(Context.ACTIVITY_SERVICE);
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.CREATED);
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.RESUMED);
 
         // Act.
         task.setActivityWindowAndroid(activityWindowAndroid, mock(TabModel.class));
@@ -1486,7 +1431,7 @@
         int taskId = 2;
         // Arrange: Setup WindowAndroid.
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         var mockActivity = activityWindowAndroid.getActivity().get();
 
         // Act.
@@ -1507,7 +1452,7 @@
         // Arrange: Setup WindowAndroid.
         int taskId = 2;
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         var mockActivity = activityWindowAndroid.getActivity().get();
         var mockActivityManager =
                 (ActivityManager) mockActivity.getSystemService(Context.ACTIVITY_SERVICE);
@@ -1521,12 +1466,10 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void setActivityWindowAndroid_fromPendingState_dispatchesPendingMaximize() {
         // Arrange: Create pending task.
         var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1, /* mockNatives= */ true, /* isPendingTask= */ true);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1, /* isPendingTask= */ true);
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
         var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         // Arrange: Request MAXIMIZE on a pending task.
@@ -1536,13 +1479,6 @@
                 chromeAndroidTaskWithMockDeps
                         .mActivityWindowAndroidMocks
                         .mMockActivityWindowAndroid;
-        var mockActivity = activityWindowAndroid.getActivity().get();
-        when(mockActivity.isInMultiWindowMode()).thenReturn(true);
-        var maximizedBounds =
-                mockMaximizedBounds(
-                        chromeAndroidTaskWithMockDeps
-                                .mActivityWindowAndroidMocks
-                                .mMockWindowManager);
 
         // Act.
         chromeAndroidTask.setActivityWindowAndroid(
@@ -1552,26 +1488,22 @@
         var boundsCaptor = ArgumentCaptor.forClass(Rect.class);
         verify(apiDelegate).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
         var capturedBounds = boundsCaptor.getValue();
-        assertEquals(maximizedBounds, capturedBounds);
+        assertEquals(DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX, capturedBounds);
     }
 
     @Test
-    @Config(sdk = Build.VERSION_CODES.R)
     public void setActivityWindowAndroid_fromPendingState_dispatchesPendingMinimize() {
         // Arrange: Create pending task.
         var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1, /* mockNatives= */ true, /* isPendingTask= */ true);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1, /* isPendingTask= */ true);
         var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         // Arrange: Request MINIMIZE on a pending task.
         chromeAndroidTask.minimize();
         // Arrange: Setup WindowAndroid.
         int taskId = 2;
         var activityWindowAndroid =
-                ChromeAndroidTaskUnitTestSupport.createMockActivityWindowAndroid(taskId);
+                createActivityWindowAndroidMocks(taskId).mMockActivityWindowAndroid;
         var mockActivity = activityWindowAndroid.getActivity().get();
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.CREATED);
-        ApplicationStatus.onStateChangeForTesting(mockActivity, ActivityState.RESUMED);
 
         // Act.
         chromeAndroidTask.setActivityWindowAndroid(
@@ -1583,16 +1515,13 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void
             setActivityWindowAndroid_fromPendingState_withNonEmptyPendingBounds_dispatchesPendingRestore() {
         // Arrange: Create pending task.
         var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1, /* mockNatives= */ true, /* isPendingTask= */ true);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1, /* isPendingTask= */ true);
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         // Arrange: Setup display parameters.
         var displayAndroid =
                 chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
@@ -1622,16 +1551,13 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void
             setActivityWindowAndroid_fromPendingState_withEmptyPendingBounds_ignoresPendingRestore() {
         // Arrange: Create pending task.
         var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1, /* mockNatives= */ true, /* isPendingTask= */ true);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1, /* isPendingTask= */ true);
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
         // Arrange: Request RESTORE on a pending task.
         chromeAndroidTask.restore();
         // Arrange: Setup WindowAndroid.
@@ -1650,28 +1576,29 @@
 
     @Test
     @Config(sdk = Build.VERSION_CODES.BAKLAVA)
-    @SuppressLint("NewApi" /* @Config already specifies the required SDK */)
     public void setActivityWindowAndroid_fromPendingState_dispatchesPendingSetBounds() {
         // Arrange: Create pending task.
         var chromeAndroidTaskWithMockDeps =
-                ChromeAndroidTaskUnitTestSupport.createChromeAndroidTaskWithMockDeps(
-                        /* taskId= */ 1, /* mockNatives= */ true, /* isPendingTask= */ true);
+                createChromeAndroidTaskWithMockDeps(/* taskId= */ 1, /* isPendingTask= */ true);
+        var chromeAndroidTask = chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+        var activityWindowAndroid =
+                chromeAndroidTaskWithMockDeps
+                        .mActivityWindowAndroidMocks
+                        .mMockActivityWindowAndroid;
         var apiDelegate = chromeAndroidTaskWithMockDeps.mMockAconfigFlaggedApiDelegate;
-        var chromeAndroidTask =
-                (ChromeAndroidTaskImpl) chromeAndroidTaskWithMockDeps.mChromeAndroidTask;
+
         // Arrange: Setup display parameters.
         var displayAndroid =
                 chromeAndroidTaskWithMockDeps.mActivityWindowAndroidMocks.mMockDisplayAndroid;
         float dipScale = 2.0f;
         when(displayAndroid.getDipScale()).thenReturn(dipScale);
+
         // Arrange: Request SET_BOUNDS on a pending task.
-        Rect pendingBoundsInDp = new Rect(10, 20, 800, 600);
+        Rect pendingBoundsInDp =
+                DisplayUtil.scaleToEnclosingRect(
+                        DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX, 1.0f / dipScale);
+        pendingBoundsInDp.offset(/* dx= */ 10, /* dy= */ 10);
         chromeAndroidTask.setBoundsInDp(pendingBoundsInDp);
-        // Arrange: Setup WindowAndroid.
-        var activityWindowAndroid =
-                chromeAndroidTaskWithMockDeps
-                        .mActivityWindowAndroidMocks
-                        .mMockActivityWindowAndroid;
 
         // Act.
         chromeAndroidTask.setActivityWindowAndroid(
@@ -1683,22 +1610,4 @@
         verify(apiDelegate).moveTaskTo(any(), anyInt(), boundsCaptor.capture());
         assertEquals(expectedBoundsInPx, boundsCaptor.getValue());
     }
-
-    /**
-     * This method sets up mock insets and window metrics to simulate and return maximized window
-     * bounds when {@link WindowManager#getMaximumWindowMetrics()} is invoked from {@code
-     * mockWindowManager}.
-     */
-    private static Rect mockMaximizedBounds(WindowManager mockWindowManager) {
-        var mockMaxWindowMetrics = mock(WindowMetrics.class);
-        var mockMaxWindowInsets = mock(WindowInsets.class);
-        when(mockWindowManager.getMaximumWindowMetrics()).thenReturn(mockMaxWindowMetrics);
-        when(mockMaxWindowMetrics.getWindowInsets()).thenReturn(mockMaxWindowInsets);
-        var tappableInsets = Insets.of(0, 10, 0, 20);
-        when(mockMaxWindowInsets.getInsets(WindowInsets.Type.tappableElement()))
-                .thenReturn(tappableInsets);
-        var fullscreenBounds = new Rect(0, 0, 1920, 1080);
-        when(mockMaxWindowMetrics.getBounds()).thenReturn(fullscreenBounds);
-        return new Rect(0, 10, 1920, 1060);
-    }
 }
diff --git a/chrome/browser/ui/browser_window/internal/browser_window_features.cc b/chrome/browser/ui/browser_window/internal/browser_window_features.cc
index 4b347e9..ef92de0 100644
--- a/chrome/browser/ui/browser_window/internal/browser_window_features.cc
+++ b/chrome/browser/ui/browser_window/internal/browser_window_features.cc
@@ -87,7 +87,6 @@
 #include "chrome/browser/ui/views/interaction/browser_elements_views_impl.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/media_router/cast_browser_controller.h"
 #include "chrome/browser/ui/views/new_tab_footer/footer_controller.h"
 #include "chrome/browser/ui/views/profiles/profile_customization_bubble_sync_controller.h"
@@ -762,10 +761,6 @@
       std::make_unique<WindowsTaskbarIconUpdater>(*browser_view);
 #endif
 
-  zoom_bubble_coordinator_ =
-      GetUserDataFactory().CreateInstance<ZoomBubbleCoordinator>(*browser_,
-                                                                 *browser_view);
-
   user_education_->Init(browser_view);
 
   find_bar_owner_ = std::make_unique<FindBarOwnerViews>(browser_view);
@@ -805,8 +800,6 @@
   }
 #endif
 
-  zoom_bubble_coordinator_.reset();
-
   comments_side_panel_coordinator_.reset();
 
   history_clusters_side_panel_coordinator_.reset();
diff --git a/chrome/browser/ui/browser_window/public/browser_window_features.h b/chrome/browser/ui/browser_window/public/browser_window_features.h
index 66cb990..faf0e6e 100644
--- a/chrome/browser/ui/browser_window/public/browser_window_features.h
+++ b/chrome/browser/ui/browser_window/public/browser_window_features.h
@@ -82,7 +82,6 @@
 class TranslateBubbleController;
 class UpgradeNotificationController;
 class WebUIBrowserSidePanelUI;
-class ZoomBubbleCoordinator;
 
 #if BUILDFLAG(IS_WIN)
 class WindowsTaskbarIconUpdater;
@@ -466,7 +465,6 @@
   ImmersiveModeController* immersive_mode_controller() {
     return immersive_mode_controller_.get();
   }
-
   const ImmersiveModeController* immersive_mode_controller() const {
     return immersive_mode_controller_.get();
   }
@@ -600,8 +598,6 @@
   std::unique_ptr<DownloadToolbarUIController> download_toolbar_ui_controller_;
 #endif
 
-  std::unique_ptr<ZoomBubbleCoordinator> zoom_bubble_coordinator_;
-
   std::unique_ptr<ActorUiWindowController> actor_ui_window_controller_;
 
   std::unique_ptr<ActorBorderViewController> actor_border_view_controller_;
diff --git a/chrome/browser/ui/browser_window/test/BUILD.gn b/chrome/browser/ui/browser_window/test/BUILD.gn
index a3f56ec..9596d379d 100644
--- a/chrome/browser/ui/browser_window/test/BUILD.gn
+++ b/chrome/browser/ui/browser_window/test/BUILD.gn
@@ -22,6 +22,8 @@
       "//chrome/browser/ui/browser_window/internal:java",
       "//chrome/browser/ui/browser_window/public/android:java",
       "//chrome/browser/util:java",
+      "//third_party/androidx:androidx_annotation_annotation_java",
+      "//third_party/androidx:androidx_core_core_java",
       "//third_party/mockito:mockito_java",
       "//ui/android:ui_no_recycler_view_java",
       "//ui/base/mojom:ui_base_types_java",
diff --git a/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskUnitTestSupport.java b/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskUnitTestSupport.java
index 15b0f8c..934c5a30 100644
--- a/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskUnitTestSupport.java
+++ b/chrome/browser/ui/browser_window/test/android/java/src/org/chromium/chrome/browser/ui/browser_window/ChromeAndroidTaskUnitTestSupport.java
@@ -7,6 +7,7 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.any;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockingDetails;
 import static org.mockito.Mockito.when;
 import static org.mockito.Mockito.withSettings;
 
@@ -14,8 +15,17 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.AppTask;
 import android.content.Context;
+import android.graphics.Insets;
 import android.graphics.Rect;
+import android.os.Build.VERSION_CODES;
+import android.view.Window;
+import android.view.WindowInsets;
+import android.view.WindowInsetsController;
 import android.view.WindowManager;
+import android.view.WindowMetrics;
+
+import androidx.annotation.RequiresApi;
+import androidx.core.view.WindowInsetsControllerCompat;
 
 import org.chromium.base.AconfigFlaggedApiDelegate;
 import org.chromium.build.annotations.NullMarked;
@@ -40,8 +50,45 @@
 public final class ChromeAndroidTaskUnitTestSupport {
 
     /**
-     * It's common for callers of {@link #createMockActivityWindowAndroid()} or {@link
-     * #createActivityWindowAndroidMocks()} to pass the resulting mocks into a {@link
+     * Default bounds (in pixels) intended for {@link WindowManager#getCurrentWindowMetrics()}.
+     *
+     * @see #mockDesktopWindowingMode
+     */
+    public static final Rect DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX = new Rect(10, 20, 800, 600);
+
+    /**
+     * Default bounds (in pixels) intended for {@link WindowManager#getMaximumWindowMetrics()}.
+     *
+     * @see #mockDesktopWindowingMode
+     */
+    public static final Rect DEFAULT_FULL_SCREEN_BOUNDS_IN_PX = new Rect(0, 0, 1920, 1080);
+
+    /**
+     * Default tappable {@link Insets} (in pixels) intended for max window metrics in {@link
+     * WindowManager}.
+     *
+     * @see #mockDesktopWindowingMode
+     */
+    public static final Insets DEFAULT_MAX_TAPPABLE_INSETS_IN_PX = Insets.of(0, 10, 0, 20);
+
+    /**
+     * Default maximized window bounds (in desktop-windowing mode) when {@link WindowManager} is
+     * configured using {@link #DEFAULT_FULL_SCREEN_BOUNDS_IN_PX} and {@link
+     * #DEFAULT_MAX_TAPPABLE_INSETS_IN_PX}.
+     *
+     * @see #mockDesktopWindowingMode
+     */
+    public static final Rect DEFAULT_MAXIMIZED_WINDOW_BOUNDS_IN_PX =
+            new Rect(
+                    0,
+                    DEFAULT_MAX_TAPPABLE_INSETS_IN_PX.top,
+                    DEFAULT_FULL_SCREEN_BOUNDS_IN_PX.right,
+                    DEFAULT_FULL_SCREEN_BOUNDS_IN_PX.bottom
+                            - DEFAULT_MAX_TAPPABLE_INSETS_IN_PX.bottom);
+
+    /**
+     * It's common for callers of {@link #createMockActivityWindowAndroid} or {@link
+     * #createActivityWindowAndroidMocks} to pass the resulting mocks into a {@link
      * ChromeAndroidTaskImpl}, which only holds it as a weak reference. Pinning the mocks here
      * ensures that they don't get garbage collected in the middle of a unit test.
      *
@@ -276,4 +323,84 @@
 
         return mockParams;
     }
+
+    /** See {@link #mockDesktopWindowingMode(ActivityWindowAndroidMocks, Rect, Rect, Insets)}. */
+    @RequiresApi(api = VERSION_CODES.R)
+    static void mockDesktopWindowingMode(ActivityWindowAndroidMocks activityWindowAndroidMocks) {
+        mockDesktopWindowingMode(
+                activityWindowAndroidMocks,
+                DEFAULT_CURRENT_WINDOW_BOUNDS_IN_PX,
+                DEFAULT_FULL_SCREEN_BOUNDS_IN_PX,
+                DEFAULT_MAX_TAPPABLE_INSETS_IN_PX);
+    }
+
+    /**
+     * Configures the provided {@code ActivityWindowAndroidMocks} to meet the expectations of
+     * desktop windowing mode.
+     *
+     * <p>Only use this in Robolectric tests. Native unit tests run on an emulator, and Mockito will
+     * fail to mock "final" framework classes like {@link WindowMetrics}.
+     *
+     * @param activityWindowAndroidMocks The mocks to configure.
+     * @param currentWindowBoundsInPx Bounds (in pixels) intended for {@link
+     *     WindowManager#getCurrentWindowMetrics()}.
+     * @param fullScreenWindowBoundsInPx Bounds (in pixels) intended for {@link
+     *     WindowManager#getMaximumWindowMetrics()}.
+     * @param maxTappableInsetsInPx {@link Insets} (in pixels) intended for max window metrics in
+     *     {@link WindowManager}.
+     */
+    @RequiresApi(api = VERSION_CODES.R)
+    static void mockDesktopWindowingMode(
+            ActivityWindowAndroidMocks activityWindowAndroidMocks,
+            Rect currentWindowBoundsInPx,
+            Rect fullScreenWindowBoundsInPx,
+            Insets maxTappableInsetsInPx) {
+        var mockActivity = activityWindowAndroidMocks.mMockActivity;
+        var mockWindowManager = activityWindowAndroidMocks.mMockWindowManager;
+
+        // Activity should be in multi-window mode.
+        // (Desktop windowing mode is a multi-window mode.)
+        when(mockActivity.isInMultiWindowMode()).thenReturn(true);
+
+        // Config system bars behavior.
+        var mockWindow = mock(Window.class);
+        var mockWindowInsetsController = mock(WindowInsetsController.class);
+        when(mockWindowInsetsController.getSystemBarsBehavior())
+                .thenReturn(WindowInsetsControllerCompat.BEHAVIOR_DEFAULT);
+        when(mockWindow.getInsetsController()).thenReturn(mockWindowInsetsController);
+        when(mockActivity.getWindow()).thenReturn(mockWindow);
+
+        mockCurrentWindowMetrics(mockWindowManager, currentWindowBoundsInPx);
+        mockMaxWindowMetrics(mockWindowManager, fullScreenWindowBoundsInPx, maxTappableInsetsInPx);
+
+        // Connect mock WindowManager to mock Activity.
+        when(mockActivity.getWindowManager()).thenReturn(mockWindowManager);
+    }
+
+    @RequiresApi(api = VERSION_CODES.R)
+    static void mockCurrentWindowMetrics(
+            WindowManager mockWindowManager, Rect currentWindowBoundsInPx) {
+        assert mockingDetails(mockWindowManager).isMock();
+
+        var currentWindowMetrics = mock(WindowMetrics.class);
+        when(currentWindowMetrics.getBounds()).thenReturn(currentWindowBoundsInPx);
+        when(mockWindowManager.getCurrentWindowMetrics()).thenReturn(currentWindowMetrics);
+    }
+
+    @RequiresApi(api = VERSION_CODES.R)
+    static void mockMaxWindowMetrics(
+            WindowManager mockWindowManager,
+            Rect fullScreenWindowBoundsInPx,
+            Insets maxTappableInsetsInPx) {
+        assert mockingDetails(mockWindowManager).isMock();
+
+        var maxWindowInsets = mock(WindowInsets.class);
+        when(maxWindowInsets.isVisible(WindowInsets.Type.statusBars())).thenReturn(true);
+        when(maxWindowInsets.getInsets(WindowInsets.Type.tappableElement()))
+                .thenReturn(maxTappableInsetsInPx);
+        var maxWindowMetrics = mock(WindowMetrics.class);
+        when(maxWindowMetrics.getBounds()).thenReturn(fullScreenWindowBoundsInPx);
+        when(maxWindowMetrics.getWindowInsets()).thenReturn(maxWindowInsets);
+        when(mockWindowManager.getMaximumWindowMetrics()).thenReturn(maxWindowMetrics);
+    }
 }
diff --git a/chrome/browser/ui/cocoa/tab_group_menu_bridge.h b/chrome/browser/ui/cocoa/tab_group_menu_bridge.h
index 52552e0..8d8065f2 100644
--- a/chrome/browser/ui/cocoa/tab_group_menu_bridge.h
+++ b/chrome/browser/ui/cocoa/tab_group_menu_bridge.h
@@ -12,7 +12,7 @@
 #include "base/task/cancelable_task_tracker.h"
 #include "chrome/app/chrome_command_ids.h"
 #import "chrome/browser/ui/cocoa/main_menu_item.h"
-#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h"
 #include "components/saved_tab_groups/public/tab_group_sync_service.h"
 
 using TabGroupMenuAction = tab_groups::TabGroupMenuAction;
diff --git a/chrome/browser/ui/cocoa/tab_group_menu_bridge.mm b/chrome/browser/ui/cocoa/tab_group_menu_bridge.mm
index 7ead393..24e90dc45 100644
--- a/chrome/browser/ui/cocoa/tab_group_menu_bridge.mm
+++ b/chrome/browser/ui/cocoa/tab_group_menu_bridge.mm
@@ -108,15 +108,24 @@
     return;
   }
 
+  std::vector<base::Uuid> group_ids =
+      tab_groups::TabGroupMenuUtils::GetGroupsForDisplaySortedByCreationTime(
+          tab_group_service_);
+  if (group_ids.empty()) {
+    return;
+  }
+
   [menu addItem:[NSMenuItem separatorItem]];
 
-  for (const tab_groups::SavedTabGroup& group :
-       tab_group_service_->GetAllGroups()) {
+  for (const base::Uuid& uuid : group_ids) {
+    const std::optional<tab_groups::SavedTabGroup> group =
+        tab_group_service_->GetGroup(uuid);
+    if (!group) {
+      continue;
+    }
+
     NSString* title = base::SysUTF16ToNSString(
-        group.title().empty() ? l10n_util::GetPluralStringFUTF16(
-                                    IDS_SAVED_TAB_GROUP_TABS_COUNT,
-                                    static_cast<int>(group.saved_tabs().size()))
-                              : group.title());
+        tab_groups::TabGroupMenuUtils::GetMenuTextForGroup(*group));
 
     // Add menu item for each group.
     NSMenuItem* item = [[NSMenuItem alloc] initWithTitle:title
@@ -125,28 +134,27 @@
     // Set the icon of the group to the group color circle.
     const auto& color_provider =
         [AppController.sharedController lastActiveColorProvider];
-    const ui::ColorId color_id = GetTabGroupContextMenuColorId(group.color());
+    const ui::ColorId color_id = GetTabGroupContextMenuColorId(group->color());
     gfx::ImageSkia group_icon = gfx::CreateVectorIcon(
         kTabGroupIcon, gfx::kFaviconSize, color_provider.GetColor(color_id));
     item.image = NSImageFromImageSkia(group_icon);
 
     NSMenu* submenu = [[NSMenu alloc] init];
-    base::Uuid uuid = group.saved_guid();
     // Add static menu items for submenu.
     [submenu addItem:CreateStaticSubmenuItem(
                          IDS_OPEN_GROUP_IN_BROWSER_MENU,
                          TabGroupMenuAction::Type::OPEN_IN_BROWSER, uuid)];
     [submenu
         addItem:CreateStaticSubmenuItem(
-                    group.local_group_id().has_value()
+                    group->local_group_id().has_value()
                         ? IDS_TAB_GROUP_HEADER_CXMENU_MOVE_GROUP_TO_NEW_WINDOW
                         : IDS_TAB_GROUP_HEADER_CXMENU_OPEN_GROUP_IN_NEW_WINDOW,
                     TabGroupMenuAction::Type::OPEN_OR_MOVE_TO_NEW_WINDOW,
                     uuid)];
     [submenu
         addItem:CreateStaticSubmenuItem(
-                    group.is_pinned() ? IDS_TAB_GROUP_HEADER_CXMENU_UNPIN_GROUP
-                                      : IDS_TAB_GROUP_HEADER_CXMENU_PIN_GROUP,
+                    group->is_pinned() ? IDS_TAB_GROUP_HEADER_CXMENU_UNPIN_GROUP
+                                       : IDS_TAB_GROUP_HEADER_CXMENU_PIN_GROUP,
                     TabGroupMenuAction::Type::PIN_OR_UNPIN_GROUP, uuid)];
     bool is_owner =
         tab_groups::SavedTabGroupUtils::IsOwnerOfSharedTabGroup(profile_, uuid);
@@ -159,15 +167,17 @@
     [submenu addItem:[NSMenuItem separatorItem]];
 
     // Add menu items for each tab in submenu.
-    for (const tab_groups::SavedTabGroupTab& tab : group.saved_tabs()) {
+    for (const tab_groups::SavedTabGroupTab& tab : group->saved_tabs()) {
       NSMenuItem* tab_menu_item = [[NSMenuItem alloc]
-          initWithTitle:base::SysUTF16ToNSString(tab.title())
+          initWithTitle:base::SysUTF16ToNSString(
+                            tab_groups::TabGroupMenuUtils::GetMenuTextForTab(
+                                tab))
                  action:@selector(onMenuItem:)
           keyEquivalent:@""];
       tab_menu_item.target = menu_listener_;
 
       const ui::ImageModel image = favicon::GetDefaultFaviconModel(
-          GetTabGroupBookmarkColorId(group.color()));
+          GetTabGroupBookmarkColorId(group->color()));
       tab_menu_item.image =
           NSImageFromImageSkia(image.Rasterize(&color_provider));
 
diff --git a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
index 9c097e28..513dc7621 100644
--- a/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
+++ b/chrome/browser/ui/startup/startup_browser_creator_browsertest.cc
@@ -2328,10 +2328,9 @@
 
     content::RunAllTasksUntilIdle();
     // Launching with an app opens the app window via a task, so the test
-    // might start before SelectFirstBrowser is called.
+    // might start before the first browser is created.
     if (!browser()) {
-      added_observer.Wait();
-      SelectFirstBrowser();
+      SetBrowser(added_observer.Wait());
     }
   }
   ASSERT_EQ(1u, chrome::GetBrowserCount(browser()->profile()));
diff --git a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.cc b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.cc
index 48d5927..55502bdc 100644
--- a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.cc
+++ b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.cc
@@ -31,13 +31,13 @@
 }
 
 void TabSensitivityCache::OnPageContentAnnotated(
-    const GURL& url,
+    const page_content_annotations::HistoryVisit& visit,
     const page_content_annotations::PageContentAnnotationsResult& result) {
   CHECK(result.GetType() ==
         page_content_annotations::AnnotationType::kContentVisibility);
 
   // Invert the visibility score to get a sensitivity score.
-  sensitivy_scores_[url] = 1.0 - result.GetContentVisibilityScore();
+  sensitivy_scores_[visit.url] = 1.0 - result.GetContentVisibilityScore();
   MaybeTrimCacheKeys();
 }
 
diff --git a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.h b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.h
index be80a56..eecc6d4 100644
--- a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.h
+++ b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache.h
@@ -36,7 +36,7 @@
   //     ::PageContentAnnotationsService
   //     ::PageContentAnnotationsObserver
   void OnPageContentAnnotated(
-      const GURL& url,
+      const page_content_annotations::HistoryVisit& visit,
       const page_content_annotations::PageContentAnnotationsResult& result)
       override;
 
diff --git a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache_browsertest.cc b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache_browsertest.cc
index 5d6c0d5..6bcf05e 100644
--- a/chrome/browser/ui/tabs/organization/tab_sensitivity_cache_browsertest.cc
+++ b/chrome/browser/ui/tabs/organization/tab_sensitivity_cache_browsertest.cc
@@ -11,6 +11,8 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "content/public/test/browser_test.h"
 
+using page_content_annotations::HistoryVisit;
+
 class TabSensitivityCacheBrowserTest : public InProcessBrowserTest {
  public:
   TabSensitivityCacheBrowserTest() = default;
@@ -57,8 +59,9 @@
   const GURL url1 = embedded_test_server()->GetURL("a.com", "/title1.html");
   AddTab(url1);
   cache()->OnPageContentAnnotated(
-      url1, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url1),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
 
   EXPECT_EQ(cache()->GetScore(url1), 0.0f);
 }
@@ -75,29 +78,34 @@
   content::WebContents* const tab2 = AddTab(url2);
   AddTab(url3);
   cache()->OnPageContentAnnotated(
-      url1, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url1),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
   cache()->OnPageContentAnnotated(
-      url2, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url2),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
   cache()->OnPageContentAnnotated(
-      url3, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url3),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
   RemoveTab(initial_tab);
   ASSERT_EQ(cache()->GetScore(url1), 0.0f);
 
   // Remove one tab. The cache does not trim yet as it would not shrink by 1/2.
   RemoveTab(tab1);
   cache()->OnPageContentAnnotated(
-      url3, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url3),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
   EXPECT_EQ(cache()->GetScore(url1), 0.0f);
 
   // Remove one more tab. The cache trims now as it can shrink by at least 1/2.
   RemoveTab(tab2);
   cache()->OnPageContentAnnotated(
-      url3, page_content_annotations::PageContentAnnotationsResult::
-                CreateContentVisibilityScoreResult(1.0f));
+      HistoryVisit({}, url3),
+      page_content_annotations::PageContentAnnotationsResult::
+          CreateContentVisibilityScoreResult(1.0f));
   EXPECT_EQ(cache()->GetScore(url1), std::nullopt);
 }
 
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn b/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn
index ac768aa..65445154 100644
--- a/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn
+++ b/chrome/browser/ui/tabs/saved_tab_groups/BUILD.gn
@@ -24,7 +24,7 @@
     "session_service_tab_group_sync_observer.h",
     "shared_tab_group_feedback_controller.h",
     "tab_group_action_context_desktop.h",
-    "tab_group_menu_action.h",
+    "tab_group_menu_utils.h",
     "tab_group_sync_delegate_desktop.h",
   ]
   public_deps = [
@@ -78,7 +78,7 @@
     "session_service_tab_group_sync_observer.cc",
     "shared_tab_group_feedback_controller.cc",
     "tab_group_action_context_desktop.cc",
-    "tab_group_menu_action.cc",
+    "tab_group_menu_utils.cc",
     "tab_group_sync_delegate_desktop.cc",
   ]
   deps = [
@@ -159,6 +159,7 @@
     "collaboration_messaging_page_action_controller_unittest.cc",
     "collaboration_messaging_tab_data_unittest.cc",
     "instant_message_queue_processor_unittest.cc",
+    "tab_group_menu_utils_unittest.cc",
   ]
   deps = [
     ":saved_tab_groups",
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h
index 6f4aa14..79ba7f8 100644
--- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h
+++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h
@@ -10,7 +10,7 @@
 
 #include "base/containers/span.h"
 #include "base/uuid.h"
-#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h"
 #include "chrome/browser/ui/tabs/tab_group_deletion_dialog_controller.h"
 #include "components/data_sharing/public/group_data.h"
 #include "components/saved_tab_groups/public/saved_tab_group.h"
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.cc
deleted file mode 100644
index e0ddfdf0..0000000
--- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.cc
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2025 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/ui/tabs/saved_tab_groups/tab_group_menu_action.h"
-
-namespace tab_groups {
-
-TabGroupMenuAction::TabGroupMenuAction(Type type,
-                                       std::variant<base::Uuid, GURL> element)
-    : type(type), element(element) {}
-TabGroupMenuAction::TabGroupMenuAction(const TabGroupMenuAction& action) =
-    default;
-TabGroupMenuAction::~TabGroupMenuAction() = default;
-
-}  // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h
deleted file mode 100644
index d1093b7..0000000
--- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_ACTION_H_
-#define CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_ACTION_H_
-
-#include <variant>
-
-#include "base/uuid.h"
-#include "url/gurl.h"
-
-namespace tab_groups {
-
-// The action users can perform on a saved tab group's submenu.
-struct TabGroupMenuAction {
-  enum class Type {
-    DEFAULT = -1,
-    OPEN_IN_BROWSER,
-    OPEN_OR_MOVE_TO_NEW_WINDOW,
-    PIN_OR_UNPIN_GROUP,
-    DELETE_GROUP,
-    LEAVE_GROUP,
-    OPEN_URL,
-  };
-
-  TabGroupMenuAction(Type type, std::variant<base::Uuid, GURL> element);
-  TabGroupMenuAction(const TabGroupMenuAction&);
-  ~TabGroupMenuAction();
-
-  Type type = Type::DEFAULT;
-
-  // The action needs either a UUID (e.g. Open group in new window) or a URL
-  // (e.g. Open tab) to perform.
-  std::variant<base::Uuid, GURL> element;
-};
-
-}  // namespace tab_groups
-
-#endif  // CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_ACTION_H_
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.cc
new file mode 100644
index 0000000..d5758d6
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.cc
@@ -0,0 +1,62 @@
+// Copyright 2025 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/ui/tabs/saved_tab_groups/tab_group_menu_utils.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "chrome/grit/generated_resources.h"
+#include "ui/base/l10n/l10n_util.h"
+
+namespace tab_groups {
+
+TabGroupMenuAction::TabGroupMenuAction(Type type,
+                                       std::variant<base::Uuid, GURL> element)
+    : type(type), element(element) {}
+TabGroupMenuAction::TabGroupMenuAction(const TabGroupMenuAction& action) =
+    default;
+TabGroupMenuAction::~TabGroupMenuAction() = default;
+
+std::u16string TabGroupMenuUtils::GetMenuTextForGroup(
+    const tab_groups::SavedTabGroup& group) {
+  return group.title().empty()
+             ? l10n_util::GetPluralStringFUTF16(
+                   IDS_SAVED_TAB_GROUP_TABS_COUNT,
+                   static_cast<int>(group.saved_tabs().size()))
+             : group.title();
+}
+
+std::u16string TabGroupMenuUtils::GetMenuTextForTab(
+    const tab_groups::SavedTabGroupTab& tab) {
+  return tab.title().empty() ? base::UTF8ToUTF16(tab.url().spec())
+                             : tab.title();
+}
+
+std::vector<base::Uuid>
+TabGroupMenuUtils::GetGroupsForDisplaySortedByCreationTime(
+    TabGroupSyncService* tab_group_service) {
+  CHECK(tab_group_service);
+  std::vector<const SavedTabGroup*> groups;
+
+  std::vector<SavedTabGroup> all_groups = tab_group_service->GetAllGroups();
+  for (const SavedTabGroup& group : all_groups) {
+    if (group.saved_tabs().empty()) {
+      continue;
+    }
+    groups.push_back(&group);
+  }
+
+  std::sort(groups.begin(), groups.end(),
+            [](const SavedTabGroup* a, const SavedTabGroup* b) {
+              return a->creation_time() > b->creation_time();
+            });
+
+  std::vector<base::Uuid> sorted_guids;
+  for (const SavedTabGroup* group : groups) {
+    sorted_guids.push_back(group->saved_guid());
+  }
+
+  return sorted_guids;
+}
+
+}  // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h
new file mode 100644
index 0000000..10f2ef6
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h
@@ -0,0 +1,57 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_UTILS_H_
+#define CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_UTILS_H_
+
+#include <variant>
+
+#include "base/uuid.h"
+#include "components/saved_tab_groups/public/saved_tab_group.h"
+#include "components/saved_tab_groups/public/saved_tab_group_tab.h"
+#include "components/saved_tab_groups/public/tab_group_sync_service.h"
+#include "url/gurl.h"
+
+namespace tab_groups {
+
+// The action users can perform on a saved tab group's submenu.
+struct TabGroupMenuAction {
+  enum class Type {
+    DEFAULT = -1,
+    OPEN_IN_BROWSER,
+    OPEN_OR_MOVE_TO_NEW_WINDOW,
+    PIN_OR_UNPIN_GROUP,
+    DELETE_GROUP,
+    LEAVE_GROUP,
+    OPEN_URL,
+  };
+
+  TabGroupMenuAction(Type type, std::variant<base::Uuid, GURL> element);
+  TabGroupMenuAction(const TabGroupMenuAction&);
+  ~TabGroupMenuAction();
+
+  Type type = Type::DEFAULT;
+
+  // The action needs either a UUID (e.g. Open group in new window) or a URL
+  // (e.g. Open tab) to perform.
+  std::variant<base::Uuid, GURL> element;
+};
+
+class TabGroupMenuUtils {
+ public:
+  static std::u16string GetMenuTextForGroup(
+      const tab_groups::SavedTabGroup& group);
+
+  static std::u16string GetMenuTextForTab(
+      const tab_groups::SavedTabGroupTab& tab);
+
+  // Returns sorted saved tab groups with the most recently created as the
+  // first, filtering out empty groups.
+  static std::vector<base::Uuid> GetGroupsForDisplaySortedByCreationTime(
+      TabGroupSyncService* wrapper_service);
+};
+
+}  // namespace tab_groups
+
+#endif  // CHROME_BROWSER_UI_TABS_SAVED_TAB_GROUPS_TAB_GROUP_MENU_UTILS_H_
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils_unittest.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils_unittest.cc
new file mode 100644
index 0000000..57c329a1
--- /dev/null
+++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils_unittest.cc
@@ -0,0 +1,100 @@
+// Copyright 2025 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/ui/tabs/saved_tab_groups/tab_group_menu_utils.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
+#include "chrome/grit/generated_resources.h"
+#include "components/saved_tab_groups/public/saved_tab_group.h"
+#include "components/saved_tab_groups/public/saved_tab_group_tab.h"
+#include "components/saved_tab_groups/public/tab_group_sync_service.h"
+#include "components/saved_tab_groups/test_support/fake_tab_group_sync_service.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "url/gurl.h"
+
+namespace tab_groups {
+
+class TabGroupMenuUtilsTest : public testing::Test {
+ public:
+  TabGroupMenuUtilsTest() = default;
+  ~TabGroupMenuUtilsTest() override = default;
+
+ protected:
+  const std::u16string kGroupTitle1 = u"Group 1";
+  const std::u16string kTabTitle1 = u"Tab 1";
+  const GURL kTabUrl1{"https://www.google.com/"};
+};
+
+TEST_F(TabGroupMenuUtilsTest, GetMenuTextForGroup) {
+  SavedTabGroup group_with_title(kGroupTitle1,
+                                 tab_groups::TabGroupColorId::kGrey, {});
+  EXPECT_EQ(kGroupTitle1,
+            TabGroupMenuUtils::GetMenuTextForGroup(group_with_title));
+
+  SavedTabGroup group_without_title(std::u16string(),
+                                    tab_groups::TabGroupColorId::kGrey, {});
+  SavedTabGroupTab tab(kTabUrl1, kTabTitle1, group_without_title.saved_guid(),
+                       /*position=*/0);
+  group_without_title.AddTabLocally(tab);
+  EXPECT_EQ(l10n_util::GetPluralStringFUTF16(
+                IDS_SAVED_TAB_GROUP_TABS_COUNT,
+                static_cast<int>(group_without_title.saved_tabs().size())),
+            TabGroupMenuUtils::GetMenuTextForGroup(group_without_title));
+}
+
+TEST_F(TabGroupMenuUtilsTest, GetMenuTextForTab) {
+  SavedTabGroupTab tab_with_title(kTabUrl1, kTabTitle1, {}, /*position=*/0);
+  EXPECT_EQ(kTabTitle1, TabGroupMenuUtils::GetMenuTextForTab(tab_with_title));
+
+  SavedTabGroupTab tab_without_title(kTabUrl1, std::u16string(), {},
+                                     /*position=*/0);
+  EXPECT_EQ(base::UTF8ToUTF16(kTabUrl1.spec()),
+            TabGroupMenuUtils::GetMenuTextForTab(tab_without_title));
+}
+
+TEST_F(TabGroupMenuUtilsTest, GetGroupsForDisplaySortedByCreationTime) {
+  FakeTabGroupSyncService service;
+
+  SavedTabGroup group1(u"Group 1", tab_groups::TabGroupColorId::kGrey, {},
+                       std::nullopt, std::nullopt, std::nullopt, std::nullopt,
+                       std::nullopt, false, base::Time::Now());
+  SavedTabGroupTab tab1(GURL("https://www.one.com/"), u"Tab 1",
+                        group1.saved_guid(), 0);
+  group1.AddTabLocally(tab1);
+  service.AddGroup(group1);
+
+  SavedTabGroup group2(u"Group 2", tab_groups::TabGroupColorId::kBlue, {},
+                       std::nullopt, std::nullopt, std::nullopt, std::nullopt,
+                       std::nullopt, false, base::Time::Now() - base::Days(1));
+  SavedTabGroupTab tab2(GURL("https://www.two.com/"), u"Tab 2",
+                        group2.saved_guid(), 0);
+  group2.AddTabLocally(tab2);
+  service.AddGroup(group2);
+
+  SavedTabGroup group3(u"Group 3", tab_groups::TabGroupColorId::kRed, {},
+                       std::nullopt, std::nullopt, std::nullopt, std::nullopt,
+                       std::nullopt, false, base::Time::Now() + base::Days(1));
+  SavedTabGroupTab tab3(GURL("https://www.three.com/"), u"Tab 3",
+                        group3.saved_guid(), 0);
+  group3.AddTabLocally(tab3);
+  service.AddGroup(group3);
+
+  SavedTabGroup empty_group(u"Empty Group", tab_groups::TabGroupColorId::kGreen,
+                            {}, std::nullopt, std::nullopt, std::nullopt,
+                            std::nullopt, std::nullopt, false,
+                            base::Time::Now());
+  service.AddGroup(empty_group);
+
+  std::vector<base::Uuid> sorted_guids =
+      TabGroupMenuUtils::GetGroupsForDisplaySortedByCreationTime(&service);
+
+  ASSERT_EQ(3u, sorted_guids.size());
+  EXPECT_EQ(group3.saved_guid(), sorted_guids[0]);
+  EXPECT_EQ(group1.saved_guid(), sorted_guids[1]);
+  EXPECT_EQ(group2.saved_guid(), sorted_guids[2]);
+}
+
+}  // namespace tab_groups
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.cc
index a8a0231d..3a4a6054 100644
--- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.cc
+++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.cc
@@ -124,37 +124,7 @@
   return sorted_non_empty_tab_groups_.at(idx_in_sorted_tab_group);
 }
 
-std::vector<base::Uuid>
-STGEverythingMenu::GetGroupsForDisplaySortedByCreationTime(
-    TabGroupSyncService* tab_group_service) {
-  CHECK(tab_group_service);
-  std::vector<base::Uuid> sorted_tab_groups;
-  for (const SavedTabGroup& group : tab_group_service->GetAllGroups()) {
-    if (group.saved_tabs().empty()) {
-      continue;
-    }
 
-    sorted_tab_groups.push_back(group.saved_guid());
-  }
-  auto compare_by_creation_time = [=](const base::Uuid& a,
-                                      const base::Uuid& b) {
-    const std::optional<SavedTabGroup> saved_tab_group_a =
-        tab_group_service->GetGroup(a);
-    const std::optional<SavedTabGroup> saved_tab_group_b =
-        tab_group_service->GetGroup(b);
-
-    // If either gets deleted while creating the model, ignore the order.
-    if (!saved_tab_group_a.has_value() || !saved_tab_group_b.has_value()) {
-      return false;
-    }
-
-    return saved_tab_group_a->creation_time() >
-           saved_tab_group_b->creation_time();
-  };
-  std::sort(sorted_tab_groups.begin(), sorted_tab_groups.end(),
-            compare_by_creation_time);
-  return sorted_tab_groups;
-}
 
 std::unique_ptr<ui::SimpleMenuModel> STGEverythingMenu::CreateMenuModel(
     TabGroupSyncService* tab_group_service) {
@@ -173,7 +143,8 @@
   }
 
   sorted_non_empty_tab_groups_ =
-      GetGroupsForDisplaySortedByCreationTime(tab_group_service);
+      TabGroupMenuUtils::GetGroupsForDisplaySortedByCreationTime(
+          tab_group_service);
 
   const auto* const color_provider = browser_->window()->GetColorProvider();
   for (size_t i = 0; i < sorted_non_empty_tab_groups_.size(); ++i) {
@@ -186,12 +157,7 @@
     const auto color_id = GetTabGroupDialogColorId(tab_group->color());
     const auto group_icon = ui::ImageModel::FromVectorIcon(
         kTabGroupIcon, color_provider->GetColor(color_id), gfx::kFaviconSize);
-    auto title = tab_group->title();
-    if (title.empty()) {
-      title = l10n_util::GetPluralStringFUTF16(
-          IDS_SAVED_TAB_GROUP_TABS_COUNT,
-          static_cast<int>(tab_group->saved_tabs().size()));
-    }
+    auto title = tab_groups::TabGroupMenuUtils::GetMenuTextForGroup(*tab_group);
     // For saved tab group items, use the indice in `sorted_tab_groups_` as the
     // command ids.
     const int command_id = GenerateTabGroupCommandID(i);
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.h b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.h
index 811245e..461ca1498 100644
--- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.h
+++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_everything_menu.h
@@ -86,11 +86,6 @@
   std::unique_ptr<ui::SimpleMenuModel> CreateMenuModel(
       TabGroupSyncService* tab_group_service);
 
-  // Returns sorted saved tab groups with the most recently created as the
-  // first, filtering out empty groups.
-  std::vector<base::Uuid> GetGroupsForDisplaySortedByCreationTime(
-      TabGroupSyncService* wrapper_service);
-
   // Because all the menu items (i.e. tab group items in the Everything menu -
   // primary menu and their submenus - secondary menu) need to be recognized and
   // invoked from the 3-dot menu so they follow the same pattern to get their
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.cc
index 3af57a2..0dfafa3 100644
--- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.cc
+++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.cc
@@ -155,8 +155,7 @@
   for (size_t i = 0; i < tabs.size(); ++i) {
     const auto& tab = tabs.at(i);
     const std::u16string title =
-        tab.title().empty() ? base::UTF8ToUTF16(tab.url().spec()) : tab.title();
-
+        tab_groups::TabGroupMenuUtils::GetMenuTextForTab(tab);
     latest_command_id = get_next_command_id.Run();
     const ui::ImageModel image = favicon::GetDefaultFaviconModel(
         GetTabGroupBookmarkColorId(saved_group.color()));
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.h b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.h
index e98685b..9cace16c 100644
--- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.h
+++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_tabs_menu_model.h
@@ -13,7 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/task/cancelable_task_tracker.h"
 #include "base/uuid.h"
-#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_action.h"
+#include "chrome/browser/ui/tabs/saved_tab_groups/tab_group_menu_utils.h"
 #include "components/saved_tab_groups/public/saved_tab_group.h"
 #include "ui/base/interaction/element_identifier.h"
 #include "ui/menus/simple_menu_model.h"
diff --git a/chrome/browser/ui/views/frame/browser_frame_view_chromeos_browsertest.cc b/chrome/browser/ui/views/frame/browser_frame_view_chromeos_browsertest.cc
index f4a3123..d65b314 100644
--- a/chrome/browser/ui/views/frame/browser_frame_view_chromeos_browsertest.cc
+++ b/chrome/browser/ui/views/frame/browser_frame_view_chromeos_browsertest.cc
@@ -50,8 +50,6 @@
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h"
@@ -69,7 +67,6 @@
 #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h"
 #include "chrome/browser/ui/views/location_bar/custom_tab_bar_view.h"
 #include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_view.h"
@@ -731,16 +728,13 @@
       zoom::ZoomController::FromWebContents(web_contents);
   IconLabelBubbleView* zoom_icon = GetPageActionView(kActionZoomNormal);
 
-  ZoomBubbleCoordinator* zoom_bubble_coordinator =
-      ZoomBubbleCoordinator::From(app_browser_);
-
   EXPECT_TRUE(zoom_icon);
   EXPECT_FALSE(zoom_icon->GetVisible());
-  EXPECT_FALSE(zoom_bubble_coordinator->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
   zoom_controller->SetZoomLevel(blink::ZoomFactorToZoomLevel(1.5));
   ASSERT_TRUE(WaitForVisible(true, zoom_icon));
-  EXPECT_TRUE(zoom_bubble_coordinator->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 }
 
 IN_PROC_BROWSER_TEST_P(WebAppFrameViewChromeOSTest, ShowFindIcon) {
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index afcbe82..e1bba69 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -134,6 +134,7 @@
 #include "chrome/browser/ui/views/frame/contents_rounded_corner.h"
 #include "chrome/browser/ui/views/frame/contents_separator.h"
 #include "chrome/browser/ui/views/frame/main_container_view.h"
+#include "chrome/browser/ui/views/frame/main_region_view.h"
 #include "chrome/browser/ui/views/frame/multi_contents_view.h"
 #include "chrome/browser/ui/views/frame/multi_contents_view_delegate.h"
 #include "chrome/browser/ui/views/frame/multi_contents_view_drop_target_controller.h"
@@ -792,7 +793,7 @@
 
   browser_->tab_strip_model()->AddObserver(this);
 
-  main_region_ = AddChildView(std::make_unique<views::View>());
+  main_region_ = AddChildView(std::make_unique<MainRegionView>());
 
   main_container_ =
       main_region_->AddChildView(std::make_unique<MainContainerView>());
diff --git a/chrome/browser/ui/views/frame/main_container_view.h b/chrome/browser/ui/views/frame/main_container_view.h
index a1daffa..e91c3e2 100644
--- a/chrome/browser/ui/views/frame/main_container_view.h
+++ b/chrome/browser/ui/views/frame/main_container_view.h
@@ -7,6 +7,16 @@
 
 #include "ui/views/view.h"
 
+// This view is responsible for holding the primary elements of the Browser UI
+// other than the tab strip:
+// - TopContainerView
+//   - ToolbarView
+//   - BookmarksBarView
+//   - ContentsSeparator
+//   - TopContainerLoadingBar
+// - InfobarContainerView
+// - ContentContainer
+// - SidePanel
 class MainContainerView : public views::View {
   METADATA_HEADER(MainContainerView, views::View)
 
diff --git a/chrome/browser/ui/views/frame/main_region_view.cc b/chrome/browser/ui/views/frame/main_region_view.cc
new file mode 100644
index 0000000..eece6aa
--- /dev/null
+++ b/chrome/browser/ui/views/frame/main_region_view.cc
@@ -0,0 +1,13 @@
+// Copyright 2025 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/ui/views/frame/main_region_view.h"
+
+#include "ui/base/metadata/metadata_impl_macros.h"
+
+MainRegionView::MainRegionView() = default;
+MainRegionView::~MainRegionView() = default;
+
+BEGIN_METADATA(MainRegionView)
+END_METADATA
diff --git a/chrome/browser/ui/views/frame/main_region_view.h b/chrome/browser/ui/views/frame/main_region_view.h
new file mode 100644
index 0000000..1c0e682
--- /dev/null
+++ b/chrome/browser/ui/views/frame/main_region_view.h
@@ -0,0 +1,22 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_MAIN_REGION_VIEW_H_
+#define CHROME_BROWSER_UI_VIEWS_FRAME_MAIN_REGION_VIEW_H_
+
+#include "ui/views/view.h"
+
+// This wrapper view primarily serves to hold the MainContainer and
+// ToolbarHeightSidePanel.
+class MainRegionView : public views::View {
+  METADATA_HEADER(MainRegionView, views::View)
+
+ public:
+  MainRegionView();
+  MainRegionView(const MainRegionView&) = delete;
+  MainRegionView& operator=(const MainRegionView&) = delete;
+  ~MainRegionView() override;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_FRAME_MAIN_REGION_VIEW_H_
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_delegate.cc b/chrome/browser/ui/views/frame/multi_contents_view_delegate.cc
index 9f72cc7..d0f4cc9 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view_delegate.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view_delegate.cc
@@ -126,9 +126,12 @@
   const int new_tab_idx =
       tab_strip_model_->active_index() +
       (side == MultiContentsDropTargetView::DropSide::START ? 0 : 1);
+
+  tabs::TabInterface* active_tab = tab_strip_model_->GetActiveTab();
   const int inserted_tab_idx = tab_strip_model_->InsertDetachedTabAt(
-      new_tab_idx, std::move(detached_tab), AddTabTypes::ADD_NONE,
-      std::nullopt);
+      new_tab_idx, std::move(detached_tab),
+      active_tab->IsPinned() ? AddTabTypes::ADD_PINNED : AddTabTypes::ADD_NONE,
+      active_tab->GetGroup());
   tab_strip_model_->AddToNewSplit(
       {inserted_tab_idx}, split_data,
       split_tabs::SplitTabCreatedSource::kDragAndDropTab);
diff --git a/chrome/browser/ui/views/location_bar/BUILD.gn b/chrome/browser/ui/views/location_bar/BUILD.gn
index be015a9..eee4d9a 100644
--- a/chrome/browser/ui/views/location_bar/BUILD.gn
+++ b/chrome/browser/ui/views/location_bar/BUILD.gn
@@ -29,7 +29,6 @@
       "omnibox_chip_theme.h",
       "selected_keyword_view.h",
       "star_view.h",
-      "zoom_bubble_coordinator.h",
       "zoom_bubble_view.h",
     ]
 
@@ -84,7 +83,6 @@
       "omnibox_chip_button.cc",
       "selected_keyword_view.cc",
       "star_view.cc",
-      "zoom_bubble_coordinator.cc",
       "zoom_bubble_view.cc",
     ]
 
diff --git a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
index 6191344..eca44e2 100644
--- a/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/location_bar_view_browsertest.cc
@@ -9,7 +9,6 @@
 #include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/functional/bind.h"
-#include "base/memory/raw_ptr.h"
 #include "base/path_service.h"
 #include "base/run_loop.h"
 #include "base/strings/string_util.h"
@@ -21,14 +20,11 @@
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
 #include "chrome/browser/ui/views/page_action/page_action_container_view.h"
@@ -78,20 +74,13 @@
 }  // namespace
 
 class LocationBarViewBrowserTest : public InProcessBrowserTest {
- protected:
+ public:
   LocationBarViewBrowserTest() = default;
 
   LocationBarViewBrowserTest(const LocationBarViewBrowserTest&) = delete;
   LocationBarViewBrowserTest& operator=(const LocationBarViewBrowserTest&) =
       delete;
 
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-    zoom_bubble_coordinator_ = ZoomBubbleCoordinator::From(browser());
-  }
-
-  void TearDownOnMainThread() override { zoom_bubble_coordinator_ = nullptr; }
-
   LocationBarView* GetLocationBarView() {
     BrowserView* browser_view =
         BrowserView::GetBrowserViewForBrowser(browser());
@@ -113,8 +102,6 @@
         location_bar_view->GetContentSettingViewsForTest(), image_type,
         &ContentSettingImageView::GetType);
   }
-
-  raw_ptr<ZoomBubbleCoordinator> zoom_bubble_coordinator_;
 };
 
 // Ensure the location bar decoration is added when zooming, and is removed when
@@ -128,38 +115,38 @@
 
   ASSERT_TRUE(zoom_view);
   EXPECT_FALSE(zoom_view->GetVisible());
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
   // Altering zoom should display a bubble. Note ZoomBubbleView closes
   // asynchronously, so precede checks with a run loop flush.
   zoom_controller->SetZoomLevel(blink::ZoomFactorToZoomLevel(1.5));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(zoom_view->GetVisible());
-  EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 
   // Close the bubble at other than 100% zoom. Icon should remain visible.
-  zoom_bubble_coordinator_->Hide();
+  ZoomBubbleView::CloseCurrentBubble();
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(zoom_view->GetVisible());
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
   // Show the bubble again.
   zoom_controller->SetZoomLevel(blink::ZoomFactorToZoomLevel(2.0));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(zoom_view->GetVisible());
-  EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 
   // Remains visible at 100% until the bubble is closed.
   zoom_controller->SetZoomLevel(blink::ZoomFactorToZoomLevel(1.0));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(zoom_view->GetVisible());
-  EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 
   // Closing at 100% hides the icon.
-  zoom_bubble_coordinator_->Hide();
+  ZoomBubbleView::CloseCurrentBubble();
   base::RunLoop().RunUntilIdle();
   EXPECT_FALSE(zoom_view->GetVisible());
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 }
 
 // Ensure that location bar bubbles close when the webcontents hides.
@@ -176,13 +163,13 @@
   zoom_controller->SetZoomLevel(blink::ZoomFactorToZoomLevel(1.5));
   base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(zoom_view->GetVisible());
-  EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
 
   chrome::NewTab(browser());
   chrome::SelectNextTab(browser());
 
   base::RunLoop().RunUntilIdle();
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 }
 
 // Check that the script blocked icon shows up when user disables javascript.
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.cc
deleted file mode 100644
index 4154ca92..0000000
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.cc
+++ /dev/null
@@ -1,251 +0,0 @@
-// Copyright 2025 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/ui/views/location_bar/zoom_bubble_coordinator.h"
-
-#include <string>
-
-#include "base/check.h"
-#include "base/types/to_address.h"
-#include "chrome/browser/ui/actions/chrome_action_id.h"
-#include "chrome/browser/ui/browser_actions.h"
-#include "chrome/browser/ui/tabs/public/tab_features.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
-#include "chrome/browser/ui/views/page_action/page_action_view.h"
-#include "chrome/browser/ui/views/zoom/zoom_view_controller.h"
-#include "components/zoom/zoom_controller.h"
-#include "extensions/browser/extension_zoom_request_client.h"
-#include "extensions/common/extension.h"
-#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/widget/widget.h"
-
-#if BUILDFLAG(IS_MAC)
-#include "chrome/browser/ui/fullscreen_util_mac.h"
-#endif
-
-namespace {
-
-// Retrieves the anchor view for the zoom bubble.
-views::View* GetAnchorView(BrowserView* browser_view) {
-  CHECK(browser_view);
-
-#if BUILDFLAG(IS_MAC)
-  if (fullscreen_utils::IsInContentFullscreen(browser_view->browser())) {
-    return nullptr;
-  }
-#endif
-
-  if (!browser_view->GetWidget()->IsFullscreen() ||
-      browser_view->IsToolbarVisible() ||
-      browser_view->immersive_mode_controller()->IsRevealed()) {
-    return browser_view->toolbar_button_provider()->GetAnchorView(
-        kActionZoomNormal);
-  }
-  return nullptr;
-}
-
-// Find the extension that initiated the zoom change, if any.
-const extensions::ExtensionZoomRequestClient* GetExtensionZoomRequestClient(
-    const content::WebContents* web_contents) {
-  auto* zoom_controller =
-      web_contents ? zoom::ZoomController::FromWebContents(web_contents)
-                   : nullptr;
-  return zoom_controller
-             ? static_cast<const extensions::ExtensionZoomRequestClient*>(
-                   zoom_controller->last_client())
-             : nullptr;
-}
-
-void UpdateBubbleVisibilityState(Browser* browser, bool is_bubble_visible) {
-  if (!browser) {
-    return;
-  }
-
-  auto* action_item = actions::ActionManager::Get().FindAction(
-      kActionZoomNormal, browser->browser_actions()->root_action_item());
-  CHECK(action_item);
-  action_item->SetIsShowingBubble(is_bubble_visible);
-}
-
-}  // namespace
-
-DEFINE_USER_DATA(ZoomBubbleCoordinator);
-
-ZoomBubbleCoordinator::ZoomBubbleCoordinator(BrowserView& browser_view)
-    : scoped_unowned_user_data_(
-          browser_view.browser()->GetUnownedUserDataHost(),
-          *this),
-      browser_view_(browser_view) {
-  immersive_mode_observation_.Observe(
-      browser_view_->immersive_mode_controller());
-}
-
-ZoomBubbleCoordinator::~ZoomBubbleCoordinator() {
-  Hide();
-}
-
-// static
-ZoomBubbleCoordinator* ZoomBubbleCoordinator::From(
-    BrowserWindowInterface* browser) {
-  return browser ? Get(browser->GetUnownedUserDataHost()) : nullptr;
-}
-
-void ZoomBubbleCoordinator::OnWidgetVisibilityChanged(views::Widget* widget,
-                                                      bool visible) {
-  CHECK(widget_observation_.IsObservingSource(widget));
-  UpdateZoomBubbleStateAndIconVisibility(
-      /*is_bubble_visible=*/visible);
-}
-
-void ZoomBubbleCoordinator::OnWidgetDestroying(views::Widget* widget) {
-  CHECK(widget_observation_.IsObservingSource(widget));
-  widget_observation_.Reset();
-}
-
-void ZoomBubbleCoordinator::Show(
-    content::WebContents* contents,
-    LocationBarBubbleDelegateView::DisplayReason reason) {
-  if (!browser_view_->browser()->GetActiveTabInterface()) {
-    return;
-  }
-
-  if (RefreshIfShowing(contents)) {
-    return;
-  }
-
-  Hide();
-
-  if (widget_observation_.IsObserving()) {
-    // Closing the widget is async, but IsClosed() will return true as soon as
-    // the Close() method has been invoked.
-    CHECK(widget_observation_.GetSource()->IsClosed());
-    widget_observation_.Reset();
-  }
-
-  auto* anchor_view = GetAnchorView(base::to_address(browser_view_));
-  auto bubble_view = std::make_unique<ZoomBubbleView>(
-      browser_view_->browser(), anchor_view, contents, reason);
-
-  if (const auto* client = GetExtensionZoomRequestClient(contents)) {
-    bubble_view->SetExtensionInfo(client->extension());
-  }
-
-  views::Button* button =
-      browser_view_->toolbar_button_provider()->GetPageActionView(
-          kActionZoomNormal);
-  bubble_view->SetHighlightedButton(button);
-
-  // If we don't anchor to anything the BrowserView is our parent. This happens
-  // in fullscreen cases.
-  bubble_view->set_parent_window(
-      bubble_view->anchor_widget()
-          ? gfx::NativeView()
-          : browser_view_->GetWidget()->GetNativeView());
-
-  ZoomBubbleView* bubble_raw = bubble_view.get();
-
-  auto* widget =
-      views::BubbleDialogDelegate::CreateBubble(std::move(bubble_view));
-
-  widget_observation_.Observe(widget);
-
-  if (!anchor_view && browser_view_->browser()->window()->IsFullscreen()) {
-    bubble_raw->AdjustForFullscreen(
-        browser_view_->browser()->window()->GetBounds());
-  }
-
-  // Do not announce hotkey for refocusing inactive Zoom bubble as it
-  // disappears after a short timeout.
-  bubble_raw->ShowForReason(reason, /*allow_refocus_alert=*/false);
-}
-
-void ZoomBubbleCoordinator::OnImmersiveRevealStarted() {
-  Hide();
-}
-
-void ZoomBubbleCoordinator::OnImmersiveModeControllerDestroyed() {
-  immersive_mode_observation_.Reset();
-}
-
-void ZoomBubbleCoordinator::Hide() {
-  if (!IsShowing()) {
-    return;
-  }
-
-  widget_observation_.GetSource()->Close();
-}
-
-bool ZoomBubbleCoordinator::RefreshIfShowing(content::WebContents* contents) {
-  if (!CanRefresh(bubble(), contents)) {
-    return false;
-  }
-
-  CHECK(bubble());
-  bubble()->Refresh();
-  return true;
-}
-
-ZoomBubbleView* ZoomBubbleCoordinator::bubble() {
-  if (!IsShowing()) {
-    return nullptr;
-  }
-
-  return static_cast<ZoomBubbleView*>(
-      widget_observation_.GetSource()->GetClientContentsView());
-}
-
-bool ZoomBubbleCoordinator::CanRefresh(ZoomBubbleView* current_bubble,
-                                       content::WebContents* web_contents) {
-  // Can't refresh when there's not already a bubble for this tab.
-  if (!current_bubble || (current_bubble->web_contents() != web_contents)) {
-    return false;
-  }
-
-  // If the anchor view has changed, we must create a new bubble.
-  if (current_bubble->GetAnchorView() !=
-      GetAnchorView(base::to_address(browser_view_))) {
-    return false;
-  }
-
-  const extensions::ExtensionZoomRequestClient* client =
-      GetExtensionZoomRequestClient(web_contents);
-
-  // Allow refreshes when the client won't create its own bubble.
-  if (client && client->ShouldSuppressBubble()) {
-    return true;
-  }
-
-  // Allow refreshes only when the bubble has the same attribution.
-  const std::string current_extension_id =
-      client ? client->extension()->id() : std::string();
-  return current_bubble->extension_id() == current_extension_id;
-}
-
-void ZoomBubbleCoordinator::UpdateZoomBubbleStateAndIconVisibility(
-    bool is_bubble_visible) {
-  // This method can be called during browser destruction since the bubble close
-  // is async.
-  auto* tab_interface = browser_view_->browser()->GetActiveTabInterface();
-  if (!tab_interface) {
-    return;
-  }
-
-  if (!IsPageActionMigrated(PageActionIconType::kZoom)) {
-    browser_view_->browser()->window()->UpdatePageActionIcon(
-        PageActionIconType::kZoom);
-    return;
-  }
-
-  // Update the bubble visibility state before we refresh the icon so that
-  // UpdateZoomIconVisibility() sees the correct value bubble state value.
-  UpdateBubbleVisibilityState(browser_view_->browser(), is_bubble_visible);
-
-  auto* tab_feature = tab_interface->GetTabFeatures();
-  CHECK(tab_feature);
-  tab_feature->zoom_view_controller()->UpdatePageActionIcon(is_bubble_visible);
-}
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h b/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h
deleted file mode 100644
index ca93998..0000000
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h
+++ /dev/null
@@ -1,95 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_ZOOM_BUBBLE_COORDINATOR_H_
-#define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_ZOOM_BUBBLE_COORDINATOR_H_
-
-#include "base/memory/raw_ref.h"
-#include "base/scoped_observation.h"
-#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
-#include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
-#include "ui/base/unowned_user_data/scoped_unowned_user_data.h"
-#include "ui/views/widget/widget_observer.h"
-
-class ZoomBubbleView;
-class BrowserWindowInterface;
-
-namespace content {
-class WebContents;
-}
-
-// Manages the zoom bubble, ensuring that only one is shown at a time and that
-// it is properly cleared. This class is responsible for creating, showing,
-// hiding, and refreshing the ZoomBubbleView.
-class ZoomBubbleCoordinator : public views::WidgetObserver,
-                              public ImmersiveModeController::Observer {
- public:
-  DECLARE_USER_DATA(ZoomBubbleCoordinator);
-
-  explicit ZoomBubbleCoordinator(BrowserView& browser_view);
-  ZoomBubbleCoordinator(const ZoomBubbleCoordinator&) = delete;
-  ZoomBubbleCoordinator& operator=(const ZoomBubbleCoordinator&) = delete;
-  ~ZoomBubbleCoordinator() override;
-
-  // Retrieves from the a browser window interface, or null if none.
-  // Note: May return null in unit_tests, even for a valid `browser`.
-  static ZoomBubbleCoordinator* From(BrowserWindowInterface* browser);
-
-  // views::WidgetObserver:
-  void OnWidgetVisibilityChanged(views::Widget* widget, bool visible) override;
-  void OnWidgetDestroying(views::Widget* widget) override;
-
-  // Creates and shows a new zoom bubble for the given `contents`, hiding any
-  // existing bubble first.
-  void Show(content::WebContents* contents,
-            LocationBarBubbleDelegateView::DisplayReason reason);
-
-  // Hides the currently showing zoom bubble, if one exists.
-  // NOTE: This is async, as a result, the hide is not immediate. Callers should
-  // ensure to wait to widget destruction.
-  void Hide();
-
-  // Refreshes the existing bubble if it's already showing for `contents`.
-  // Returns true if a bubble was successfully refreshed, false otherwise.
-  bool RefreshIfShowing(content::WebContents* contents);
-
-  // Returns true if a zoom bubble is currently being shown.
-  [[nodiscard]] bool IsShowing() const {
-    return widget_observation_.IsObserving() &&
-           widget_observation_.GetSource()->IsVisible();
-  }
-
-  // Returns a pointer to the currently showing bubble, or nullptr if none.
-  ZoomBubbleView* bubble();
-
- private:
-  // ImmersiveModeController::Observer:
-  void OnImmersiveRevealStarted() override;
-  void OnImmersiveModeControllerDestroyed() override;
-
-  // Determines if the existing zoom bubble can be refreshed for the given
-  // WebContents.
-  bool CanRefresh(ZoomBubbleView* current_bubble,
-                  content::WebContents* web_contents);
-
-  // Updates visibility of the zoom icon.
-  void UpdateZoomBubbleStateAndIconVisibility(bool is_bubble_visible);
-
-  ui::ScopedUnownedUserData<ZoomBubbleCoordinator> scoped_unowned_user_data_;
-
-  // Unowned reference to the  browser view that whole this coordinator.
-  const raw_ref<BrowserView> browser_view_;
-
-  // Observes the widget of the zoom bubble to be notified of its destruction.
-  base::ScopedObservation<views::Widget, views::WidgetObserver>
-      widget_observation_{this};
-
-  // The immersive mode controller observation for the BrowserView containing
-  // `web_contents_`.
-  base::ScopedObservation<ImmersiveModeController,
-                          ImmersiveModeController::Observer>
-      immersive_mode_observation_{this};
-};
-
-#endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_ZOOM_BUBBLE_COORDINATOR_H_
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
index 82ce7f5..30daade 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.cc
@@ -8,7 +8,6 @@
 #include <memory>
 
 #include "base/auto_reset.h"
-#include "base/check.h"
 #include "base/i18n/number_formatting.h"
 #include "base/i18n/rtl.h"
 #include "base/strings/stringprintf.h"
@@ -153,32 +152,222 @@
 BEGIN_METADATA(ZoomValue)
 END_METADATA
 
+bool IsBrowserFullscreen(Browser* browser) {
+  DCHECK(browser->window() && browser->GetFeatures()
+                                  .exclusive_access_manager()
+                                  ->fullscreen_controller());
+  return browser->window()->IsFullscreen();
+}
+
+views::View* GetAnchorViewForBrowser(Browser* browser) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+#if BUILDFLAG(IS_MAC)
+  if (fullscreen_utils::IsInContentFullscreen(browser)) {
+    return nullptr;
+  }
+#endif
+  if (!IsBrowserFullscreen(browser) || browser_view->IsToolbarVisible() ||
+      browser_view->immersive_mode_controller()->IsRevealed()) {
+    return browser_view->toolbar_button_provider()->GetAnchorView(
+        kActionZoomNormal);
+  }
+  return nullptr;
+}
+
+ImmersiveModeController* GetImmersiveModeControllerForBrowser(
+    Browser* browser) {
+  BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser);
+  return browser_view->immersive_mode_controller();
+}
+
+void ParentToBrowser(Browser* browser,
+                     ZoomBubbleView* zoom_bubble,
+                     views::View* anchor_view,
+                     content::WebContents* web_contents) {
+  BrowserView* const browser_view =
+      BrowserView::GetBrowserViewForBrowser(browser);
+  views::Button* button =
+      browser_view->toolbar_button_provider()->GetPageActionView(
+          kActionZoomNormal);
+
+  zoom_bubble->SetHighlightedButton(button);
+
+  // If we don't anchor to anything the BrowserView is our parent. This happens
+  // in fullscreen cases.
+  zoom_bubble->set_parent_window(
+      zoom_bubble->anchor_widget()
+          ? gfx::NativeView()
+          : browser_view->GetWidget()->GetNativeView());
+
+  views::BubbleDialogDelegateView::CreateBubble(zoom_bubble);
+}
+
+// Find the extension that initiated the zoom change, if any.
+const extensions::ExtensionZoomRequestClient* GetExtensionZoomRequestClient(
+    const content::WebContents* web_contents) {
+  const zoom::ZoomController* zoom_controller =
+      zoom::ZoomController::FromWebContents(web_contents);
+  const zoom::ZoomRequestClient* client = zoom_controller->last_client();
+  return static_cast<const extensions::ExtensionZoomRequestClient*>(client);
+}
+
+void UpdateBubbleVisibilityState(Browser* browser, bool is_bubble_visible) {
+  if (!browser) {
+    return;
+  }
+
+  auto* action_item = actions::ActionManager::Get().FindAction(
+      kActionZoomNormal, browser->browser_actions()->root_action_item());
+  CHECK(action_item);
+  action_item->SetIsShowingBubble(is_bubble_visible);
+}
+
 }  // namespace
 
+// static
+ZoomBubbleView* ZoomBubbleView::zoom_bubble_ = nullptr;
+
+// static
+void ZoomBubbleView::ShowBubble(content::WebContents* web_contents,
+                                DisplayReason reason) {
+  Browser* browser = chrome::FindBrowserWithTab(web_contents);
+  // |web_contents| could have been unloaded if a tab gets closed and a mouse
+  // event arrives before the zoom icon gets hidden.
+  if (!browser) {
+    return;
+  }
+
+  if (RefreshBubbleIfShowing(web_contents)) {
+    return;
+  }
+
+  // If the bubble is already showing but in a different tab, the current
+  // bubble must be closed and a new one created.
+  CloseCurrentBubble();
+
+  views::View* anchor_view = GetAnchorViewForBrowser(browser);
+  ImmersiveModeController* immersive_mode_controller =
+      GetImmersiveModeControllerForBrowser(browser);
+  CHECK(immersive_mode_controller);
+
+  zoom_bubble_ = new ZoomBubbleView(anchor_view, web_contents, reason,
+                                    *immersive_mode_controller);
+
+  const extensions::ExtensionZoomRequestClient* client =
+      GetExtensionZoomRequestClient(web_contents);
+
+  // If the zoom change was initiated by an extension, capture the relevent
+  // information from it.
+  if (client) {
+    zoom_bubble_->SetExtensionInfo(client->extension());
+  }
+
+  ParentToBrowser(browser, zoom_bubble_, anchor_view, web_contents);
+
+  if (!anchor_view && IsBrowserFullscreen(browser)) {
+    zoom_bubble_->AdjustForFullscreen(browser->window()->GetBounds());
+  }
+
+  // Do not announce hotkey for refocusing inactive Zoom bubble as it
+  // disappears after a short timeout.
+  zoom_bubble_->ShowForReason(reason, /* allow_refocus_alert */ false);
+
+  // This is a temporary fix (https://crbug.com/434615869). For some reason,
+  // `zoom_bubble_` become null after calling ShowForReason. A long term fix
+  // will be to have a clear and defined lifetime for the zoom bubble.
+  if (!zoom_bubble_) {
+    return;
+  }
+
+  // Update the "bubble is showing" state before we refresh the icon so that
+  // UpdateZoomIconVisibility() sees the correct value bubble state value.
+  zoom_bubble_->UpdateZoomBubbleStateAndIconVisibility(
+      /*is_bubble_visible=*/true);
+}
+
+// static
+bool ZoomBubbleView::RefreshBubbleIfShowing(
+    const content::WebContents* web_contents) {
+  if (!CanRefresh(web_contents)) {
+    return false;
+  }
+
+  DCHECK_EQ(web_contents, zoom_bubble_->web_contents());
+  zoom_bubble_->Refresh();
+
+  return true;
+}
+
+// static
+bool ZoomBubbleView::CanRefresh(const content::WebContents* web_contents) {
+  // Can't refresh when there's not already a bubble for this tab.
+  if (!zoom_bubble_ || (zoom_bubble_->web_contents() != web_contents)) {
+    return false;
+  }
+
+  Browser* browser = chrome::FindBrowserWithTab(web_contents);
+  if (!browser ||
+      (zoom_bubble_->GetAnchorView() != GetAnchorViewForBrowser(browser))) {
+    return false;
+  }
+
+  const extensions::ExtensionZoomRequestClient* client =
+      GetExtensionZoomRequestClient(web_contents);
+
+  // Allow refreshes when the client won't create its own bubble; otherwise
+  // the existing bubble would show the wrong zoom value.
+  if (client && client->ShouldSuppressBubble()) {
+    return true;
+  }
+
+  // Allow refreshes when the existing bubble has the same attribution for
+  // the zoom change, so only the label needs updating.
+  return zoom_bubble_->extension_info_.id ==
+         (client ? client->extension()->id() : std::string());
+}
+
+// static
+void ZoomBubbleView::CloseCurrentBubble() {
+  if (zoom_bubble_) {
+    zoom_bubble_->CloseBubble();
+  }
+}
+
+// static
+ZoomBubbleView* ZoomBubbleView::GetZoomBubble() {
+  return zoom_bubble_;
+}
+
 void ZoomBubbleView::Refresh() {
   UpdateZoomPercent();
   StartTimerIfNecessary();
 }
 
-ZoomBubbleView::ZoomBubbleView(Browser* browser,
-                               views::View* anchor_view,
-                               content::WebContents* web_contents,
-                               DisplayReason reason)
+ZoomBubbleView::ZoomBubbleView(
+    views::View* anchor_view,
+    content::WebContents* web_contents,
+    DisplayReason reason,
+    ImmersiveModeController& immersive_mode_controller)
     : LocationBarBubbleDelegateView(anchor_view, web_contents),
-      browser_(browser),
       auto_close_duration_(kBubbleCloseDelayDefault),
-      auto_close_(reason == AUTOMATIC) {
+      auto_close_(reason == AUTOMATIC),
+      session_id_(chrome::FindBrowserWithTab(web_contents)->session_id()) {
   SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone));
   SetNotifyEnterExitOnChild(true);
+  scoped_observation_.Observe(&immersive_mode_controller);
   UseCompactMargins();
 }
 
 ZoomBubbleView::~ZoomBubbleView() = default;
 
 std::u16string ZoomBubbleView::GetAccessibleWindowTitle() const {
+  Browser* browser = GetBrowser();
+  if (!browser) {
+    return {};
+  }
+
   ToolbarButtonProvider* provider =
-      BrowserView::GetBrowserViewForBrowser(browser_)
-          ->toolbar_button_provider();
+      BrowserView::GetBrowserViewForBrowser(browser)->toolbar_button_provider();
 
   return provider->GetPageActionView(kActionZoomNormal)->GetAccessibleName();
 }
@@ -200,7 +389,8 @@
 }
 
 void ZoomBubbleView::OnGestureEvent(ui::GestureEvent* event) {
-  if (!auto_close_ || event->type() != ui::EventType::kGestureTap) {
+  if (!zoom_bubble_ || !zoom_bubble_->auto_close_ ||
+      event->type() != ui::EventType::kGestureTap) {
     return;
   }
 
@@ -210,7 +400,7 @@
 }
 
 void ZoomBubbleView::OnKeyEvent(ui::KeyEvent* event) {
-  if (!auto_close_) {
+  if (!zoom_bubble_ || !zoom_bubble_->auto_close_) {
     return;
   }
 
@@ -324,6 +514,40 @@
   StartTimerIfNecessary();
 }
 
+void ZoomBubbleView::WindowClosing() {
+  // |zoom_bubble_| can be a new bubble by this point (as Close(); doesn't
+  // call this right away). Only set to nullptr when it's this bubble.
+  bool this_bubble = zoom_bubble_ == this;
+  if (this_bubble) {
+    zoom_bubble_ = nullptr;
+  }
+
+  // Clear the "bubble is showing" state before we refresh the icon so that
+  // UpdateZoomIconVisibility() sees the correct value bubble state value.
+  UpdateZoomBubbleStateAndIconVisibility(/*is_bubble_visible=*/zoom_bubble_ !=
+                                         nullptr);
+}
+
+void ZoomBubbleView::CloseBubble() {
+  Browser* browser = GetBrowser();
+  if (ignore_close_bubble_ && browser &&
+      GetAnchorViewForBrowser(browser) == GetAnchorView()) {
+    return;
+  }
+
+  // Widget's Close() is async, but we don't want to use zoom_bubble_ after
+  // this. Additionally web_contents() may have been destroyed.
+  zoom_bubble_ = nullptr;
+  LocationBarBubbleDelegateView::CloseBubble();
+}
+
+void ZoomBubbleView::OnImmersiveRevealStarted() {
+  CloseBubble();
+}
+
+void ZoomBubbleView::OnImmersiveModeControllerDestroyed() {
+  scoped_observation_.Reset();
+}
 
 void ZoomBubbleView::OnExtensionIconImageChanged(
     extensions::IconImage* /* image */) {
@@ -388,20 +612,38 @@
       !blink::ZoomValuesEqual(zoom_levels.back(), current_zoom_level));
 }
 
+void ZoomBubbleView::UpdateZoomBubbleStateAndIconVisibility(
+    bool is_bubble_visible) {
+  // Note that we can't rely on web_contents() here, as it may have been
+  // destroyed by the time we get this call. Also note parent_window() (if set)
+  // may also be destroyed: the call to WindowClosing() may be triggered by
+  // parent window destruction tearing down its child windows.
+  Browser* browser = chrome::FindBrowserWithID(session_id_);
+  if (!browser || !browser->window() || !browser->GetActiveTabInterface()) {
+    return;
+  }
+
+  if (!IsPageActionMigrated(PageActionIconType::kZoom)) {
+    browser->window()->UpdatePageActionIcon(PageActionIconType::kZoom);
+    return;
+  }
+
+  // Update the bubble visibility state before we refresh the icon so that
+  // UpdateZoomIconVisibility() sees the correct value bubble state value.
+  UpdateBubbleVisibilityState(browser, is_bubble_visible);
+
+  auto* tab_feature = browser->GetActiveTabInterface()->GetTabFeatures();
+  CHECK(tab_feature);
+  tab_feature->zoom_view_controller()->UpdatePageActionIcon(is_bubble_visible);
+}
+
 void ZoomBubbleView::StartTimerIfNecessary() {
   if (!auto_close_) {
     return;
   }
 
-  auto_close_timer_.Start(
-      FROM_HERE, auto_close_duration_,
-      base::BindOnce(&ZoomBubbleView::Close, base::Unretained(this)));
-}
-
-void ZoomBubbleView::Close() {
-  if (GetWidget()) {
-    GetWidget()->Close();
-  }
+  auto_close_timer_.Start(FROM_HERE, auto_close_duration_, this,
+                          &ZoomBubbleView::CloseBubble);
 }
 
 void ZoomBubbleView::StopTimer() {
@@ -422,30 +664,18 @@
 
 void ZoomBubbleView::ImageButtonPressed() {
   DCHECK(extension_info_.icon_image) << "Invalid button press.";
-  chrome::AddSelectedTabWithURL(
-      browser_,
-      GURL(base::StringPrintf("chrome://extensions?id=%s",
-                              extension_info_.id.c_str())),
-      ui::PAGE_TRANSITION_FROM_API);
+  Browser* browser = GetBrowser();
+  if (browser) {
+    chrome::AddSelectedTabWithURL(
+        browser,
+        GURL(base::StringPrintf("chrome://extensions?id=%s",
+                                extension_info_.id.c_str())),
+        ui::PAGE_TRANSITION_FROM_API);
+  }
 }
 
-std::u16string_view ZoomBubbleView::GetLabelForTesting() const {
-  return label_->GetText();
-}
-
-base::OneShotTimer* ZoomBubbleView::GetAutoCloseTimerForTesting() {
-  return &auto_close_timer_;
-}
-views::Button* ZoomBubbleView::GetResetButtonForTesting() {
-  return reset_button_;
-}
-
-views::Button* ZoomBubbleView::GetZoomInButtonForTesting() {
-  return zoom_in_button_;
-}
-
-void ZoomBubbleView::OnKeyEventForTesting(ui::KeyEvent* event) {
-  OnKeyEvent(event);
+Browser* ZoomBubbleView::GetBrowser() const {
+  return web_contents() ? chrome::FindBrowserWithTab(web_contents()) : nullptr;
 }
 
 ZoomBubbleView::ZoomBubbleExtensionInfo::ZoomBubbleExtensionInfo() = default;
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
index 440b916..1c2ced0 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view.h
@@ -13,6 +13,7 @@
 #include "base/scoped_observation.h"
 #include "base/time/time.h"
 #include "base/timer/timer.h"
+#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_bubble_delegate_view.h"
 #include "components/sessions/core/session_id.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -32,44 +33,41 @@
 
 // View used to display the zoom percentage when it has changed.
 class ZoomBubbleView : public LocationBarBubbleDelegateView,
+                       public ImmersiveModeController::Observer,
                        public extensions::IconImage::Observer {
   METADATA_HEADER(ZoomBubbleView, LocationBarBubbleDelegateView)
 
  public:
-  // Constructs ZoomBubbleView. Anchors the bubble to |anchor_view|, which must
-  // not be nullptr. The bubble will auto-close when |reason| is AUTOMATIC. If
-  // |immersive_mode_controller_| is present, the bubble will auto-close when
-  // the top-of-window views are revealed.
-  ZoomBubbleView(Browser* browser,
-                 views::View* anchor_view,
-                 content::WebContents* web_contents,
-                 DisplayReason reason);
-  ~ZoomBubbleView() override;
-
   ZoomBubbleView(const ZoomBubbleView&) = delete;
   ZoomBubbleView& operator=(const ZoomBubbleView&) = delete;
 
+  // Shows the bubble and automatically closes it after a short time period if
+  // |reason| is AUTOMATIC.
+  static void ShowBubble(content::WebContents* web_contents,
+                         DisplayReason reason);
+
+  // If the bubble is being shown for the given |web_contents|, refreshes it.
+  static bool RefreshBubbleIfShowing(const content::WebContents* web_contents);
+
+  // Closes the showing bubble (if one exists).
+  static void CloseCurrentBubble();
+
+  // Returns the zoom bubble if the zoom bubble is showing. Returns NULL
+  // otherwise.
+  static ZoomBubbleView* GetZoomBubble();
+
   // Refreshes the bubble by changing the zoom percentage appropriately and
   // resetting the timer if necessary.
   void Refresh();
 
-  // Sets information about the extension that initiated the zoom change.
-  // Calling this method asserts that the extension |extension| did initiate
-  // the zoom change.
-  void SetExtensionInfo(const extensions::Extension* extension);
-
-  // Returns the ID of the extension that triggered the bubble, or an empty
-  // string if it was not triggered by an extension.
-  const std::string& extension_id() const { return extension_info_.id; }
-
-  // Helpers for testing.
-  std::u16string_view GetLabelForTesting() const;
-  base::OneShotTimer* GetAutoCloseTimerForTesting();
-  views::Button* GetResetButtonForTesting();
-  views::Button* GetZoomInButtonForTesting();
-  void OnKeyEventForTesting(ui::KeyEvent* event);
-
  private:
+  FRIEND_TEST_ALL_PREFIXES(ZoomBubbleBrowserTest, ImmersiveFullscreen);
+  FRIEND_TEST_ALL_PREFIXES(ZoomBubbleBrowserTest,
+                           BubbleSuppressingExtensionRefreshesExistingBubble);
+  FRIEND_TEST_ALL_PREFIXES(ZoomBubbleBrowserTest, FocusPreventsClose);
+  FRIEND_TEST_ALL_PREFIXES(ZoomBubbleImmersiveDisabledBrowserTest,
+                           AnchorPositionsInFullscreen);
+
   // Returns true if we can reuse the existing bubble for the given
   // |web_contents|.
   static bool CanRefresh(const content::WebContents* web_contents);
@@ -93,6 +91,16 @@
     std::unique_ptr<const extensions::IconImage> icon_image;
   };
 
+  // Constructs ZoomBubbleView. Anchors the bubble to |anchor_view|, which must
+  // not be nullptr. The bubble will auto-close when |reason| is AUTOMATIC. If
+  // |immersive_mode_controller_| is present, the bubble will auto-close when
+  // the top-of-window views are revealed.
+  ZoomBubbleView(views::View* anchor_view,
+                 content::WebContents* web_contents,
+                 DisplayReason reason,
+                 ImmersiveModeController& immersive_mode_controller);
+  ~ZoomBubbleView() override;
+
   // LocationBarBubbleDelegateView:
   std::u16string GetAccessibleWindowTitle() const override;
   void OnFocus() override;
@@ -102,16 +110,27 @@
   void OnMouseEntered(const ui::MouseEvent& event) override;
   void OnMouseExited(const ui::MouseEvent& event) override;
   void Init() override;
+  void WindowClosing() override;
+  void CloseBubble() override;
+
+  // ImmersiveModeController::Observer
+  void OnImmersiveRevealStarted() override;
+  void OnImmersiveModeControllerDestroyed() override;
 
   // extensions::IconImage::Observer
   void OnExtensionIconImageChanged(extensions::IconImage* /* image */) override;
 
-  // Closes the bubble's widget.
-  void Close();
+  // Sets information about the extension that initiated the zoom change.
+  // Calling this method asserts that the extension |extension| did initiate
+  // the zoom change.
+  void SetExtensionInfo(const extensions::Extension* extension);
 
   // Updates |label_| with the up to date zoom.
   void UpdateZoomPercent();
 
+  // Updates visibility of the zoom icon.
+  void UpdateZoomBubbleStateAndIconVisibility(bool is_bubble_visible);
+
   // Starts a timer which will close the bubble if |auto_close_| is true.
   void StartTimerIfNecessary();
 
@@ -124,10 +143,16 @@
   // Called by ButtonPressed() when |image_button_| is pressed.
   void ImageButtonPressed();
 
-  raw_ptr<Browser> browser_;
+  // Gets the browser for `web_contents()`. May return null.
+  Browser* GetBrowser() const;
 
   ZoomBubbleExtensionInfo extension_info_;
 
+  // Singleton instance of the zoom bubble. The zoom bubble can only be shown on
+  // the active browser window, so there is no case in which it will be shown
+  // twice at the same time.
+  static ZoomBubbleView* zoom_bubble_;
+
   // Timer used to auto close the bubble.
   base::OneShotTimer auto_close_timer_;
 
@@ -154,6 +179,16 @@
   // button presses, since pressing a button in the bubble should not trigger
   // closing.
   bool ignore_close_bubble_ = false;
+
+  // The immersive mode controller observation for the BrowserView containing
+  // |web_contents_|.
+  base::ScopedObservation<ImmersiveModeController,
+                          ImmersiveModeController::Observer>
+      scoped_observation_{this};
+
+  // The session of the Browser that triggered the bubble. This allows the zoom
+  // icon to be updated even if the WebContents is destroyed.
+  const SessionID session_id_;
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_ZOOM_BUBBLE_VIEW_H_
diff --git a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
index 6b747a7..9767329 100644
--- a/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
+++ b/chrome/browser/ui/views/location_bar/zoom_bubble_view_browsertest.cc
@@ -7,14 +7,11 @@
 #include "build/build_config.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/exclusive_access/fullscreen_controller.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/test/test_browser_dialog.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
@@ -38,26 +35,18 @@
 #include "ui/views/test/button_test_api.h"
 #endif
 
+using ZoomBubbleBrowserTest = InProcessBrowserTest;
+
 namespace {
 
-class ZoomBubbleBrowserTest : public InProcessBrowserTest {
- protected:
-  void SetUpOnMainThread() override {
-    InProcessBrowserTest::SetUpOnMainThread();
-    zoom_bubble_coordinator_ = ZoomBubbleCoordinator::From(browser());
-  }
+void ShowInActiveTab(Browser* browser) {
+  content::WebContents* web_contents =
+      browser->tab_strip_model()->GetActiveWebContents();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::USER_GESTURE);
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
+}
 
-  void TearDownOnMainThread() override { zoom_bubble_coordinator_ = nullptr; }
-
-  void ShowInActiveTab(Browser* browser) {
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-    zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::USER_GESTURE);
-    EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
-  }
-
-  raw_ptr<ZoomBubbleCoordinator> zoom_bubble_coordinator_;
-};
+}  // namespace
 
 // Test whether the zoom bubble is anchored and whether it is visible when in
 // content fullscreen.
@@ -70,37 +59,32 @@
   content::WebContents* web_contents = browser_view->GetActiveWebContents();
 
   // The zoom bubble should be anchored when not in fullscreen.
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  ASSERT_TRUE(zoom_bubble_coordinator_->bubble());
-  const ZoomBubbleView* zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  ASSERT_TRUE(ZoomBubbleView::GetZoomBubble());
+  const ZoomBubbleView* zoom_bubble = ZoomBubbleView::GetZoomBubble();
   EXPECT_TRUE(zoom_bubble->GetAnchorView());
 
-  views::test::WidgetDestroyedWaiter waiter(
-      const_cast<views::Widget*>(zoom_bubble->GetWidget()));
-
   // Entering fullscreen should close the bubble. (We enter into tab fullscreen
   // here because tab fullscreen is non-immersive even on Chrome OS.)
   {
     // The fullscreen change notification is sent asynchronously. Wait for the
     // notification before testing the zoom bubble visibility.
-    ui_test_utils::FullscreenWaiter waiter_f(browser(),
-                                             {.tab_fullscreen = true});
+    ui_test_utils::FullscreenWaiter waiter(browser(), {.tab_fullscreen = true});
     static_cast<content::WebContentsDelegate*>(browser())
         ->EnterFullscreenModeForTab(web_contents->GetPrimaryMainFrame(), {});
-    waiter_f.Wait();
+    waiter.Wait();
   }
 #if !BUILDFLAG(IS_MAC)
   // The immersive mode controller is enabled in content fullscreen on Mac.
   ASSERT_FALSE(browser_view->immersive_mode_controller()->IsEnabled());
 #endif
-  waiter.Wait();
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
   // The bubble should not be anchored when it is shown in non-immersive
   // fullscreen.
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  ASSERT_TRUE(zoom_bubble_coordinator_->bubble());
-  zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  ASSERT_TRUE(ZoomBubbleView::GetZoomBubble());
+  zoom_bubble = ZoomBubbleView::GetZoomBubble();
   EXPECT_FALSE(zoom_bubble->GetAnchorView());
 
   // Exit fullscreen before ending the test for the sake of sanity.
@@ -138,24 +122,16 @@
   BrowserView* browser_view = static_cast<BrowserView*>(browser()->window());
   content::WebContents* web_contents = browser_view->GetActiveWebContents();
 
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  ASSERT_TRUE(zoom_bubble_coordinator_->bubble());
-  ZoomBubbleView* zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  ASSERT_TRUE(ZoomBubbleView::GetZoomBubble());
+  ZoomBubbleView* zoom_bubble = ZoomBubbleView::GetZoomBubble();
   ASSERT_TRUE(zoom_bubble);
   // Record the anchor view when not in fullscreen.
   const views::View* org_anchor_view = zoom_bubble->GetAnchorView();
 
-  // Set up a waiter to wait for the bubble to be destroyed when we enter
-  // fullscreen.
-  views::test::WidgetDestroyedWaiter close_waiter(zoom_bubble->GetWidget());
-
   // Enter into a browser fullscreen mode. This would close the zoom bubble.
   ui_test_utils::ToggleFullscreenModeAndWait(browser());
-
-  // Wait for the asynchronous widget destruction to complete.
-  close_waiter.Wait();
-
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
 #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_CHROMEOS)
   const bool should_show_toolbar = true;
@@ -166,8 +142,8 @@
 
   // The zoom bubble should be anchored to the same anchor view if the toolbar
   // shows.
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  zoom_bubble = ZoomBubbleView::GetZoomBubble();
   ASSERT_TRUE(zoom_bubble);
   if (should_show_toolbar) {
     EXPECT_EQ(org_anchor_view, zoom_bubble->GetAnchorView());
@@ -176,7 +152,7 @@
     // Hide toolbar.
     chrome::ToggleAlwaysShowToolbarInFullscreen(browser());
 
-    zoom_bubble = zoom_bubble_coordinator_->bubble();
+    zoom_bubble = ZoomBubbleView::GetZoomBubble();
     EXPECT_EQ(org_zoom_bubble, zoom_bubble);
     EXPECT_EQ(org_anchor_view, zoom_bubble->GetAnchorView());
 
@@ -185,9 +161,8 @@
     // position.
     const ui::MouseEvent event(ui::EventType::kMousePressed, gfx::Point(),
                                gfx::Point(), ui::EventTimeForNow(), 0, 0);
-    views::test::ButtonTestApi(zoom_bubble->GetZoomInButtonForTesting())
-        .NotifyClick(event);
-    zoom_bubble = zoom_bubble_coordinator_->bubble();
+    views::test::ButtonTestApi(zoom_bubble->zoom_in_button_).NotifyClick(event);
+    zoom_bubble = ZoomBubbleView::GetZoomBubble();
     EXPECT_NE(org_zoom_bubble, zoom_bubble);
     EXPECT_FALSE(zoom_bubble->GetAnchorView());
 
@@ -224,25 +199,22 @@
 
   // The zoom bubble should not be anchored when it is shown in immersive
   // fullscreen and the top-of-window views are not revealed.
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  ASSERT_TRUE(zoom_bubble_coordinator_->bubble());
-  const ZoomBubbleView* zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  ASSERT_TRUE(ZoomBubbleView::GetZoomBubble());
+  const ZoomBubbleView* zoom_bubble = ZoomBubbleView::GetZoomBubble();
   EXPECT_FALSE(zoom_bubble->GetAnchorView());
 
   // An immersive reveal should hide the zoom bubble.
-  views::test::WidgetDestroyedWaiter waiter(
-      zoom_bubble_coordinator_->bubble()->GetWidget());
   std::unique_ptr<ImmersiveRevealedLock> immersive_reveal_lock =
       immersive_controller->GetRevealedLock(
           ImmersiveModeController::ANIMATE_REVEAL_NO);
   ASSERT_TRUE(immersive_controller->IsRevealed());
-  waiter.Wait();
-  EXPECT_EQ(nullptr, zoom_bubble_coordinator_->bubble());
+  EXPECT_EQ(nullptr, ZoomBubbleView::zoom_bubble_);
 
   // The zoom bubble should be anchored when it is shown in immersive fullscreen
   // and the top-of-window views are revealed.
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  zoom_bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  zoom_bubble = ZoomBubbleView::GetZoomBubble();
   ASSERT_TRUE(zoom_bubble);
   EXPECT_TRUE(zoom_bubble->GetAnchorView());
 
@@ -251,7 +223,7 @@
   // the zoom bubble was still visible.)
   immersive_reveal_lock.reset();
   EXPECT_TRUE(immersive_controller->IsRevealed());
-  zoom_bubble_coordinator_->Hide();
+  ZoomBubbleView::CloseCurrentBubble();
   // The zoom bubble is deleted on a task.
   content::RunAllPendingInMessageLoop();
   EXPECT_FALSE(immersive_controller->IsRevealed());
@@ -266,11 +238,11 @@
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
 
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
   // Close the current tab and try opening the zoom bubble with stale
   // |web_contents|.
   chrome::CloseTab(browser());
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
 }
 
 // Ensure a tab switch closes the bubble.
@@ -279,10 +251,10 @@
       AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK));
   ShowInActiveTab(browser());
   views::test::WidgetDestroyedWaiter close_waiter(
-      zoom_bubble_coordinator_->bubble()->GetWidget());
+      ZoomBubbleView::GetZoomBubble()->GetWidget());
   chrome::SelectNextTab(browser());
   close_waiter.Wait();
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 }
 
 // Ensure the bubble is dismissed on tab closure and doesn't reference a
@@ -292,19 +264,21 @@
       AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_LINK));
   ShowInActiveTab(browser());
 
-  ZoomBubbleView* bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView* bubble = ZoomBubbleView::GetZoomBubble();
   EXPECT_TRUE(bubble);
 
   views::test::TestWidgetObserver observer(bubble->GetWidget());
   EXPECT_FALSE(bubble->GetWidget()->IsClosed());
 
-  views::test::WidgetDestroyedWaiter waiter(bubble->GetWidget());
-
   chrome::CloseTab(browser());
-  // Wait for the widget destruction to complete.
-  waiter.Wait();
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
-  EXPECT_FALSE(zoom_bubble_coordinator_->bubble());
+  // Widget::Close() completes asynchronously, so it's still safe to access
+  // |bubble| here, even though GetZoomBubble() returned null.
+  EXPECT_FALSE(observer.widget_closed());
+  EXPECT_TRUE(bubble->GetWidget()->IsClosed());
+
+  base::RunLoop().RunUntilIdle();
   EXPECT_TRUE(observer.widget_closed());
 }
 
@@ -343,11 +317,11 @@
   zoom_controller->SetZoomMode(zoom::ZoomController::ZOOM_MODE_MANUAL);
 
   ShowInActiveTab(browser());
-  const ZoomBubbleView* bubble = zoom_bubble_coordinator_->bubble();
+  const ZoomBubbleView* bubble = ZoomBubbleView::GetZoomBubble();
   ASSERT_TRUE(bubble);
 
   const double old_zoom_level = zoom_controller->GetZoomLevel();
-  const std::u16string old_label(bubble->GetLabelForTesting());
+  const std::u16string old_label(bubble->label_->GetText());
 
   scoped_refptr<const extensions::Extension> extension =
       extensions::ExtensionBuilder("Test").Build();
@@ -356,8 +330,8 @@
   const double new_zoom_level = old_zoom_level + 0.5;
   zoom_controller->SetZoomLevelByClient(new_zoom_level, client);
 
-  ASSERT_EQ(zoom_bubble_coordinator_->bubble(), bubble);
-  EXPECT_NE(bubble->GetLabelForTesting(), old_label);
+  ASSERT_EQ(ZoomBubbleView::GetZoomBubble(), bubble);
+  EXPECT_NE(bubble->label_->GetText(), old_label);
 }
 
 class ZoomBubbleReuseTest : public ZoomBubbleBrowserTest {
@@ -382,10 +356,10 @@
     const double zoom_level2 = zoom_level1 + 0.5;
 
     zoom_controller->SetZoomLevelByClient(zoom_level1, client1);
-    const ZoomBubbleView* bubble1 = zoom_bubble_coordinator_->bubble();
+    const ZoomBubbleView* bubble1 = ZoomBubbleView::GetZoomBubble();
     EXPECT_TRUE(bubble1);
     zoom_controller->SetZoomLevelByClient(zoom_level2, client2);
-    const ZoomBubbleView* bubble2 = zoom_bubble_coordinator_->bubble();
+    const ZoomBubbleView* bubble2 = ZoomBubbleView::GetZoomBubble();
     EXPECT_TRUE(bubble2);
 
     return bubble1 == bubble2;
@@ -398,8 +372,6 @@
     extension2_ = extensions::ExtensionBuilder("Test2").Build();
     client2_ =
         base::MakeRefCounted<const TestZoomRequestClient>(extension2_, false);
-
-    zoom_bubble_coordinator_ = ZoomBubbleCoordinator::From(browser());
   }
 
   scoped_refptr<const extensions::Extension> extension1_;
@@ -435,27 +407,8 @@
   ZoomBubbleDialogTest(const ZoomBubbleDialogTest&) = delete;
   ZoomBubbleDialogTest& operator=(const ZoomBubbleDialogTest&) = delete;
 
-  void SetUpOnMainThread() override {
-    DialogBrowserTest::SetUpOnMainThread();
-    zoom_bubble_coordinator_ = ZoomBubbleCoordinator::From(browser());
-  }
-
-  void TearDownOnMainThread() override {
-    zoom_bubble_coordinator_ = nullptr;
-    DialogBrowserTest::TearDownOnMainThread();
-  }
-
-  void ShowInActiveTab(Browser* browser) {
-    content::WebContents* web_contents =
-        browser->tab_strip_model()->GetActiveWebContents();
-    zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::USER_GESTURE);
-    EXPECT_TRUE(zoom_bubble_coordinator_->bubble());
-  }
-
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override { ShowInActiveTab(browser()); }
-
-  raw_ptr<ZoomBubbleCoordinator> zoom_bubble_coordinator_;
 };
 
 // Test that calls ShowUi("default").
@@ -468,11 +421,11 @@
 IN_PROC_BROWSER_TEST_F(ZoomBubbleBrowserTest, FocusPreventsClose) {
   content::WebContents* web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
-  zoom_bubble_coordinator_->Show(web_contents, ZoomBubbleView::AUTOMATIC);
-  ZoomBubbleView* bubble = zoom_bubble_coordinator_->bubble();
+  ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
+  ZoomBubbleView* bubble = ZoomBubbleView::GetZoomBubble();
   ASSERT_TRUE(bubble);
   // |auto_close_timer_| is running so that the bubble is closed at the end.
-  EXPECT_TRUE(bubble->GetAutoCloseTimerForTesting()->IsRunning());
+  EXPECT_TRUE(bubble->auto_close_timer_.IsRunning());
 
   views::FocusManager* focus_manager = bubble->GetFocusManager();
   // The bubble must have an associated Widget from which to get a FocusManager.
@@ -480,11 +433,9 @@
 
   // Focus is usually gained via a key combination like alt+shift+a. The test
   // simulates this by focusing the bubble and then sending an empty KeyEvent.
-  focus_manager->SetFocusedView(bubble->GetResetButtonForTesting());
-  bubble->OnKeyEventForTesting(nullptr);
+  focus_manager->SetFocusedView(bubble->reset_button_);
+  bubble->OnKeyEvent(nullptr);
   // |auto_close_timer_| should not be running since focus should prevent the
   // bubble from closing.
-  EXPECT_FALSE(bubble->GetAutoCloseTimerForTesting()->IsRunning());
+  EXPECT_FALSE(bubble->auto_close_timer_.IsRunning());
 }
-
-}  // namespace
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.cc
index 5d03d1d..2dfdb66f 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.cc
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.cc
@@ -5,6 +5,8 @@
 #include "chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h"
 
 #include "base/feature_list.h"
+#include "base/functional/bind.h"
+#include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/observer_list_types.h"
@@ -13,6 +15,7 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/omnibox/omnibox_view.h"
 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.h"
 #include "chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h"
 #include "chrome/browser/ui/views/theme_copying_widget.h"
 #include "chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.h"
@@ -21,39 +24,36 @@
 #include "chrome/common/webui_url_constants.h"
 #include "components/omnibox/common/omnibox_features.h"
 #include "content/public/browser/render_widget_host_view.h"
-#include "ui/base/metadata/metadata_impl_macros.h"
+#include "omnibox_popup_webui_content.h"
+#include "rounded_omnibox_results_frame.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
+#include "ui/views/view_utils.h"
 
 OmniboxPopupPresenter::OmniboxPopupPresenter(LocationBarView* location_bar_view,
                                              OmniboxController* controller)
-    : views::WebView(location_bar_view->profile()),
-      location_bar_view_(location_bar_view),
+    : location_bar_view_(location_bar_view),
+      controller_(controller),
       include_location_bar_cutout_(
           !base::FeatureList::IsEnabled(omnibox::kWebUIOmniboxFullPopup)) {
-  set_owned_by_client(OwnedByClientPassKey());
-
-  // Make the OmniboxController available to the OmniboxPopupUI.
-  OmniboxPopupWebContentsHelper::CreateForWebContents(GetWebContents());
-  OmniboxPopupWebContentsHelper::FromWebContents(GetWebContents())
-      ->set_omnibox_controller(controller);
-
-  LoadInitialURL(GURL(chrome::kChromeUIOmniboxPopupURL));
-
+  owned_omnibox_popup_webui_content_ =
+      std::make_unique<OmniboxPopupWebUIContent>(
+          this, location_bar_view_, controller_, include_location_bar_cutout_);
   location_bar_view_->AddObserver(this);
 }
 
 OmniboxPopupPresenter::~OmniboxPopupPresenter() {
   location_bar_view_->RemoveObserver(this);
-  ReleaseWidget(false);
+  ReleaseWidget();
 }
 
 void OmniboxPopupPresenter::Show() {
   if (!widget_) {
-    widget_ = new ThemeCopyingWidget(location_bar_view_->GetWidget());
+    widget_ =
+        std::make_unique<ThemeCopyingWidget>(location_bar_view_->GetWidget());
 
     const views::Widget* parent_widget = location_bar_view_->GetWidget();
     views::Widget::InitParams params(
-        views::Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET,
+        views::Widget::InitParams::CLIENT_OWNS_WIDGET,
         views::Widget::InitParams::TYPE_POPUP);
 #if BUILDFLAG(IS_WIN)
     // On Windows use the software compositor to ensure that we don't block
@@ -64,36 +64,28 @@
     params.parent = parent_widget->GetNativeView();
     params.context = parent_widget->GetNativeWindow();
 
-    RoundedOmniboxResultsFrame::OnBeforeWidgetInit(&params, widget_);
+    RoundedOmniboxResultsFrame::OnBeforeWidgetInit(&params, widget_.get());
+
+    widget_->MakeCloseSynchronous(base::BindOnce(
+        &OmniboxPopupPresenter::OnWidgetClosed, base::Unretained(this)));
 
     widget_->Init(std::move(params));
     widget_->SetContentsView(std::make_unique<RoundedOmniboxResultsFrame>(
-        this, location_bar_view_, include_location_bar_cutout_));
-    widget_->AddObserver(this);
+        owned_omnibox_popup_webui_content_.release(), location_bar_view_,
+        include_location_bar_cutout_));
+
     widget_->SetVisibilityChangedAnimationsEnabled(false);
-    // On ShowInactive(), the widget height can not be 0 or else the compositor
-    // thinks the webview is hidden and will not calculate its preferred size.
+    // On Show(), the widget height can not be 0 or else the compositor thinks
+    // the webview is hidden and will not calculate its preferred size.
     SetWidgetContentHeight(1);
     widget_->ShowInactive();
-
-    // Manually set zoom level, since any zooming is undesirable in the omnibox.
-    auto* zoom_controller =
-        zoom::ZoomController::FromWebContents(GetWebContents());
-    if (!zoom_controller) {
-      // Create ZoomController manually, if not already exists, because it is
-      // not automatically created when the WebUI has not been opened in a tab.
-      zoom_controller =
-          zoom::ZoomController::CreateForWebContents(GetWebContents());
-    }
-    zoom_controller->SetZoomMode(zoom::ZoomController::ZOOM_MODE_ISOLATED);
-    zoom_controller->SetZoomLevel(0);
   }
 }
 
 void OmniboxPopupPresenter::Hide() {
   // Only close if UI DevTools settings allow.
   if (widget_ && widget_->ShouldHandleNativeWidgetActivationChanged(false)) {
-    ReleaseWidget(true);
+    ReleaseWidget();
   }
 }
 
@@ -102,36 +94,10 @@
 }
 
 WebuiOmniboxHandler* OmniboxPopupPresenter::GetHandler() {
-  const bool ready = IsHandlerReady();
-  if (!requested_handler_) {
-    // Only log on first access.
-    requested_handler_ = true;
-    base::UmaHistogramBoolean("Omnibox.WebUI.HandlerReadyOnFirstAccess", ready);
+  if (auto* content = GetOmniboxPopupWebUIContent()) {
+    return content->GetHandler();
   }
-  if (!ready) {
-    return nullptr;
-  }
-  OmniboxPopupUI* omnibox_popup_ui = static_cast<OmniboxPopupUI*>(
-      GetWebContents()->GetWebUI()->GetController());
-  return omnibox_popup_ui->handler();
-}
-
-void OmniboxPopupPresenter::AddedToWidget() {
-  views::WebView::AddedToWidget();
-  const float corner_radius =
-      views::LayoutProvider::Get()->GetCornerRadiusMetric(
-          views::ShapeContextTokens::kOmniboxExpandedRadius);
-  gfx::RoundedCornersF rounded_corner_radii =
-      gfx::RoundedCornersF(include_location_bar_cutout_ ? 0 : corner_radius,
-                           include_location_bar_cutout_ ? 0 : corner_radius,
-                           corner_radius, corner_radius);
-  holder()->SetCornerRadii(rounded_corner_radii);
-}
-
-void OmniboxPopupPresenter::OnWidgetDestroyed(views::Widget* widget) {
-  if (widget == widget_) {
-    widget_ = nullptr;
-  }
+  return nullptr;
 }
 
 void OmniboxPopupPresenter::SetWidgetContentHeight(int content_height) {
@@ -151,53 +117,49 @@
   }
 }
 
-void OmniboxPopupPresenter::ResizeDueToAutoResize(content::WebContents* source,
-                                                  const gfx::Size& new_size) {
-  SetWidgetContentHeight(new_size.height());
+void OmniboxPopupPresenter::OnViewBoundsChanged(views::View* observed_view) {
+  CHECK(observed_view == location_bar_view_);
+  if (auto* content = GetOmniboxPopupWebUIContent()) {
+    const int width =
+        location_bar_view_->width() +
+        RoundedOmniboxResultsFrame::GetLocationBarAlignmentInsets().width();
+    gfx::Size min_size(width, 1);
+    gfx::Size max_size(width, INT_MAX);
+
+    content::RenderWidgetHostView* render_widget_host_view =
+        content->GetWebContents()->GetRenderWidgetHostView();
+    if (render_widget_host_view) {
+      render_widget_host_view->EnableAutoResize(min_size, max_size);
+    }
+  }
 }
 
-void OmniboxPopupPresenter::OnViewBoundsChanged(View* observed_view) {
-  CHECK(observed_view == location_bar_view_);
-  const int width =
-      location_bar_view_->width() +
-      RoundedOmniboxResultsFrame::GetLocationBarAlignmentInsets().width();
-  gfx::Size min_size(width, 1);
-  gfx::Size max_size(width, INT_MAX);
-
-  content::RenderWidgetHostView* render_widget_host_view =
-      GetWebContents()->GetRenderWidgetHostView();
-  if (render_widget_host_view) {
-    render_widget_host_view->EnableAutoResize(min_size, max_size);
-  }
+void OmniboxPopupPresenter::OnWidgetClosed(
+    views::Widget::ClosedReason closed_reason) {
+  owned_omnibox_popup_webui_content_ = AsViewClass<OmniboxPopupWebUIContent>(
+      AsViewClass<RoundedOmniboxResultsFrame>(widget_->GetContentsView())
+          ->ExtractContents());
+  widget_.reset();
 }
 
 bool OmniboxPopupPresenter::IsHandlerReady() {
-  OmniboxPopupUI* omnibox_popup_ui = static_cast<OmniboxPopupUI*>(
-      GetWebContents()->GetWebUI()->GetController());
-  return omnibox_popup_ui->handler() &&
-         omnibox_popup_ui->handler()->IsRemoteBound();
+  return GetOmniboxPopupWebUIContent()->IsHandlerReady();
 }
 
-void OmniboxPopupPresenter::ReleaseWidget(bool close) {
+void OmniboxPopupPresenter::ReleaseWidget() {
   if (widget_) {
-    // Avoid possibility of dangling raw_ptr by nulling before cleanup.
-    views::Widget* widget = widget_;
-    widget_ = nullptr;
-
-    widget->RemoveObserver(this);
-    if (close) {
-      // Ensure we close `widget_` synchronously.  This is necessary as the
-      // `widget_`'s contents view has dependencies on the hosting widget's
-      // BrowserView (see `SetContentsView()` above). Since the popup widget is
-      // owned by its NativeWidget there is a risk of dangling pointers if it is
-      // not destroyed synchronously with its parent.
-      // TODO(crbug.com/40232479): Once this is migrated to CLIENT_OWNS_WIDGET
-      // this will no longer be necessary.
-      widget->CloseNow();
-    }
+    widget_->CloseWithReason(views::Widget::ClosedReason::kUnspecified);
   }
-  CHECK(!views::WidgetObserver::IsInObserverList());
 }
 
-BEGIN_METADATA(OmniboxPopupPresenter)
-END_METADATA
+OmniboxPopupWebUIContent* OmniboxPopupPresenter::GetOmniboxPopupWebUIContent() {
+  if (widget_) {
+    return views::AsViewClass<OmniboxPopupWebUIContent>(
+        views::AsViewClass<RoundedOmniboxResultsFrame>(
+            widget_->GetContentsView()));
+  }
+  if (owned_omnibox_popup_webui_content_) {
+    return owned_omnibox_popup_webui_content_.get();
+  }
+  return nullptr;
+}
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h b/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h
index 6da1b7f..776d285 100644
--- a/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h
@@ -5,10 +5,11 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_POPUP_PRESENTER_H_
 #define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_POPUP_PRESENTER_H_
 
+#include <memory>
+
 #include "base/memory/raw_ptr.h"
 #include "chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h"
 #include "content/public/browser/render_frame_host.h"
-#include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/controls/webview/webview.h"
@@ -18,6 +19,7 @@
 
 class LocationBarView;
 class OmniboxController;
+class OmniboxPopupWebUIContent;
 
 // An assistant class for OmniboxPopupViewWebUI, this manages a WebView and a
 // Widget to present WebUI suggestions.  This class is an implementation detail
@@ -25,11 +27,7 @@
 // of this class is presentation only, i.e. Views and Widgets.  For omnibox
 // logic concerns and communication between native omnibox code and the WebUI
 // code, work with OmniboxPopupViewWebUI directly.
-class OmniboxPopupPresenter : public views::WebView,
-                              public views::WidgetObserver,
-                              public views::ViewObserver {
-  METADATA_HEADER(OmniboxPopupPresenter, views::WebView)
-
+class OmniboxPopupPresenter : public views::ViewObserver {
  public:
   OmniboxPopupPresenter(LocationBarView* location_bar_view,
                         OmniboxController* controller);
@@ -48,37 +46,39 @@
   // Returns nullptr if handler is not ready.
   WebuiOmniboxHandler* GetHandler();
 
-  // views::View:
-  void AddedToWidget() override;
-
-  // views::WidgetObserver:
-  void OnWidgetDestroyed(views::Widget* widget) override;
-
   // views::ViewObserver:
-  void OnViewBoundsChanged(View* observed_view) override;
-
-  // content::WebContentsDelegate:
-  void ResizeDueToAutoResize(content::WebContents* source,
-                             const gfx::Size& new_size) override;
+  void OnViewBoundsChanged(views::View* observed_view) override;
 
   void SetWidgetContentHeight(int content_height);
 
  private:
   friend class OmniboxPopupViewWebUITest;
 
+  void OnWidgetClosed(views::Widget::ClosedReason closed_reason);
+
   // Tells whether the WebUI handler is loaded and ready to receive calls.
   bool IsHandlerReady();
 
   // Remove observation and reset widget, optionally requesting it to close.
-  void ReleaseWidget(bool close);
+  void ReleaseWidget();
+
+  // Returns the webui content, either from the owned pointer or from the
+  // content of the widget_.
+  OmniboxPopupWebUIContent* GetOmniboxPopupWebUIContent();
 
   // The location bar view that owns `this`.
   const raw_ptr<LocationBarView> location_bar_view_;
 
+  // The Omnibox WebUI popup contents. It is held here when the widget_ isn't
+  // being shown.
+  std::unique_ptr<OmniboxPopupWebUIContent> owned_omnibox_popup_webui_content_;
+
+  // The controller for the Omnibox.
+  raw_ptr<OmniboxController> controller_ = nullptr;
+
   // The popup widget that contains this WebView. Created and closed by `this`;
   // owned and destroyed by the OS.
-  // TODO(crbug.com/40232479): Migrate this to CLIENT_OWNS_WIDGET.
-  raw_ptr<views::Widget> widget_ = nullptr;
+  std::unique_ptr<views::Widget> widget_;
 
   // Whether any call to `GetHandler` has been made.
   bool requested_handler_ = false;
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.cc
new file mode 100644
index 0000000..61667b5
--- /dev/null
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.cc
@@ -0,0 +1,94 @@
+// Copyright 2025 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/ui/views/omnibox/omnibox_popup_webui_content.h"
+
+#include "base/feature_list.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
+#include "chrome/browser/ui/views/omnibox/omnibox_popup_presenter.h"
+#include "chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h"
+#include "chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.h"
+#include "chrome/browser/ui/webui/omnibox_popup/omnibox_popup_web_contents_helper.h"
+#include "chrome/common/webui_url_constants.h"
+#include "components/omnibox/common/omnibox_features.h"
+#include "components/zoom/zoom_controller.h"
+#include "ui/base/metadata/metadata_impl_macros.h"
+#include "ui/gfx/geometry/rounded_corners_f.h"
+
+OmniboxPopupWebUIContent::OmniboxPopupWebUIContent(
+    OmniboxPopupPresenter* presenter,
+    LocationBarView* location_bar_view,
+    OmniboxController* controller,
+    bool include_location_bar_cutout)
+    : views::WebView(location_bar_view->profile()),
+      location_bar_view_(location_bar_view),
+      omnibox_popup_presenter_(presenter),
+      include_location_bar_cutout_(include_location_bar_cutout) {
+  // Make the OmniboxController available to the OmniboxPopupUI.
+  OmniboxPopupWebContentsHelper::CreateForWebContents(GetWebContents());
+  OmniboxPopupWebContentsHelper::FromWebContents(GetWebContents())
+      ->set_omnibox_controller(controller);
+
+  LoadInitialURL(GURL(chrome::kChromeUIOmniboxPopupURL));
+}
+
+OmniboxPopupWebUIContent::~OmniboxPopupWebUIContent() = default;
+
+WebuiOmniboxHandler* OmniboxPopupWebUIContent::GetHandler() {
+  const bool ready = IsHandlerReady();
+  if (!requested_handler_) {
+    // Only log on first access.
+    requested_handler_ = true;
+    base::UmaHistogramBoolean("Omnibox.WebUI.HandlerReadyOnFirstAccess", ready);
+  }
+  if (!ready) {
+    return nullptr;
+  }
+  OmniboxPopupUI* omnibox_popup_ui = static_cast<OmniboxPopupUI*>(
+      GetWebContents()->GetWebUI()->GetController());
+  return omnibox_popup_ui->handler();
+}
+
+void OmniboxPopupWebUIContent::AddedToWidget() {
+  views::WebView::AddedToWidget();
+  const float corner_radius =
+      views::LayoutProvider::Get()->GetCornerRadiusMetric(
+          views::ShapeContextTokens::kOmniboxExpandedRadius);
+  gfx::RoundedCornersF rounded_corner_radii =
+      gfx::RoundedCornersF(include_location_bar_cutout_ ? 0 : corner_radius,
+                           include_location_bar_cutout_ ? 0 : corner_radius,
+                           corner_radius, corner_radius);
+  holder()->SetCornerRadii(rounded_corner_radii);
+
+  // Manually set zoom level, since any zooming is undesirable in the omnibox.
+  auto* zoom_controller =
+      zoom::ZoomController::FromWebContents(GetWebContents());
+  if (!zoom_controller) {
+    // Create ZoomController manually, if not already exists, because it is
+    // not automatically created when the WebUI has not been opened in a tab.
+    zoom_controller =
+        zoom::ZoomController::CreateForWebContents(GetWebContents());
+  }
+  zoom_controller->SetZoomMode(zoom::ZoomController::ZOOM_MODE_ISOLATED);
+  zoom_controller->SetZoomLevel(0);
+}
+
+void OmniboxPopupWebUIContent::ResizeDueToAutoResize(
+    content::WebContents* source,
+    const gfx::Size& new_size) {
+  omnibox_popup_presenter_->SetWidgetContentHeight(new_size.height());
+}
+
+bool OmniboxPopupWebUIContent::IsHandlerReady() {
+  OmniboxPopupUI* omnibox_popup_ui = static_cast<OmniboxPopupUI*>(
+      GetWebContents()->GetWebUI()->GetController());
+  return omnibox_popup_ui->handler() &&
+         omnibox_popup_ui->handler()->IsRemoteBound();
+}
+
+BEGIN_METADATA(OmniboxPopupWebUIContent)
+END_METADATA
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.h b/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.h
new file mode 100644
index 0000000..cb9a219
--- /dev/null
+++ b/chrome/browser/ui/views/omnibox/omnibox_popup_webui_content.h
@@ -0,0 +1,61 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_POPUP_WEBUI_CONTENT_H_
+#define CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_POPUP_WEBUI_CONTENT_H_
+
+#include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
+#include "chrome/browser/ui/webui/searchbox/webui_omnibox_handler.h"
+#include "content/public/browser/render_frame_host.h"
+#include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/controls/webview/webview.h"
+#include "ui/views/view_observer.h"
+#include "ui/views/widget/widget.h"
+
+class LocationBarView;
+class OmniboxController;
+class OmniboxPopupPresenter;
+
+// The content WebView for the popup of a WebUI Omnibox.
+class OmniboxPopupWebUIContent : public views::WebView {
+  METADATA_HEADER(OmniboxPopupWebUIContent, views::WebView)
+ public:
+  OmniboxPopupWebUIContent() = delete;
+  OmniboxPopupWebUIContent(OmniboxPopupPresenter* presenter,
+                           LocationBarView* location_bar_view,
+                           OmniboxController* controller,
+                           bool include_location_bar_cutout);
+  OmniboxPopupWebUIContent(const OmniboxPopupWebUIContent&) = delete;
+  OmniboxPopupWebUIContent& operator=(const OmniboxPopupWebUIContent&) = delete;
+  ~OmniboxPopupWebUIContent() override;
+
+  // Get the handler for communicating with the WebUI interface.
+  // Returns nullptr if handler is not ready.
+  WebuiOmniboxHandler* GetHandler();
+
+  // Tells whether the WebUI handler is loaded and ready to receive calls.
+  bool IsHandlerReady();
+
+  // views::View:
+  void AddedToWidget() override;
+
+  // content::WebContentsDelegate:
+  void ResizeDueToAutoResize(content::WebContents* source,
+                             const gfx::Size& new_size) override;
+
+ private:
+  raw_ptr<LocationBarView> location_bar_view_ = nullptr;
+  raw_ptr<OmniboxPopupPresenter> omnibox_popup_presenter_ = nullptr;
+
+  // Whether any call to `GetHandler` has been made.
+  bool requested_handler_ = false;
+
+  // Whether or not the WebUI popup includes the `location_bar_view` cutout.
+  bool include_location_bar_cutout_ = true;
+};
+
+#endif  // CHROME_BROWSER_UI_VIEWS_OMNIBOX_OMNIBOX_POPUP_WEBUI_CONTENT_H_
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
index ee2ea7a..69d062e9 100644
--- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
+++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h"
 
+#include <memory>
+#include <utility>
+
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
@@ -308,6 +311,15 @@
   return views::BubbleBorder::GetBorderAndShadowInsets(kElevation);
 }
 
+std::unique_ptr<views::View> RoundedOmniboxResultsFrame::ExtractContents() {
+  auto contents = std::exchange(contents_, nullptr);
+  return contents_host_->RemoveChildViewT<views::View>(contents);
+}
+
+views::View* RoundedOmniboxResultsFrame::GetContents() {
+  return contents_;
+}
+
 void RoundedOmniboxResultsFrame::Layout(PassKey) {
   // This is called when the Widget resizes due to results changing. Resizing
   // the Widget is fast on ChromeOS, but slow on other platforms, and can't be
diff --git a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
index b2238d2..823cb66 100644
--- a/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
+++ b/chrome/browser/ui/views/omnibox/rounded_omnibox_results_frame.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_OMNIBOX_ROUNDED_OMNIBOX_RESULTS_FRAME_H_
 #define CHROME_BROWSER_UI_VIEWS_OMNIBOX_ROUNDED_OMNIBOX_RESULTS_FRAME_H_
 
+#include <memory>
+
 #include "base/memory/raw_ptr.h"
 #include "ui/base/metadata/metadata_header_macros.h"
 #include "ui/gfx/geometry/insets.h"
@@ -39,6 +41,12 @@
   // Returns the blur region taken up by the Omnibox popup shadows.
   static gfx::Insets GetShadowInsets();
 
+  // Removes the `contents_` view and returns ownership to the caller.
+  std::unique_ptr<views::View> ExtractContents();
+
+  // Returns the `contents_` view.
+  views::View* GetContents();
+
   // views::View:
   void Layout(PassKey) override;
   void AddedToWidget() override;
diff --git a/chrome/browser/ui/views/page_action/zoom_view.cc b/chrome/browser/ui/views/page_action/zoom_view.cc
index 04aa706..c9e13f6 100644
--- a/chrome/browser/ui/views/page_action/zoom_view.cc
+++ b/chrome/browser/ui/views/page_action/zoom_view.cc
@@ -6,14 +6,10 @@
 
 #include "base/i18n/number_formatting.h"
 #include "chrome/app/vector_icons/vector_icons.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/view_ids.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/omnibox/browser/location_bar_model.h"
-#include "components/tabs/public/tab_interface.h"
 #include "components/zoom/zoom_controller.h"
 #include "ui/accessibility/ax_node_data.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -22,23 +18,6 @@
 #include "ui/gfx/geometry/size.h"
 #include "ui/views/accessibility/view_accessibility.h"
 
-namespace {
-
-ZoomBubbleCoordinator* GetZoomBubbleCoordinator(
-    content::WebContents* web_contents) {
-  if (!web_contents) {
-    return nullptr;
-  }
-
-  auto* tab_interface = tabs::TabInterface::GetFromContents(web_contents);
-  CHECK(tab_interface);
-
-  auto* bwi = tab_interface->GetBrowserWindowInterface();
-  return ZoomBubbleCoordinator::From(bwi);
-}
-
-}  // namespace
-
 ZoomView::ZoomView(IconLabelBubbleView::Delegate* icon_label_bubble_delegate,
                    PageActionIconView::Delegate* page_action_icon_delegate)
     : PageActionIconView(nullptr,
@@ -97,9 +76,6 @@
     return;
   }
 
-  auto* zoom_bubble_coordinator = GetZoomBubbleCoordinator(web_contents);
-  CHECK(zoom_bubble_coordinator);
-
   if (ShouldBeVisible(can_show_bubble)) {
     zoom::ZoomController* zoom_controller =
         zoom::ZoomController::FromWebContents(web_contents);
@@ -120,34 +96,26 @@
     SetVisible(true);
 
     if (can_show_bubble) {
-      zoom_bubble_coordinator->Show(web_contents, ZoomBubbleView::AUTOMATIC);
+      ZoomBubbleView::ShowBubble(web_contents, ZoomBubbleView::AUTOMATIC);
     } else {
-      zoom_bubble_coordinator->RefreshIfShowing(web_contents);
+      ZoomBubbleView::RefreshBubbleIfShowing(web_contents);
     }
   } else {
     // Close the bubble first to ensure focus is not lost when SetVisible(false)
     // is called. See crbug.com/913829.
     if (HasAssociatedBubble()) {
-      zoom_bubble_coordinator->Hide();
+      ZoomBubbleView::CloseCurrentBubble();
     }
     SetVisible(false);
   }
 }
 
 void ZoomView::OnExecuting(PageActionIconView::ExecuteSource source) {
-  auto* zoom_bubble_coordinator = GetZoomBubbleCoordinator(GetWebContents());
-  CHECK(zoom_bubble_coordinator);
-
-  zoom_bubble_coordinator->Show(GetWebContents(), ZoomBubbleView::USER_GESTURE);
+  ZoomBubbleView::ShowBubble(GetWebContents(), ZoomBubbleView::USER_GESTURE);
 }
 
 views::BubbleDialogDelegate* ZoomView::GetBubble() const {
-  auto* zoom_bubble_coordinator = GetZoomBubbleCoordinator(GetWebContents());
-  if (!zoom_bubble_coordinator) {
-    return nullptr;
-  }
-
-  return zoom_bubble_coordinator->bubble();
+  return ZoomBubbleView::GetZoomBubble();
 }
 
 const gfx::VectorIcon& ZoomView::GetVectorIcon() const {
diff --git a/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc b/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc
index 52e2351..9043f16 100644
--- a/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc
+++ b/chrome/browser/ui/views/page_action/zoom_view_browsertest.cc
@@ -5,17 +5,13 @@
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_view.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "content/public/test/browser_test.h"
-#include "ui/views/test/widget_test.h"
 
 using ZoomViewBrowserTest = InProcessBrowserTest;
 
@@ -33,31 +29,25 @@
   auto* zoom_icon = GetZoomView(browser());
   auto* second_zoom_icon = GetZoomView(CreateBrowser(browser()->profile()));
 
-  ZoomBubbleCoordinator* zoom_bubble_coordinator =
-      ZoomBubbleCoordinator::From(browser());
-
   // Initially no icon.
-  EXPECT_FALSE(zoom_bubble_coordinator->bubble());
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
   EXPECT_FALSE(zoom_icon->GetVisible());
   EXPECT_FALSE(second_zoom_icon->GetVisible());
 
   // Zooming in one browser should show the icon in all browsers on the same
   // URL.
   chrome::Zoom(browser(), content::PAGE_ZOOM_IN);
-  EXPECT_TRUE(zoom_bubble_coordinator->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
   EXPECT_TRUE(zoom_icon->GetVisible());
   EXPECT_TRUE(second_zoom_icon->GetVisible());
 
-  views::test::WidgetDestroyedWaiter waiter(
-      zoom_bubble_coordinator->bubble()->GetWidget());
-  zoom_bubble_coordinator->Hide();
-  waiter.Wait();
-  EXPECT_FALSE(zoom_bubble_coordinator->bubble());
+  ZoomBubbleView::CloseCurrentBubble();
+  EXPECT_FALSE(ZoomBubbleView::GetZoomBubble());
 
   // Clearing the zoom should clear the icon for all browsers on the URL except
   // the one where the interaction occurred because the bubble is showing there.
   chrome::Zoom(browser(), content::PAGE_ZOOM_RESET);
-  EXPECT_TRUE(zoom_bubble_coordinator->bubble());
+  EXPECT_TRUE(ZoomBubbleView::GetZoomBubble());
   EXPECT_TRUE(zoom_icon->GetVisible());
   EXPECT_FALSE(second_zoom_icon->GetVisible());
 }
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc b/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
index 7216c5a..b8e2f3e7 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view_ui_browsertest.cc
@@ -502,7 +502,7 @@
     if (new_browser) {
       ASSERT_NE(new_browser, browser());
       CloseBrowserSynchronously(browser());
-      SelectFirstBrowser();
+      SetBrowser(new_browser);
       ASSERT_EQ(new_browser, browser());
     }
 
diff --git a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_interactive_uitest.cc b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_interactive_uitest.cc
index c93bc07..c8208d1 100644
--- a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_interactive_uitest.cc
+++ b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_interactive_uitest.cc
@@ -302,6 +302,25 @@
   RunTestSequence(EnsureNotPresent(ConfirmInfoBar::kInfoBarElementId));
 }
 
+// Test that the session restore infobar is not shown on a new tab after the
+// pref is changed.
+IN_PROC_BROWSER_TEST_P(SessionRestoreInfobarInteractiveTest,
+                       InfobarNotShownOnNewTabAfterPrefChange) {
+  CreateInfobar(browser(), false);
+  RunTestSequence(WaitForShow(ConfirmInfoBar::kInfoBarElementId),
+                  // Change the pref to continue where you left off.
+                  Do([this]() {
+                    browser()->profile()->GetPrefs()->SetInteger(
+                        prefs::kRestoreOnStartup, 1);
+                  }),
+                  // The infobar should be hidden after the pref change.
+                  WaitForHide(ConfirmInfoBar::kInfoBarElementId),
+                  // Open a new tab.
+                  AddInstrumentedTab(kSecondTabContents, GURL("about:blank")),
+                  // Ensure the infobar is not present on the new tab.
+                  EnsureNotPresent(ConfirmInfoBar::kInfoBarElementId));
+}
+
 INSTANTIATE_TEST_SUITE_P(All,
                          SessionRestoreInfobarInteractiveTest,
                          testing::Bool());
diff --git a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.cc b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.cc
index 4b47738..e7a7249 100644
--- a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.cc
+++ b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.cc
@@ -19,9 +19,12 @@
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_delegate.h"
+#include "chrome/common/pref_names.h"
 #include "components/infobars/content/content_infobar_manager.h"
 #include "components/infobars/core/confirm_infobar_delegate.h"
 #include "components/infobars/core/infobar.h"
+#include "components/prefs/pref_change_registrar.h"
+#include "components/prefs/pref_service.h"
 #include "content/public/browser/web_contents.h"
 
 namespace session_restore_infobar {
@@ -43,6 +46,14 @@
   profile_->AddObserver(this);
   message_type_ = message_type;
 
+  pref_change_registrar_ = std::make_unique<PrefChangeRegistrar>();
+  pref_change_registrar_->Init(profile_->GetPrefs());
+  pref_change_registrar_->Add(
+      prefs::kRestoreOnStartup,
+      base::BindRepeating(
+          &SessionRestoreInfoBarManager::OnSessionRestorePreferenceChanged,
+          base::Unretained(this)));
+
   InitTabStripTracker();
 }
 
@@ -52,6 +63,7 @@
   }
 
   browser_tab_strip_tracker_.reset();
+  pref_change_registrar_.reset();
 
   // Repeatedly remove the first infobar. OnInfoBarRemoved will be called,
   // which erases the infobar from the map. This continues until the map is
@@ -157,4 +169,12 @@
   CloseAllInfoBars();
 }
 
+void SessionRestoreInfoBarManager::OnSessionRestorePreferenceChanged() {
+  if (!profile_->GetPrefs()
+           ->FindPreference(prefs::kRestoreOnStartup)
+           ->IsDefaultValue()) {
+    CloseAllInfoBars();
+  }
+}
+
 }  // namespace session_restore_infobar
diff --git a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.h b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.h
index 596481e..8a285b2 100644
--- a/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.h
+++ b/chrome/browser/ui/views/session_restore_infobar/session_restore_infobar_manager.h
@@ -28,6 +28,8 @@
 class InfoBar;
 }
 
+class PrefChangeRegistrar;
+
 namespace session_restore_infobar {
 
 // This class is responsible for managing the session restore infobar. It
@@ -72,6 +74,9 @@
   // ProfileObserver:
   void OnProfileWillBeDestroyed(Profile* profile) override;
 
+  // Callback for session restore preference changes.
+  void OnSessionRestorePreferenceChanged();
+
   // Helper methods
   void InitTabStripTracker();
   void CreateInfoBarForWebContents(content::WebContents* web_contents);
@@ -87,6 +92,8 @@
   bool user_initiated_info_bar_close_pending_ = false;
   SessionRestoreInfoBarDelegate::InfobarMessageType message_type_ =
       SessionRestoreInfoBarDelegate::InfobarMessageType::kNone;
+
+  std::unique_ptr<PrefChangeRegistrar> pref_change_registrar_;
 };
 
 }  // namespace session_restore_infobar
diff --git a/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.cc b/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.cc
index 8c3b1b6..f787daf 100644
--- a/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.cc
+++ b/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.cc
@@ -17,6 +17,7 @@
 #include "chrome/browser/ui/browser_actions.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_features.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
+#include "chrome/browser/ui/views/side_panel/side_panel.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_entry.h"
 #include "chrome/browser/ui/views/side_panel/side_panel_entry_scope.h"
@@ -48,10 +49,7 @@
     : tab_(tab),
       side_panel_registry_(side_panel_registry),
       glic_action_(GetGlicActionItem(
-          tab->GetBrowserWindowInterface()->GetActions()->root_action_item())),
-      side_panel_coordinator_(tab->GetBrowserWindowInterface()
-                                  ->GetFeatures()
-                                  .side_panel_coordinator()) {
+          tab->GetBrowserWindowInterface()->GetActions()->root_action_item())) {
   CHECK(base::FeatureList::IsEnabled(features::kGlicMultiInstance));
   auto* glic_service = GlicKeyedServiceFactory::GetGlicKeyedService(
       tab->GetBrowserWindowInterface()->GetProfile());
@@ -62,6 +60,9 @@
   if (glic_service->enabling().IsAllowed()) {
     CreateAndRegisterEntry();
   }
+  tab_deactivated_subscription_ =
+      tab_->RegisterWillDeactivate(base::BindRepeating(
+          &GlicSidePanelCoordinator::OnTabDeactivated, base::Unretained(this)));
 }
 
 GlicSidePanelCoordinator::~GlicSidePanelCoordinator() = default;
@@ -81,19 +82,58 @@
   entry->set_should_show_header(false);
   entry->set_should_show_ephemerally_in_toolbar(false);
   entry->AddObserver(this);
+  entry_ = entry->GetWeakPtr();
   side_panel_registry_->Register(std::move(entry));
 }
 
+void GlicSidePanelCoordinator::Show() {
+  auto* window_side_panel_coordinator = GetWindowSidePanelCoordinator();
+  if (!window_side_panel_coordinator || !entry_) {
+    return;
+  }
+  if (!tab_->IsActivated()) {
+    if (entry_) {
+      // The tab is in the background, so we just mark it for showing the glic
+      // side panel when it becomes the active tab. eg. This flow can be
+      // encountered when a background tab is bound via daisy chaining.
+      side_panel_registry_->SetActiveEntry(entry_.get());
+    }
+    return;
+  }
+  window_side_panel_coordinator->Show(SidePanelEntry::Id::kGlic);
+}
+
+void GlicSidePanelCoordinator::Close() {
+  auto* window_side_panel_coordinator = GetWindowSidePanelCoordinator();
+  if (!window_side_panel_coordinator || !IsShowing()) {
+    return;
+  }
+  window_side_panel_coordinator->Close();
+}
+
+bool GlicSidePanelCoordinator::IsShowing() const {
+  return state_ == State::kShown;
+}
+
 void GlicSidePanelCoordinator::OnEntryWillHide(
     SidePanelEntry* entry,
     SidePanelEntryHideReason reason) {
   CHECK_EQ(entry->key().id(), SidePanelEntry::Id::kGlic);
-  visibility_changed_callbacks_.Notify(false);
+  state_ = State::kClosed;
+  NotifyStateChanged();
 }
 
 void GlicSidePanelCoordinator::OnEntryShown(SidePanelEntry* entry) {
   CHECK_EQ(entry->key().id(), SidePanelEntry::Id::kGlic);
-  visibility_changed_callbacks_.Notify(true);
+  state_ = State::kShown;
+  NotifyStateChanged();
+}
+
+void GlicSidePanelCoordinator::OnTabDeactivated(tabs::TabInterface* tab) {
+  if (IsShowing()) {
+    state_ = State::kHidden;
+    NotifyStateChanged();
+  }
 }
 
 void GlicSidePanelCoordinator::OnGlicEnabledChanged() {
@@ -111,12 +151,13 @@
   } else {
     SidePanelEntry::Key glic_key =
         SidePanelEntry::Key(SidePanelEntry::Id::kGlic);
-    if (side_panel_coordinator_->IsSidePanelEntryShowing(glic_key)) {
-      side_panel_coordinator_->Close();
+    auto* window_side_panel_coordinator = GetWindowSidePanelCoordinator();
+    if (window_side_panel_coordinator &&
+        window_side_panel_coordinator->IsSidePanelEntryShowing(glic_key)) {
+      window_side_panel_coordinator->Close();
     }
-    SidePanelEntry* glic_entry = side_panel_registry_->GetEntryForKey(glic_key);
-    if (glic_entry) {
-      glic_entry->RemoveObserver(this);
+    if (entry_) {
+      entry_->RemoveObserver(this);
     }
     side_panel_registry_->Deregister(glic_key);
   }
@@ -142,9 +183,9 @@
   return glic_container;
 }
 
-base::CallbackListSubscription GlicSidePanelCoordinator::AddVisibilityCallback(
-    base::RepeatingCallback<void(bool isShowing)> callback) {
-  return visibility_changed_callbacks_.Add(std::move(callback));
+base::CallbackListSubscription GlicSidePanelCoordinator::AddStateCallback(
+    base::RepeatingCallback<void(State state)> callback) {
+  return state_changed_callbacks_.Add(std::move(callback));
 }
 
 void GlicSidePanelCoordinator::SetContentsView(
@@ -166,4 +207,16 @@
   return features::kGlicSidePanelMinWidth.Get();
 }
 
+SidePanelCoordinator* GlicSidePanelCoordinator::GetWindowSidePanelCoordinator()
+    const {
+  if (auto* window = tab_->GetBrowserWindowInterface()) {
+    return window->GetFeatures().side_panel_coordinator();
+  }
+  return nullptr;
+}
+
+void GlicSidePanelCoordinator::NotifyStateChanged() {
+  state_changed_callbacks_.Notify(state_);
+}
+
 }  // namespace glic
diff --git a/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.h b/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.h
index a415ca9..148f8f33 100644
--- a/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.h
+++ b/chrome/browser/ui/views/side_panel/glic/glic_side_panel_coordinator.h
@@ -41,13 +41,31 @@
   // Create and register the Glic side panel entry.
   void CreateAndRegisterEntry();
 
-  using VisibilityCallback = base::RepeatingCallback<void(bool isVisible)>;
+  // The current state of the Glic side panel.
+  enum class State {
+    // The side panel is showing in the foreground.
+    kShown,
+    // The side panel is in the background, but it will show if its tab becomes
+    // active.
+    kHidden,
+    // The side panel is closed and will only be shown if explicitly requested.
+    kClosed,
+  };
+
+  // Show the Glic side panel.
+  void Show();
+
+  // Close the Glic side panel.
+  void Close();
+
+  // Returns true if the Glic side panel is currently the active entry.
+  bool IsShowing() const;
 
   // Registers `callback` to be called when panel visibility is updated.
-  base::CallbackListSubscription AddVisibilityCallback(
-      VisibilityCallback callback);
+  base::CallbackListSubscription AddStateCallback(
+      base::RepeatingCallback<void(State state)> callback);
 
-  // Set the content to display in the Glic side panel.
+  // Sets the content view for the Glic side panel.
   void SetContentsView(std::unique_ptr<views::View> contents_view);
 
   // Returns preferred side panel width. Not guaranteed to be used if user
@@ -59,24 +77,38 @@
  protected:
   // Called when the Glic enabled status changes for `profile_`.
   void OnGlicEnabledChanged();
-  // `SidePanelEntryObserver`:
+
+  // SidePanelEntryObserver:
   void OnEntryWillHide(SidePanelEntry* entry,
                        SidePanelEntryHideReason reason) override;
   void OnEntryShown(SidePanelEntry* entry) override;
 
  private:
+  void OnTabDeactivated(tabs::TabInterface* tab);
+
+  // Returns the SidePanelCoordinator for the window associated with `tab_`.
+  SidePanelCoordinator* GetWindowSidePanelCoordinator() const;
+
   // Gets the Glic WebView from the Glic service.
   std::unique_ptr<views::View> CreateView(SidePanelEntryScope& scope);
 
+  void NotifyStateChanged();
+
   raw_ptr<tabs::TabInterface> tab_ = nullptr;
   raw_ptr<SidePanelRegistry> side_panel_registry_ = nullptr;
   raw_ptr<actions::ActionItem> glic_action_ = nullptr;
-  raw_ptr<SidePanelCoordinator> side_panel_coordinator_ = nullptr;
+  base::WeakPtr<SidePanelEntry> entry_;
   base::CallbackListSubscription on_glic_enabled_changed_subscription_;
-  base::RepeatingCallbackList<void(bool isShowing)>
-      visibility_changed_callbacks_;
-  std::unique_ptr<views::View> contents_view_;
+  base::RepeatingCallbackList<void(State state)> state_changed_callbacks_;
+  base::CallbackListSubscription tab_deactivated_subscription_;
+
+  State state_ = State::kHidden;
+
+  // Tracks the glic container view.
   views::ViewTracker glic_container_tracker_;
+
+  // Caches the contents view if it's set before the container is created.
+  std::unique_ptr<views::View> contents_view_;
 };
 
 }  // namespace glic
diff --git a/chrome/browser/ui/views/tabs/dragging/tab_drag_controller_interactive_uitest.cc b/chrome/browser/ui/views/tabs/dragging/tab_drag_controller_interactive_uitest.cc
index d56f7b5..03735186 100644
--- a/chrome/browser/ui/views/tabs/dragging/tab_drag_controller_interactive_uitest.cc
+++ b/chrome/browser/ui/views/tabs/dragging/tab_drag_controller_interactive_uitest.cc
@@ -3958,7 +3958,7 @@
                        HomeTabAddedToEveryWindow) {
   // Install tabbed web app.
   webapps::AppId app_id = InstallMockApp(/*add_home_tab=*/true);
-  Browser* app_browser =
+  BrowserWindowInterface* const app_browser =
       web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
   ASSERT_EQ(2u, browser_list()->size());
 
@@ -3966,7 +3966,7 @@
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
 
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
 
   AddTabsAndResetBrowser(browser(), 1, GURL("https://www.example.com/newpage"));
@@ -4015,7 +4015,7 @@
                        MAYBE_CantDragHomeTab) {
   // Install tabbed web app.
   webapps::AppId app_id = InstallMockApp(/*add_home_tab=*/true);
-  Browser* app_browser =
+  BrowserWindowInterface* const app_browser =
       web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
   ASSERT_EQ(2u, browser_list()->size());
 
@@ -4023,7 +4023,7 @@
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
 
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
 
   AddTabsAndResetBrowser(browser(), 1, GURL("https://www.example.com/newpage"));
@@ -4050,7 +4050,7 @@
                        NoHomeTab) {
   // Install tabbed web app.
   webapps::AppId app_id = InstallMockApp(/*add_home_tab=*/false);
-  Browser* app_browser =
+  BrowserWindowInterface* const app_browser =
       web_app::LaunchWebAppBrowser(browser()->profile(), app_id);
   ASSERT_EQ(2u, browser_list()->size());
 
@@ -4058,7 +4058,7 @@
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
 
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
 
   AddTabsAndResetBrowser(browser(), 1, GURL("https://www.example.com/newpage"));
@@ -4865,7 +4865,7 @@
   // Close normal browser since other code expects only 1 browser to start.
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
   EXPECT_EQ(BrowserWindowInterface::Type::TYPE_APP, browser()->GetType());
   AddTabsAndResetBrowser(browser(), 1, GetAppUrl());
@@ -4907,7 +4907,7 @@
   // Close normal browser since other code expects only 1 browser to start.
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(2u, browser_list()->size());
-  SelectFirstBrowser();
+  SetBrowser(app_browser1);
   ASSERT_EQ(app_browser1, browser());
 
   AddTabsAndResetBrowser(browser(), 1, GetAppUrl());
@@ -5880,7 +5880,7 @@
   // Close normal browser.
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
   EXPECT_EQ(Browser::Type::TYPE_APP, browser()->GetType());
 
@@ -5914,7 +5914,7 @@
   // Close normal browser.
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
   EXPECT_EQ(Browser::Type::TYPE_APP, browser()->GetType());
 
@@ -5943,7 +5943,7 @@
   // Close normal browser.
   CloseBrowserSynchronously(browser());
   ASSERT_EQ(1u, browser_list()->size());
-  SelectFirstBrowser();
+  SetBrowser(app_browser);
   ASSERT_EQ(app_browser, browser());
   EXPECT_EQ(Browser::Type::TYPE_APP, browser()->GetType());
 
diff --git a/chrome/browser/ui/views/tabs/glic_button.cc b/chrome/browser/ui/views/tabs/glic_button.cc
index c48353e..2683bc7 100644
--- a/chrome/browser/ui/views/tabs/glic_button.cc
+++ b/chrome/browser/ui/views/tabs/glic_button.cc
@@ -22,6 +22,7 @@
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/browser/ui/user_education/browser_user_education_interface.h"
+#include "chrome/browser/ui/views/interaction/browser_elements_views.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_control_button.h"
 #include "chrome/browser/ui/views/tabs/tab_strip_controller.h"
 #include "chrome/common/buildflags.h"
@@ -205,6 +206,15 @@
 
 GlicButton::~GlicButton() = default;
 
+// Static
+GlicButton* GlicButton::FromBrowser(BrowserWindowInterface* browser) {
+  if (!browser) {
+    return nullptr;
+  }
+  return BrowserElementsViews::From(browser)->GetViewAs<glic::GlicButton>(
+      kGlicButtonElementId);
+}
+
 void GlicButton::SetNudgeLabel(std::string label) {
   if (!EntrypointVariationsEnabled()) {
     initial_width_ = GetLayoutManager()->GetPreferredSize(this).width();
diff --git a/chrome/browser/ui/views/tabs/glic_button.h b/chrome/browser/ui/views/tabs/glic_button.h
index 99ee85a..f81c39f 100644
--- a/chrome/browser/ui/views/tabs/glic_button.h
+++ b/chrome/browser/ui/views/tabs/glic_button.h
@@ -18,6 +18,7 @@
 #include "chrome/browser/glic/fre/glic_fre.mojom.h"
 #endif  // BUILDFLAG(ENABLE_GLIC)
 
+class BrowserWindowInterface;
 class PrefService;
 
 namespace glic {
@@ -42,6 +43,8 @@
   GlicButton& operator=(const GlicButton&) = delete;
   ~GlicButton() override;
 
+  static GlicButton* FromBrowser(BrowserWindowInterface* browser);
+
   void SetNudgeLabel(std::string label);
   void RestoreDefaultLabel();
 
diff --git a/chrome/browser/ui/views/zoom/BUILD.gn b/chrome/browser/ui/views/zoom/BUILD.gn
index 6d5cf3d..572c2716 100644
--- a/chrome/browser/ui/views/zoom/BUILD.gn
+++ b/chrome/browser/ui/views/zoom/BUILD.gn
@@ -17,7 +17,6 @@
     ":zoom",
     "//chrome/browser/ui",
     "//chrome/browser/ui:ui_features",
-    "//chrome/browser/ui/browser_window",
     "//chrome/browser/ui/views/frame:toolbar_button_provider",
     "//chrome/browser/ui/views/location_bar",
     "//chrome/browser/ui/views/page_action",
@@ -35,7 +34,6 @@
   deps = [
     "//chrome/browser/ui",
     "//chrome/browser/ui:ui_features",
-    "//chrome/browser/ui/browser_window",
     "//chrome/browser/ui/views/frame:toolbar_button_provider",
     "//chrome/browser/ui/views/location_bar",
     "//chrome/browser/ui/views/page_action",
diff --git a/chrome/browser/ui/views/zoom/zoom_view_controller.cc b/chrome/browser/ui/views/zoom/zoom_view_controller.cc
index 1a94dc8..556b356 100644
--- a/chrome/browser/ui/views/zoom/zoom_view_controller.cc
+++ b/chrome/browser/ui/views/zoom/zoom_view_controller.cc
@@ -10,13 +10,10 @@
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser_actions.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_controller.h"
 #include "chrome/browser/ui/views/page_action/page_action_view.h"
@@ -101,15 +98,15 @@
       CanBubbleBeVisible(prefer_to_show_bubble, is_at_default_zoom);
   if (can_bubble_be_visible) {
     if (prefer_to_show_bubble) {
-      GetBubbleCoordinator()->Show(
+      ZoomBubbleView::ShowBubble(
           GetWebContents(), from_user_gesture ? ZoomBubbleView::USER_GESTURE
                                               : ZoomBubbleView::AUTOMATIC);
     } else {
-      GetBubbleCoordinator()->RefreshIfShowing(GetWebContents());
+      ZoomBubbleView::RefreshBubbleIfShowing(GetWebContents());
     }
   } else {
     if (IsBubbleVisible()) {
-      GetBubbleCoordinator()->Hide();
+      ZoomBubbleView::CloseCurrentBubble();
     }
   }
 }
@@ -139,9 +136,4 @@
   return tab_interface_->GetContents();
 }
 
-ZoomBubbleCoordinator* ZoomViewController::GetBubbleCoordinator() {
-  return ZoomBubbleCoordinator::From(
-      tab_interface_->GetBrowserWindowInterface());
-}
-
 }  // namespace zoom
diff --git a/chrome/browser/ui/views/zoom/zoom_view_controller.h b/chrome/browser/ui/views/zoom/zoom_view_controller.h
index 735016a..c418b23 100644
--- a/chrome/browser/ui/views/zoom/zoom_view_controller.h
+++ b/chrome/browser/ui/views/zoom/zoom_view_controller.h
@@ -7,8 +7,6 @@
 
 #include "components/tabs/public/tab_interface.h"
 
-class ZoomBubbleCoordinator;
-
 namespace content {
 class WebContents;
 }
@@ -60,10 +58,6 @@
   // Helper to retrieve the active WebContents from the tab.
   content::WebContents* GetWebContents() const;
 
-  // Returns the zoom bubble coordinator associated with the window owning this
-  // zoom page action.
-  ZoomBubbleCoordinator* GetBubbleCoordinator();
-
   // Because zoom settings are per-tab, we store the tab interface by reference.
   // The TabInterface is guaranteed valid for this object’s lifetime.
   const raw_ref<tabs::TabInterface> tab_interface_;
diff --git a/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc b/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
index 5f553d8..3b31f69f 100644
--- a/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
+++ b/chrome/browser/ui/views/zoom/zoom_view_interactive_ui_tests.cc
@@ -8,11 +8,9 @@
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_features.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
-#include "chrome/browser/ui/views/location_bar/zoom_bubble_coordinator.h"
 #include "chrome/browser/ui/views/location_bar/zoom_bubble_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_view.h"
@@ -82,16 +80,14 @@
     DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<bool>,
                                         kZoomBubbleVisible);
 
-    return Steps(
-        PollState(kZoomBubbleVisible,
-                  [&, visible]() {
-                    const bool is_visible =
-                        ZoomBubbleCoordinator::From(browser())->bubble() !=
-                        nullptr;
-                    return is_visible == visible;
-                  }),
-        WaitForState(kZoomBubbleVisible, true),
-        StopObservingState(kZoomBubbleVisible));
+    return Steps(PollState(kZoomBubbleVisible,
+                           [&, visible]() {
+                             bool is_visible =
+                                 ZoomBubbleView::GetZoomBubble() != nullptr;
+                             return is_visible == visible;
+                           }),
+                 WaitForState(kZoomBubbleVisible, true),
+                 StopObservingState(kZoomBubbleVisible));
   }
 
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/ui/webui/BUILD.gn b/chrome/browser/ui/webui/BUILD.gn
index d7ae711..bf36d6af 100644
--- a/chrome/browser/ui/webui/BUILD.gn
+++ b/chrome/browser/ui/webui/BUILD.gn
@@ -65,6 +65,7 @@
       "//chrome/browser/ui/webui/infobar_internals",
       "//chrome/browser/ui/webui/new_tab_footer",
       "//chrome/browser/ui/webui/privacy_sandbox",
+      "//chrome/browser/ui/webui/reload_button",
       "//chrome/browser/ui/webui_browser",
     ]
 
diff --git a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
index 8472a678..e294e9c 100644
--- a/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
+++ b/chrome/browser/ui/webui/app_management/app_management_page_handler_unittest.cc
@@ -611,6 +611,56 @@
   EXPECT_TRUE(overlapping_apps.empty());
 }
 
+TEST_P(AppManagementPageHandlerTestBase, GetSupportedLinksWithScopeExtensions) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(
+      ::features::kPwaNavigationCapturingWithScopeExtensions);
+  auto web_app_info = web_app::WebAppInstallInfo::CreateWithStartUrlForTesting(
+      GURL("https://example.com/"));
+  web_app_info->title = u"app_name";
+  web_app_info->scope_extensions = {
+      web_app::ScopeExtensionInfo::CreateForScope(GURL("https://sitea.com")),
+      web_app::ScopeExtensionInfo::CreateForScope(
+          GURL("https://app.siteb.com")),
+      web_app::ScopeExtensionInfo::CreateForScope(GURL("https://sitec.com"),
+                                                  /*has_origin_wildcard=*/true),
+      web_app::ScopeExtensionInfo::CreateForScope(
+          GURL("https://sited.com/path")),
+      web_app::ScopeExtensionInfo::CreateForScope(
+          GURL("http://☃.net/")) /* Unicode */
+  };
+  web_app_info->validated_scope_extensions = web_app_info->scope_extensions;
+  web_app_info->scope_extensions.insert(
+      web_app::ScopeExtensionInfo::CreateForScope(
+          GURL("https://unvalidatedscope.com")));
+
+  web_app::WebAppInstallParams install_params;
+  // Skip origin association validation for testing.
+  install_params.skip_origin_association_validation = true;
+
+  base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
+      future;
+  web_app::WebAppProvider* provider =
+      web_app::WebAppProvider::GetForTest(profile());
+  provider->scheduler().InstallFromInfoWithParams(
+      std::move(web_app_info), /*overwrite_existing_manifest_fields=*/false,
+      webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, future.GetCallback(),
+      install_params);
+
+  EXPECT_EQ(webapps::InstallResultCode::kSuccessNewInstall,
+            future.Get<webapps::InstallResultCode>());
+  const webapps::AppId& app_id = future.Get<webapps::AppId>();
+
+  base::test::TestFuture<app_management::mojom::AppPtr> result;
+  handler()->GetApp(app_id, result.GetCallback());
+
+  EXPECT_THAT(result.Get()->supported_links,
+              testing::UnorderedElementsAre("sitea.com/*", "app.siteb.com/*",
+                                            "*.sitec.com/*", "sitec.com/*",
+                                            "sited.com/path*", "example.com/*",
+                                            "xn--n3h.net/*"));
+}
+
 #if !BUILDFLAG(IS_CHROMEOS)
 TEST_P(AppManagementPageHandlerTestBase, GetScopeExtensions) {
   auto web_app_info = web_app::WebAppInstallInfo::CreateWithStartUrlForTesting(
diff --git a/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc
index 62e7c4d..0c70e63 100644
--- a/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc
+++ b/chrome/browser/ui/webui/app_management/web_app_settings_page_handler.cc
@@ -14,6 +14,7 @@
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom-shared.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_scope.h"
 #include "chrome/browser/web_applications/web_app_ui_manager.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
 #include "chrome/common/chrome_features.h"
@@ -33,24 +34,45 @@
 
 namespace {
 
+std::string FormatScope(const GURL& scope_url) {
+  std::string scope_str(scope_url.host());
+  if (scope_url.has_port()) {
+    scope_str += ":";
+    scope_str += scope_url.port();
+  }
+  scope_str += scope_url.path().empty() ? "/" : scope_url.path();
+  scope_str += "*";
+  return scope_str;
+}
+
 std::vector<std::string> GetSupportedLinks(const std::string& app_id,
                                            web_app::WebAppProvider& provider) {
-  GURL app_scope = provider.registrar_unsafe().GetAppScope(app_id);
-  if (!web_app::IsValidScopeForLinkCapturing(app_scope)) {
-    return std::vector<std::string>();
+  std::optional<web_app::WebAppScope> effective_scope =
+      provider.registrar_unsafe().GetEffectiveScope(app_id);
+  if (!effective_scope) {
+    return {};
   }
 
-  std::string scope_str(app_scope.GetHost());
-  if (app_scope.has_port()) {
-    scope_str += ":" + app_scope.GetPort();
+  std::vector<std::string> supported_links;
+  if (base::FeatureList::IsEnabled(
+          features::kPwaNavigationCapturingWithScopeExtensions)) {
+    for (const auto& scope_extension :
+         effective_scope->validated_scope_extensions()) {
+      std::string formatted_scope = FormatScope(scope_extension.scope);
+      supported_links.push_back(formatted_scope);
+      if (scope_extension.has_origin_wildcard) {
+        supported_links.push_back("*." + formatted_scope);
+      }
+    }
   }
-  scope_str += app_scope.GetPath();
-  if (scope_str.back() == '/') {
-    scope_str = scope_str + "*";
-  } else {
-    scope_str = scope_str + "/*";
+
+  GURL app_scope = effective_scope->scope();
+  if (!web_app::IsValidScopeForLinkCapturing(app_scope)) {
+    return supported_links;
   }
-  return {scope_str};
+
+  supported_links.push_back(FormatScope(app_scope));
+  return supported_links;
 }
 
 std::string GetFormattedOrigin(const webapps::AppId& app_id,
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/BUILD.gn b/chrome/browser/ui/webui/ash/settings/pages/device/BUILD.gn
index fa907e2..9d4bfa70 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/device/BUILD.gn
+++ b/chrome/browser/ui/webui/ash/settings/pages/device/BUILD.gn
@@ -82,7 +82,6 @@
   sources = [
     "device_keyboard_handler_unittest.cc",
     "device_section_unittest.cc",
-    "inputs_section_unittest.cc",
   ]
 
   deps = [
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
index ffdb12b..97f891f 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
@@ -634,7 +634,7 @@
 }
 
 bool InputsSection::ShouldShowEmojiSuggestionsSettings() const {
-  return pref_service_->GetBoolean(prefs::kEmojiSuggestionEnterpriseAllowed);
+  return false;
 }
 
 bool InputsSection::IsSpellCheckEnabled() const {
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section_unittest.cc b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section_unittest.cc
deleted file mode 100644
index 5c731a4d..0000000
--- a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section_unittest.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.h"
-
-#include "ash/constants/ash_features.h"
-#include "ash/constants/ash_pref_names.h"
-#include "base/command_line.h"
-#include "base/memory/raw_ptr.h"
-#include "base/test/scoped_feature_list.h"
-#include "chrome/browser/ash/input_method/editor_geolocation_mock_provider.h"
-#include "chrome/browser/ash/input_method/editor_geolocation_provider.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/webui/ash/settings/search/search_tag_registry.h"
-#include "chrome/grit/generated_resources.h"
-#include "chrome/test/base/chrome_ash_test_base.h"
-#include "chrome/test/base/testing_browser_process.h"
-#include "chrome/test/base/testing_profile.h"
-#include "chrome/test/base/testing_profile_manager.h"
-#include "chromeos/components/magic_boost/test/fake_magic_boost_state.h"
-#include "chromeos/constants/chromeos_features.h"
-#include "chromeos/constants/chromeos_switches.h"
-#include "components/prefs/testing_pref_service.h"
-#include "components/spellcheck/browser/pref_names.h"
-#include "components/sync_preferences/testing_pref_service_syncable.h"
-#include "content/public/test/browser_task_environment.h"
-#include "content/public/test/test_web_ui_data_source.h"
-
-namespace ash::settings {
-
-namespace {
-
-std::string GetSettingsSearchResultId(OsSettingsIdentifier id, int message_id) {
-  std::stringstream ss;
-  ss << id.setting << "," << message_id;
-  return ss.str();
-}
-
-}  // namespace
-
-// Test for the inputs settings page.
-class InputsSectionTest : public ChromeAshTestBase {
- public:
-  InputsSectionTest()
-      : local_search_service_proxy_(
-            std::make_unique<
-                ash::local_search_service::LocalSearchServiceProxy>(
-                /*for_testing=*/true)),
-        search_tag_registry_(local_search_service_proxy_.get()) {}
-
-  ~InputsSectionTest() override = default;
-
-  TestingProfile* profile() { return &profile_; }
-  TestingPrefServiceSimple* pref_service() { return &pref_service_; }
-  ash::settings::SearchTagRegistry* search_tag_registry() {
-    return &search_tag_registry_;
-  }
-
-  std::unique_ptr<InputsSection> inputs_section_;
-
- protected:
-  void SetUp() override {
-    pref_service()->registry()->RegisterBooleanPref(
-        prefs::kEmojiSuggestionEnterpriseAllowed, true);
-    pref_service()->registry()->RegisterBooleanPref(
-        spellcheck::prefs::kSpellCheckEnable, true);
-
-    ChromeAshTestBase::SetUp();
-  }
-  void TearDown() override {
-    inputs_section_.reset();
-    ChromeAshTestBase::TearDown();
-  }
-
- private:
-  std::unique_ptr<ash::local_search_service::LocalSearchServiceProxy>
-      local_search_service_proxy_;
-  ash::settings::SearchTagRegistry search_tag_registry_;
-  TestingPrefServiceSimple pref_service_;
-  TestingProfile profile_;
-};
-
-TEST_F(InputsSectionTest, SearchResultShouldIncludeEmojiSuggestion) {
-  auto mock_geolocation_provider =
-      std::make_unique<input_method::EditorGeolocationMockProvider>("us");
-  input_method::EditorMediator editor_mediator(
-      profile(), std::move(mock_geolocation_provider));
-  inputs_section_ = std::make_unique<InputsSection>(
-      profile(), search_tag_registry(), pref_service(), &editor_mediator);
-  OsSettingsIdentifier kEmojiSuggestionSettingId = {
-      .setting = chromeos::settings::mojom::Setting::kShowEmojiSuggestions};
-
-  std::string result_id = GetSettingsSearchResultId(
-      kEmojiSuggestionSettingId,
-      IDS_OS_SETTINGS_TAG_LANGUAGES_EMOJI_SUGGESTIONS);
-
-  EXPECT_TRUE(search_tag_registry()->GetTagMetadata(result_id));
-}
-
-}  // namespace ash::settings
diff --git a/chrome/browser/ui/webui/chrome_web_ui_configs.cc b/chrome/browser/ui/webui/chrome_web_ui_configs.cc
index 746ec07..4bdba3f6 100644
--- a/chrome/browser/ui/webui/chrome_web_ui_configs.cc
+++ b/chrome/browser/ui/webui/chrome_web_ui_configs.cc
@@ -42,6 +42,7 @@
 #include "chrome/browser/ui/webui/policy/policy_ui.h"
 #include "chrome/browser/ui/webui/predictors/predictors_ui.h"
 #include "chrome/browser/ui/webui/privacy_sandbox/privacy_sandbox_internals_ui.h"
+#include "chrome/browser/ui/webui/reload_button/reload_button_ui.h"
 #include "chrome/browser/ui/webui/saved_tab_groups_unsupported/saved_tab_groups_unsupported_ui.h"
 #include "chrome/browser/ui/webui/segmentation_internals/segmentation_internals_ui.h"
 #include "chrome/browser/ui/webui/signin_internals_ui.h"
@@ -334,6 +335,7 @@
       std::make_unique<commerce::ProductSpecificationsUIConfig>());
   map.AddWebUIConfig(std::make_unique<ProfileInternalsUIConfig>());
   map.AddWebUIConfig(std::make_unique<ReadingListUIConfig>());
+  map.AddWebUIConfig(std::make_unique<ReloadButtonUIConfig>());
   map.AddWebUIConfig(std::make_unique<SearchEngineChoiceUIConfig>());
   map.AddWebUIConfig(std::make_unique<settings::SettingsUIConfig>());
   map.AddWebUIConfig(std::make_unique<ShoppingInsightsSidePanelUIConfig>());
diff --git a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
index 138a16b8..c5efd6f 100644
--- a/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
+++ b/chrome/browser/ui/webui/omnibox_popup/omnibox_popup_ui.cc
@@ -23,6 +23,7 @@
 #include "chrome/grit/omnibox_popup_resources.h"
 #include "chrome/grit/omnibox_popup_resources_map.h"
 #include "components/favicon_base/favicon_url_parser.h"
+#include "components/omnibox/common/omnibox_features.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "ui/webui/color_change_listener/color_change_handler.h"
 #include "ui/webui/webui_util.h"
@@ -44,8 +45,11 @@
 
   source->AddBoolean("isTopChromeSearchbox", true);
 
-  webui::SetupWebUIDataSource(source, kOmniboxPopupResources,
-                              IDR_OMNIBOX_POPUP_OMNIBOX_POPUP_HTML);
+  webui::SetupWebUIDataSource(
+      source, kOmniboxPopupResources,
+      base::FeatureList::IsEnabled(omnibox::kWebUIOmniboxFullPopup)
+          ? IDR_OMNIBOX_POPUP_OMNIBOX_POPUP_FULL_HTML
+          : IDR_OMNIBOX_POPUP_OMNIBOX_POPUP_HTML);
   webui::EnableTrustedTypesCSP(source);
 
   content::URLDataSource::Add(profile_,
diff --git a/chrome/browser/ui/webui/profile_helper_browsertest.cc b/chrome/browser/ui/webui/profile_helper_browsertest.cc
index b268907..3a46ddf 100644
--- a/chrome/browser/ui/webui/profile_helper_browsertest.cc
+++ b/chrome/browser/ui/webui/profile_helper_browsertest.cc
@@ -200,10 +200,11 @@
   webui::DeleteProfileAtPath(original_browser->profile()->GetPath(),
                              ProfileMetrics::DELETE_PROFILE_SETTINGS);
   ui_test_utils::WaitForBrowserToClose(original_browser);
-  content::RunAllTasksUntilIdle();
 
   EXPECT_EQ(1u, browser_list->size());
-  EXPECT_EQ(additional_profile, browser_list->get(0)->profile());
+  BrowserWindowInterface* const additional_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
+  EXPECT_EQ(additional_profile, additional_browser->GetProfile());
   EXPECT_EQ(1u, storage.GetNumberOfProfiles());
 }
 
diff --git a/chrome/browser/ui/webui/reload_button/BUILD.gn b/chrome/browser/ui/webui/reload_button/BUILD.gn
new file mode 100644
index 0000000..4a869c6
--- /dev/null
+++ b/chrome/browser/ui/webui/reload_button/BUILD.gn
@@ -0,0 +1,24 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(!is_android)
+
+source_set("reload_button") {
+  sources = [ "reload_button_ui.h" ]
+  public_deps = [
+    "//chrome/browser/ui/webui/top_chrome",
+    "//chrome/common",
+    "//content/public/browser",
+  ]
+}
+
+source_set("impl") {
+  sources = [ "reload_button_ui.cc" ]
+  deps = [
+    ":reload_button",
+    "//chrome/common",
+    "//ui/webui",
+  ]
+  public_deps = [ "//chrome/browser:browser_public_dependencies" ]
+}
diff --git a/chrome/browser/ui/webui/reload_button/OWNERS b/chrome/browser/ui/webui/reload_button/OWNERS
new file mode 100644
index 0000000..1a22119a
--- /dev/null
+++ b/chrome/browser/ui/webui/reload_button/OWNERS
@@ -0,0 +1,7 @@
+fergal@chromium.org
+leimy@chromium.org
+mych@chromium.org
+rakina@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/browser/ui/webui/reload_button/reload_button_ui.cc b/chrome/browser/ui/webui/reload_button/reload_button_ui.cc
new file mode 100644
index 0000000..98446d3
--- /dev/null
+++ b/chrome/browser/ui/webui/reload_button/reload_button_ui.cc
@@ -0,0 +1,25 @@
+// Copyright 2025 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/ui/webui/reload_button/reload_button_ui.h"
+
+#include "base/feature_list.h"
+#include "chrome/common/chrome_features.h"
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_ui.h"
+#include "content/public/browser/web_ui_data_source.h"
+#include "ui/webui/webui_util.h"
+
+// TODO(crbug.com/444358999): implement the reload button
+ReloadButtonUI::ReloadButtonUI(content::WebUI* web_ui)
+    : TopChromeWebUIController(web_ui) {}
+
+ReloadButtonUI::~ReloadButtonUI() = default;
+
+bool ReloadButtonUIConfig::IsWebUIEnabled(
+    content::BrowserContext* browser_context) {
+  return base::FeatureList::IsEnabled(features::kInitialWebUI) &&
+         base::FeatureList::IsEnabled(features::kWebUIReloadButton);
+}
diff --git a/chrome/browser/ui/webui/reload_button/reload_button_ui.h b/chrome/browser/ui/webui/reload_button/reload_button_ui.h
new file mode 100644
index 0000000..2c28bca
--- /dev/null
+++ b/chrome/browser/ui/webui/reload_button/reload_button_ui.h
@@ -0,0 +1,34 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_WEBUI_RELOAD_BUTTON_RELOAD_BUTTON_UI_H_
+#define CHROME_BROWSER_UI_WEBUI_RELOAD_BUTTON_RELOAD_BUTTON_UI_H_
+
+#include "chrome/browser/ui/webui/top_chrome/top_chrome_web_ui_controller.h"
+#include "chrome/browser/ui/webui/top_chrome/top_chrome_webui_config.h"
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/webui_config.h"
+#include "content/public/common/url_constants.h"
+
+class ReloadButtonUI;
+
+class ReloadButtonUI : public TopChromeWebUIController {
+ public:
+  explicit ReloadButtonUI(content::WebUI* web_ui);
+  ~ReloadButtonUI() override;
+  static constexpr std::string_view GetWebUIName() { return "ReloadButtonUI"; }
+};
+
+class ReloadButtonUIConfig
+    : public DefaultTopChromeWebUIConfig<ReloadButtonUI> {
+ public:
+  ReloadButtonUIConfig()
+      : DefaultTopChromeWebUIConfig(content::kChromeUIScheme,
+                                    chrome::kChromeUIReloadButtonHost) {}
+  // DefaultTopChromeWebUIConfig overrides:
+  bool IsWebUIEnabled(content::BrowserContext* browser_context) override;
+};
+
+#endif  // CHROME_BROWSER_UI_WEBUI_RELOAD_BUTTON_RELOAD_BUTTON_UI_H_
diff --git a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui_browsertest.cc b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui_browsertest.cc
index 94eee3f..03c7238 100644
--- a/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui_browsertest.cc
+++ b/chrome/browser/ui/webui/search_engine_choice/search_engine_choice_ui_browsertest.cc
@@ -263,7 +263,7 @@
       ASSERT_TRUE(new_browser->profile()->IsGuestSession());
 
       CloseBrowserSynchronously(browser());
-      SelectFirstBrowser();
+      SetBrowser(new_browser);
       ASSERT_EQ(new_browser, browser());
     }
   }
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 36955759..e4580632 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
@@ -1428,10 +1428,13 @@
   // A visible URL is used when the a new tab is still loading.
   // If it is cancelled during loading the visible URL becomes empty.
   // We will display an empty URL as about:blank in Javascript.
-  tab_data->url =
-      !last_committed_url.is_valid() || last_committed_url.is_empty()
-          ? tab_renderer_data.visible_url
-          : last_committed_url;
+  if (!last_committed_url.is_valid() || last_committed_url.is_empty()) {
+    tab_data->url = tab_renderer_data.should_display_url
+                        ? tab_renderer_data.visible_url
+                        : GURL(url::kAboutBlankURL);
+  } else {
+    tab_data->url = last_committed_url;
+  }
 
   if (tab_renderer_data.favicon.IsEmpty()) {
     tab_data->is_default_favicon = true;
diff --git a/chrome/browser/ui/webui_browser/webui_browser_browsertest.cc b/chrome/browser/ui/webui_browser/webui_browser_browsertest.cc
index 06c0d6a..497ee41 100644
--- a/chrome/browser/ui/webui_browser/webui_browser_browsertest.cc
+++ b/chrome/browser/ui/webui_browser/webui_browser_browsertest.cc
@@ -36,6 +36,27 @@
     InProcessBrowserTest::SetUpOnMainThread();
   }
 
+  // Helper function to set up embedded web contents for tests.
+  // Returns the embedded web contents after it has been converted to a guest.
+  content::WebContents* SetUpEmbeddedWebContents() {
+    EXPECT_TRUE(browser()->window());
+
+    content::WebContents* web_contents =
+        browser()->tab_strip_model()->GetActiveWebContents();
+    EXPECT_TRUE(web_contents);
+    EXPECT_TRUE(content::WaitForLoadStop(web_contents));
+
+    // Make sure that the web contents actually got converted to a guest before
+    // we navigate it again, so that WebContentsViewChildFrame gets involved.
+    EXPECT_TRUE(base::test::RunUntil(
+        [web_contents]() { return !!web_contents->GetOuterWebContents(); }));
+
+    GURL url = embedded_https_test_server().GetURL("a.com", "/defaultresponse");
+    EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
+
+    return web_contents;
+  }
+
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
 };
@@ -88,53 +109,79 @@
 #if !BUILDFLAG(IS_CHROMEOS)
 // Begin security related tests. These tests validate the security
 // boundary between a GuestContents and the parent.
+
+// Test that parent history is not affected by embedded navigation.
+// The history.length should be independent between inner and outer webcontents.
 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, HistoryLengthIndependent) {
-  auto* window = browser()->window();
-  ASSERT_TRUE(window);
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+  EXPECT_EQ(2, EvalJs(inner_webcontents, "window.history.length"));
 
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(web_contents);
-  EXPECT_TRUE(content::WaitForLoadStop(web_contents));
-
-  // Make sure that the web contents actually got converted to a guest before
-  // we navigate it again, so that WebContentsViewChildFrame gets involved.
-  EXPECT_TRUE(base::test::RunUntil([web_contents]() {
-    return web_contents->GetOuterWebContents() != nullptr;
-  }));
-
-  GURL url = embedded_https_test_server().GetURL("a.com", "/defaultresponse");
-  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-  EXPECT_EQ(2, EvalJs(web_contents, "window.history.length"));
-
-  content::WebContents* outer_webcontents = web_contents->GetOuterWebContents();
-  EXPECT_TRUE(outer_webcontents->GetOuterWebContents() == nullptr);
-  EXPECT_NE(outer_webcontents, nullptr);
+  content::WebContents* outer_webcontents =
+      inner_webcontents->GetOuterWebContents();
+  EXPECT_FALSE(outer_webcontents->GetOuterWebContents());
+  EXPECT_TRUE(outer_webcontents);
   EXPECT_EQ(1, EvalJs(outer_webcontents, "window.history.length"));
 }
 
+// Test that the frame tree isolation between inner and outer webcontents.
+// Neither should include the other in their frames collection.
 IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, FramesIndependent) {
-  auto* window = browser()->window();
-  ASSERT_TRUE(window);
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+  EXPECT_EQ(0, EvalJs(inner_webcontents, "window.frames.length"));
 
-  content::WebContents* web_contents =
-      browser()->tab_strip_model()->GetActiveWebContents();
-  ASSERT_TRUE(web_contents);
-  EXPECT_TRUE(content::WaitForLoadStop(web_contents));
-
-  // Make sure that the web contents actually got converted to a guest before
-  // we navigate it again, so that WebContentsViewChildFrame gets involved.
-  EXPECT_TRUE(base::test::RunUntil([web_contents]() {
-    return web_contents->GetOuterWebContents() != nullptr;
-  }));
-
-  GURL url = embedded_https_test_server().GetURL("a.com", "/defaultresponse");
-  EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), url));
-  EXPECT_EQ(0, EvalJs(web_contents, "window.frames.length"));
-
-  content::WebContents* outer_webcontents = web_contents->GetOuterWebContents();
-  EXPECT_TRUE(outer_webcontents->GetOuterWebContents() == nullptr);
-  EXPECT_NE(outer_webcontents, nullptr);
+  content::WebContents* outer_webcontents =
+      inner_webcontents->GetOuterWebContents();
   EXPECT_EQ(0, EvalJs(outer_webcontents, "window.frames.length"));
 }
+
+// Test that the parent window does not count the embedded content as a frame.
+// The outer web contents should have window.length = 0 since the embedded
+// content should not be counted in the parent's frame count.
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, WindowLengthIndependent) {
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+
+  content::WebContents* outer_webcontents =
+      inner_webcontents->GetOuterWebContents();
+  EXPECT_EQ(0, EvalJs(outer_webcontents, "window.length"));
+}
+
+// Test that the embedded content acts as top level.
+// window.top in the embedded content should equal window (itself),
+// not the actual parent's top-level window.
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, WindowTopIndependent) {
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+
+  EXPECT_TRUE(EvalJs(inner_webcontents, "window.top === window").ExtractBool());
+}
+
+// Test that the embedded content acts as top level.
+// window.opener should be null since the embedded content should not
+// have access to the parent that "opened" it.
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, WindowOpenerIndependent) {
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+
+  EXPECT_TRUE(
+      EvalJs(inner_webcontents, "window.opener === null").ExtractBool());
+}
+
+// Test that the embedded content acts as top level.
+// window.parent should equal window (itself) since there should be
+// no accessible parent window from the embedded content's perspective.
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, WindowParentIndependent) {
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+
+  EXPECT_TRUE(
+      EvalJs(inner_webcontents, "window.parent === window").ExtractBool());
+}
+
+// Test that the embedded content acts as top level.
+// window.frameElement should be null since the embedded content should
+// not appear to be contained within a frame element.
+IN_PROC_BROWSER_TEST_F(WebUIBrowserTest, WindowFrameElementIndependent) {
+  content::WebContents* inner_webcontents = SetUpEmbeddedWebContents();
+
+  EXPECT_TRUE(
+      EvalJs(inner_webcontents, "window.frameElement === null").ExtractBool());
+}
+
 #endif  // !BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index 290230ca..c9d85b2 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -596,6 +596,8 @@
         "preinstalled_web_apps/messages_dogfood.h",
         "preinstalled_web_apps/notebook_lm.cc",
         "preinstalled_web_apps/notebook_lm.h",
+        "preinstalled_web_apps/vids.cc",
+        "preinstalled_web_apps/vids.h",
       ]
       deps += [ "//extensions/common:common_constants" ]
     }
diff --git a/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc b/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
index a783b2b5..3c98fc5 100644
--- a/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
+++ b/chrome/browser/web_applications/chromeos_web_app_experiments_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/test/test_future.h"
 #include "build/build_config.h"
 #include "chrome/browser/apps/app_service/app_registry_cache_waiter.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
@@ -20,8 +19,6 @@
 #include "chrome/browser/apps/link_capturing/link_capturing_feature_test_support.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_list_observer.h"
-#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
@@ -31,14 +28,12 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/base/ui_test_utils.h"
 #include "chromeos/constants/chromeos_features.h"
-#include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "content/public/test/theme_change_waiter.h"
-#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
 #include "third_party/blink/public/common/manifest/manifest.h"
 #include "third_party/blink/public/mojom/input/input_event.mojom-shared.h"
@@ -54,56 +49,6 @@
 
 namespace web_app {
 
-// A TestNavigationObserver that also waits for the browser window containing
-// the navigation to become active.
-class ActiveBrowserWindowNavigationObserver
-    : public content::TestNavigationObserver,
-      public BrowserListObserver {
- public:
-  explicit ActiveBrowserWindowNavigationObserver(const GURL& target_url)
-      : content::TestNavigationObserver(target_url) {
-    WatchExistingWebContents();
-    StartWatchingNewWebContents();
-  }
-
-  BrowserWindowInterface* WaitForActiveWindow() {
-    Wait();
-    EXPECT_TRUE(navigated_contents_);
-    return active_browser_future_.Get();
-  }
-
- protected:
-  void CheckNavigatedWindowActive(BrowserWindowInterface* active_browser) {
-    ASSERT_TRUE(navigated_contents_);
-    if (active_browser->GetTabStripModel()->GetActiveWebContents() ==
-        navigated_contents_) {
-      active_browser_future_.SetValue(active_browser);
-    }
-  }
-
-  // TestNavigationObserver:
-  void NavigationOfInterestDidFinish(
-      content::NavigationHandle* navigation_handle) override {
-    ASSERT_FALSE(navigated_contents_);
-    navigated_contents_ = navigation_handle->GetWebContents();
-
-    // Check if the navigated WebContents is already active.
-    CheckNavigatedWindowActive(
-        GetLastActiveBrowserWindowInterfaceWithAnyProfile());
-  }
-
-  // BrowserListObserver:
-  void OnBrowserSetLastActive(Browser* browser) override {
-    if (navigated_contents_) {
-      CheckNavigatedWindowActive(browser);
-    }
-  }
-
- private:
-  raw_ptr<content::WebContents> navigated_contents_ = nullptr;
-  base::test::TestFuture<BrowserWindowInterface*> active_browser_future_;
-};
-
 class ChromeOsWebAppExperimentsBrowserTest
     : public WebAppNavigationBrowserTest,
       public testing::WithParamInterface<
@@ -240,11 +185,6 @@
         )",
         on_click_code.c_str());
     ASSERT_TRUE(content::ExecJs(web_contents, script));
-
-    // Input events to a page may not work right after a page load. See
-    // browser_test_utils.h for details.
-    SimulateEndOfPaintHoldingOnPrimaryMainFrame(web_contents);
-
     content::SimulateMouseClick(web_contents,
                                 blink::WebInputEvent::Modifiers::kNoModifiers,
                                 blink::WebMouseEvent::Button::kLeft);
@@ -291,12 +231,13 @@
       )",
       extended_scope_page_.spec().c_str());
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(app_web_contents, on_click_code);
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
-  // The web app handles the navigation without opening a new window.
-  EXPECT_EQ(active_browser, app_browser);
+  // The web app handles the navigation.
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_TRUE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -328,13 +269,13 @@
       )",
       extended_scope_page_.spec().c_str());
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(app_web_contents, on_click_code);
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // The web app handles the navigation by opening a new app window.
-  ASSERT_TRUE(active_browser);
-  EXPECT_NE(active_browser, app_browser);
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_TRUE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -356,13 +297,13 @@
       )",
       extended_scope_page_.spec().c_str());
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(app_web_contents, on_click_code);
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // The web app handles the navigation by opening a new app window.
-  ASSERT_TRUE(active_browser);
-  EXPECT_NE(active_browser, app_browser);
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_TRUE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -385,13 +326,13 @@
       )",
       extended_scope_page_.spec().c_str());
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(app_web_contents, on_click_code);
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // The web app handles the navigation by opening a new app window.
-  ASSERT_TRUE(active_browser);
-  EXPECT_NE(active_browser, app_browser);
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_TRUE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -410,14 +351,14 @@
   content::WebContents* page_web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(page_web_contents,
                           GetFormBasedRedirectorCode(extended_scope_page_));
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // The web app handles the navigation by opening a new app window.
-  ASSERT_TRUE(active_browser);
-  EXPECT_NE(active_browser, browser());
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_TRUE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -438,14 +379,14 @@
   content::WebContents* page_web_contents =
       browser()->tab_strip_model()->GetActiveWebContents();
 
-  ActiveBrowserWindowNavigationObserver observer(extended_scope_page_);
+  auto observer = GetTestNavigationObserver(extended_scope_page_);
   AddAndClickLinkWithCode(page_web_contents,
                           GetFormBasedRedirectorCode(extended_scope_page_));
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // The app window was not launched for the navigation.
-  ASSERT_TRUE(active_browser);
-  EXPECT_EQ(active_browser, browser());
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_FALSE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
@@ -463,14 +404,14 @@
       app_browser->tab_strip_model()->GetActiveWebContents();
 
   const GURL target_url = https_server().GetURL("/empty.html");
-  ActiveBrowserWindowNavigationObserver observer(target_url);
+  auto observer = GetTestNavigationObserver(target_url);
   ClickLink(app_web_contents, target_url, LinkTarget::BLANK,
             /*rel=*/"noreferrer noopener");
-  BrowserWindowInterface* const active_browser = observer.WaitForActiveWindow();
+  observer->Wait();
 
   // A browser tab is opened for the target URL.
-  ASSERT_TRUE(active_browser);
-  EXPECT_NE(active_browser, app_browser);
+  BrowserWindowInterface* const active_browser =
+      GetLastActiveBrowserWindowInterfaceWithAnyProfile();
   EXPECT_FALSE(AppBrowserController::IsForWebApp(active_browser, app_id_));
   EXPECT_EQ(active_browser->GetTabStripModel()
                 ->GetActiveWebContents()
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
index 8802e47..5ffd93c 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
@@ -38,7 +38,9 @@
 #include "chrome/browser/web_applications/preinstalled_web_apps/google_meet.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/messages_dogfood.h"
 #include "chrome/browser/web_applications/preinstalled_web_apps/notebook_lm.h"
+#include "chrome/browser/web_applications/preinstalled_web_apps/vids.h"
 #include "chrome/common/extensions/extension_constants.h"
+#include "chromeos/constants/chromeos_features.h"
 #include "extensions/common/constants.h"
 #include "google_apis/gaia/gaia_auth_util.h"
 #endif  // BUILDFLAG(IS_CHROMEOS)
@@ -105,6 +107,12 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
   };
 
+#if BUILDFLAG(IS_CHROMEOS)
+  if (base::FeatureList::IsEnabled(chromeos::features::kVidsAppPreinstall)) {
+    apps.push_back(GetConfigForVids());
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
 #if !BUILDFLAG(IS_CHROMEOS)
   if (base::FeatureList::IsEnabled(kChatPreinstalledWebApp)) {
     apps.insert(apps.end(), GetConfigForGoogleChat(
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/vids.cc b/chrome/browser/web_applications/preinstalled_web_apps/vids.cc
new file mode 100644
index 0000000..7d624cf
--- /dev/null
+++ b/chrome/browser/web_applications/preinstalled_web_apps/vids.cc
@@ -0,0 +1,85 @@
+// Copyright 2025 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/web_applications/preinstalled_web_apps/vids.h"
+
+#include "ash/constants/web_app_id_constants.h"
+#include "base/functional/bind.h"
+#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
+#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
+#include "chrome/browser/web_applications/preinstalled_app_install_features.h"
+#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_app_definition_utils.h"
+#include "chrome/browser/web_applications/web_app_helpers.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "chrome/grit/preinstalled_web_apps_resources.h"
+#include "third_party/blink/public/common/manifest/manifest.h"
+#include "third_party/blink/public/common/safe_url_pattern.h"
+#include "third_party/liburlpattern/parse.h"
+#include "third_party/liburlpattern/part.h"
+#include "third_party/liburlpattern/pattern.h"
+
+namespace web_app {
+
+namespace {
+
+blink::Manifest::TabStrip HomeTabPathnames(
+    std::vector<std::string_view> pathnames) {
+  blink::Manifest::TabStrip tab_strip;
+  auto& home_tab = tab_strip.home_tab.emplace<blink::Manifest::HomeTabParams>();
+
+  for (const std::string_view pathname : pathnames) {
+    base::expected<liburlpattern::Pattern, absl::Status> parse_result =
+        liburlpattern::Parse(pathname, [](std::string_view input) {
+          return std::string(input);
+        });
+    CHECK(parse_result.has_value());
+
+    blink::SafeUrlPattern url_pattern;
+    url_pattern.pathname = std::move(parse_result.value().PartList());
+    for (const liburlpattern::Part& part : url_pattern.pathname) {
+      CHECK_NE(part.type, liburlpattern::PartType::kRegex);
+    }
+    home_tab.scope_patterns.push_back(std::move(url_pattern));
+  }
+
+  return tab_strip;
+}
+
+}  // namespace
+
+ExternalInstallOptions GetConfigForVids() {
+  ExternalInstallOptions options(
+      /*install_url=*/GURL(
+          "https://docs.google.com/videos/installwebapp?usp=chrome_default"),
+      /*user_display_mode=*/mojom::UserDisplayMode::kStandalone,
+      /*install_source=*/ExternalInstallSource::kExternalDefault);
+
+  options.user_type_allowlist = {"unmanaged", "managed"};
+  options.only_use_app_info_factory = true;
+  options.app_info_factory = base::BindRepeating([]() {
+    GURL start_url =
+        GURL("https://docs.google.com/videos/?usp=installed_webapp");
+    webapps::ManifestId manifest_id =
+        GenerateManifestId("videos/?usp=installed_webapp", start_url);
+    auto info = std::make_unique<WebAppInstallInfo>(manifest_id, start_url);
+    info->title = u"Vids";
+    info->scope = GURL("https://docs.google.com/videos/");
+    info->display_mode = DisplayMode::kBrowser;
+    info->display_override = {DisplayMode::kTabbed};
+    info->tab_strip = HomeTabPathnames({
+        "/videos/",
+        "/videos/u/:index",
+        "/videos/u/:index/",
+    });
+    info->icon_bitmaps.any =
+        LoadBundledIcons({IDR_PREINSTALLED_WEB_APPS_VIDS_ICON_144_PNG});
+    return info;
+  });
+  options.expected_app_id = ash::kVidsAppId;
+
+  return options;
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/vids.h b/chrome/browser/web_applications/preinstalled_web_apps/vids.h
new file mode 100644
index 0000000..a98122f
--- /dev/null
+++ b/chrome/browser/web_applications/preinstalled_web_apps/vids.h
@@ -0,0 +1,17 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_VIDS_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_VIDS_H_
+
+#include "chrome/browser/web_applications/external_install_options.h"
+
+namespace web_app {
+
+// Returns the config for preinstalling the Vids app.
+ExternalInstallOptions GetConfigForVids();
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_PREINSTALLED_WEB_APPS_VIDS_H_
diff --git a/chrome/browser/web_applications/web_app_scope.h b/chrome/browser/web_applications/web_app_scope.h
index e5866d7bb..6464400 100644
--- a/chrome/browser/web_applications/web_app_scope.h
+++ b/chrome/browser/web_applications/web_app_scope.h
@@ -55,6 +55,12 @@
       const GURL& url,
       WebAppScopeScoreOptions options = WebAppScopeScoreOptions()) const;
 
+  const GURL& scope() const { return scope_; }
+
+  const base::flat_set<ScopeExtensionInfo>& validated_scope_extensions() const {
+    return validated_scope_extensions_;
+  }
+
   bool operator==(const WebAppScope& other) const;
 
  private:
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 64cbb35..8d58ef12 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1759924488-e3da09e001217576724d139ef282c4b98dd4ac6b-586f74523e01f66517ccfb6beed4c7e943ec6ace.profdata
+chrome-android32-main-1759967434-2cead1bccc6c8d34dfe60937761769f85ec8eaed-a448ecee062d789daa5fb70bed84846e08e816dd.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index c7af90e..e0832381a0 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1759944655-32f1b77da7055b43f79e97220d24b9ad7ae3f858-47d808b4258c17b18046ba7114012884bd8563af.profdata
+chrome-android64-main-1759989178-37857a53db7ec9d923b6fe163a4f9104018c11d9-8c3a5c2e5f5315e4998479543077add43819aa58.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index cc94965..c37cb18 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1759946382-7610ff0f5500555794b0cab5067c92880d879be9-fee6c9da9c645ec4bcdd789ac89f894449410824.profdata
+chrome-android-desktop-x64-main-1759989178-b99f9b6b695d97da54b5bcda127319fb2502e6b7-8c3a5c2e5f5315e4998479543077add43819aa58.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 72f66ac..3b4c7f1 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1759946382-42308464b7771da9e521d7a327f8a1d134e1a35d-fee6c9da9c645ec4bcdd789ac89f894449410824.profdata
+chrome-linux-main-1759989178-f057ea5cd62168c3d6b4f1395e07d1c00149b67d-8c3a5c2e5f5315e4998479543077add43819aa58.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 922d805..38127472 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1759953581-4d6f48bfbc83aa6dc8329d3f56f722e51ba2a82e-87d37048d4660c3026788080099c508a0ea97b59.profdata
+chrome-mac-arm-main-1759989178-3782005e18fb0077ed5244407eb5383ad0f2ba3c-8c3a5c2e5f5315e4998479543077add43819aa58.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index fb5d968..ef570b0 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1759935520-43d46a9afdca8c3fd328a3279439aeae3cae314b-75d5e8706cb696cba392ce9d51638c16c33132b2.profdata
+chrome-win32-main-1759967434-02657514b65c5f0479fefa6f87a5dceeb5cbe786-a448ecee062d789daa5fb70bed84846e08e816dd.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index ce90533..41cc39ce 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1759935520-95b912030054417b6887c29e4d2edf95e4c51131-75d5e8706cb696cba392ce9d51638c16c33132b2.profdata
+chrome-win64-main-1759967434-32098c0d35956aac4d3c7f58532f0f030474e5fa-a448ecee062d789daa5fb70bed84846e08e816dd.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni
index 13aef8d..f0b5e19e 100644
--- a/chrome/chrome_paks.gni
+++ b/chrome/chrome_paks.gni
@@ -222,6 +222,7 @@
         "$root_gen_dir/chrome/password_manager_resources.pak",
         "$root_gen_dir/chrome/privacy_sandbox_resources.pak",
         "$root_gen_dir/chrome/profile_internals_resources.pak",
+        "$root_gen_dir/chrome/reload_button_resources.pak",
         "$root_gen_dir/chrome/search_engine_choice_resources.pak",
         "$root_gen_dir/chrome/settings_resources.pak",
         "$root_gen_dir/chrome/side_panel_bookmarks_resources.pak",
@@ -256,6 +257,7 @@
         "//chrome/browser/resources/data_sharing:resources",
         "//chrome/browser/resources/lens/overlay:resources",
         "//chrome/browser/resources/lens/shared:resources",
+        "//chrome/browser/resources/reload_button:resources",
         "//chrome/browser/resources/search_engine_choice:resources",
         "//chrome/browser/resources/side_panel/comments:resources",
         "//chrome/browser/resources/tab_group_home:resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index eec31a4..329fbea2 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -436,6 +436,11 @@
 // if user manually resizes.
 const base::FeatureParam<int> kGlicSidePanelMinWidth{
     &kGlicMultiInstance, "glic-side-panel-min-width", 384};
+// Controls the width and height of the multi-instance floating panel.
+const base::FeatureParam<int> kGlicMultiInstanceFloatyWidth{
+    &kGlicMultiInstance, "glic-multi-instance-floaty-width", 400};
+const base::FeatureParam<int> kGlicMultiInstanceFloatyHeight{
+    &kGlicMultiInstance, "glic-multi-instance-floaty-height", 400};
 
 // Controls whether the Glic feature's z order changes based on the webclient
 // mode.
@@ -1686,6 +1691,10 @@
 // the WebUI implementation of top chrome. Individual features will be
 // additionally gated by this flag.
 BASE_FEATURE(kInitialWebUI, base::FEATURE_DISABLED_BY_DEFAULT);
+// When enable, the reload button will be replaced with the a WebView, and
+// chrome://reload-button.top-chrome will be loaded as the content.
+// crbug.com/444358999
+BASE_FEATURE(kWebUIReloadButton, base::FEATURE_DISABLED_BY_DEFAULT);
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 // Enables the User-Agent override fix for SearchPrefetch. This will work only
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index d7d6c136..b5d9624 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -440,6 +440,10 @@
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicMultiInstance);
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::FeatureParam<int> kGlicSidePanelMinWidth;
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::FeatureParam<int> kGlicMultiInstanceFloatyWidth;
+COMPONENT_EXPORT(CHROME_FEATURES)
+extern const base::FeatureParam<int> kGlicMultiInstanceFloatyHeight;
 
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicZOrderChanges);
 
@@ -1251,6 +1255,11 @@
 BASE_DECLARE_FEATURE(kWebium);
 COMPONENT_EXPORT(CHROME_FEATURES)
 BASE_DECLARE_FEATURE(kInitialWebUI);
+// TODO(crbug.com/444358999): after the experiment to collect metrics, either
+// remove this reload button web UI or extend it to include more top-chrome
+// components.
+COMPONENT_EXPORT(CHROME_FEATURES)
+BASE_DECLARE_FEATURE(kWebUIReloadButton);
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/common/webui_url_constants.cc b/chrome/common/webui_url_constants.cc
index 85b06a4..b497a43 100644
--- a/chrome/common/webui_url_constants.cc
+++ b/chrome/common/webui_url_constants.cc
@@ -121,6 +121,9 @@
       kChromeUIPrefsInternalsHost,
       kChromeUIProfileInternalsHost,
       content::kChromeUIQuotaInternalsHost,
+#if !BUILDFLAG(IS_ANDROID)
+      kChromeUIReloadButtonHost,
+#endif
       kChromeUISignInInternalsHost,
       kChromeUISiteEngagementHost,
 #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h
index c98aa09..bc84e44 100644
--- a/chrome/common/webui_url_constants.h
+++ b/chrome/common/webui_url_constants.h
@@ -300,6 +300,9 @@
 inline constexpr char kChromeUITermsHost[] = "terms";
 inline constexpr char kChromeUITermsURL[] = "chrome://terms/";
 inline constexpr char kChromeUIThemeHost[] = "theme";
+inline constexpr char kChromeUIReloadButtonURL[] =
+    "chrome://reload-button.top-chrome";
+inline constexpr char kChromeUIReloadButtonHost[] = "reload-button.top-chrome";
 inline constexpr char kChromeUIThemeURL[] = "chrome://theme/";
 inline constexpr char kChromeUITopChromeDomain[] = "top-chrome";
 inline constexpr char kChromeUITranslateInternalsHost[] = "translate-internals";
diff --git a/chrome/test/base/in_process_browser_test.cc b/chrome/test/base/in_process_browser_test.cc
index 69190d7..e0a468f 100644
--- a/chrome/test/base/in_process_browser_test.cc
+++ b/chrome/test/base/in_process_browser_test.cc
@@ -61,6 +61,7 @@
 #include "chrome/browser/ui/browser_tabstrip.h"
 #include "chrome/browser/ui/browser_window.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "chrome/browser/ui/toolbar_controller_util.h"
 #include "chrome/common/chrome_constants.h"
@@ -596,13 +597,7 @@
 }
 
 void InProcessBrowserTest::SetBrowser(BrowserWindowInterface* browser) {
-  browser_ = browser->GetBrowserForMigrationOnly();
-}
-
-void InProcessBrowserTest::SelectFirstBrowser() {
-  const BrowserList* browser_list = BrowserList::GetInstance();
-  if (!browser_list->empty())
-    browser_ = browser_list->get(0);
+  browser_ = browser ? browser->GetBrowserForMigrationOnly() : nullptr;
 }
 
 void InProcessBrowserTest::RecordPropertyFromMap(
@@ -838,7 +833,7 @@
   // Pump startup related events.
   content::RunAllPendingInMessageLoop();
 
-  SelectFirstBrowser();
+  SetBrowser(GetLastActiveBrowserWindowInterfaceWithAnyProfile());
   if (browser_ && !browser_->tab_strip_model()->empty()) {
     base::WeakPtr<content::WebContents> tab =
         browser_->tab_strip_model()->GetActiveWebContents()->GetWeakPtr();
diff --git a/chrome/test/base/in_process_browser_test.h b/chrome/test/base/in_process_browser_test.h
index 612a8fd..92fc2be 100644
--- a/chrome/test/base/in_process_browser_test.h
+++ b/chrome/test/base/in_process_browser_test.h
@@ -181,23 +181,14 @@
   // and setup functions.
   static size_t GetTestPreCount();
 
-  // Returns the browser created by BrowserMain().
-  // If no browser is created in BrowserMain(), this will return nullptr unless
-  // another browser instance is created at a later time and
-  // `SelectFirstBrowser()` or `SetBrowser()` is called.
+  // Returns the browser created by BrowserMain(). If no browser is created in
+  // BrowserMain(), this will return nullptr unless another browser instance is
+  // created at a later time and `SetBrowser()` is called.
   Browser* browser() const { return browser_; }
 
   // Sets the default `browser_` instance for the fixture.
   void SetBrowser(BrowserWindowInterface* browser);
 
-  // Set |browser_| to the first browser on the browser list.
-  // Call this when your test subclass wants to access a non-null browser
-  // instance through browser() but browser creation is delayed until after
-  // PreRunTestOnMainThread().
-  // DEPRECATED: Clients should not rely on ordering in the global BrowserList,
-  // use SetBrowser() instead.
-  void SelectFirstBrowser();
-
   // This function is used to record a set of properties for a test case in
   // gtest result and that will be used by resultDB. The map's key value pair
   // are defined by each test case. For use case check this bug:
@@ -375,9 +366,8 @@
   static SetUpBrowserFunction* global_browser_set_up_function_;
 
   // Usually references the browser created in BrowserMain().
-  // If no browser is created in BrowserMain(), then |browser_| will remain
-  // nullptr unless SelectFirstBrowser() is called after the creation of the
-  // first browser instance at a later time.
+  // If no browser is created in BrowserMain(), then `browser_` will remain
+  // nullptr unless `SetBrowser()` is called at a later time.
   raw_ptr<Browser, AcrossTasksDanglingUntriaged> browser_ = nullptr;
 
   // Used to run the process until the BrowserProcess signals the test to quit.
diff --git a/chrome/test/data/webui/omnibox_popup/BUILD.gn b/chrome/test/data/webui/omnibox_popup/BUILD.gn
index 3a76deab..9c85035 100644
--- a/chrome/test/data/webui/omnibox_popup/BUILD.gn
+++ b/chrome/test/data/webui/omnibox_popup/BUILD.gn
@@ -7,7 +7,10 @@
 assert(!is_android && !is_ios)
 
 build_webui_tests("build") {
-  files = [ "app_test.ts" ]
+  files = [
+    "app_test.ts",
+    "full_app_test.ts",
+  ]
 
   ts_path_mappings = [ "chrome://omnibox-popup.top-chrome/omnibox_popup.js|" + rebase_path(
                            "$root_gen_dir/chrome/browser/resources/omnibox_popup/tsc/omnibox_popup.d.ts",
diff --git a/chrome/test/data/webui/omnibox_popup/full_app_test.ts b/chrome/test/data/webui/omnibox_popup/full_app_test.ts
new file mode 100644
index 0000000..f06543b5
--- /dev/null
+++ b/chrome/test/data/webui/omnibox_popup/full_app_test.ts
@@ -0,0 +1,20 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'chrome://omnibox-popup.top-chrome/omnibox_popup.js';
+
+import {assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {eventToPromise} from 'chrome://webui-test/test_util.js';
+
+suite('FullAppTest', function() {
+  test('ContextMenuPrevented', async function() {
+    const app = document.createElement('omnibox-full-app');
+    document.body.appendChild(app);
+    const whenFired = eventToPromise('contextmenu', document.documentElement);
+    document.documentElement.dispatchEvent(
+        new Event('contextmenu', {cancelable: true}));
+    const e = await whenFired;
+    assertTrue(e.defaultPrevented);
+  });
+});
diff --git a/chrome/test/data/webui/omnibox_popup/omnibox_popup_browsertest.cc b/chrome/test/data/webui/omnibox_popup/omnibox_popup_browsertest.cc
index 1abf427b..c46df65 100644
--- a/chrome/test/data/webui/omnibox_popup/omnibox_popup_browsertest.cc
+++ b/chrome/test/data/webui/omnibox_popup/omnibox_popup_browsertest.cc
@@ -3,23 +3,52 @@
 // found in the LICENSE file.
 
 #include "base/test/scoped_feature_list.h"
+#include "build/config/coverage/buildflags.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/test/base/web_ui_mocha_browser_test.h"
 #include "components/omnibox/common/omnibox_features.h"
 #include "content/public/test/browser_test.h"
 
-class OmniboxPopupBrowserTest : public WebUIMochaBrowserTest {
+class OmniboxPopupTest : public WebUIMochaBrowserTest {
  protected:
-  OmniboxPopupBrowserTest() {
+  OmniboxPopupTest() {
     set_test_loader_host(chrome::kChromeUIOmniboxPopupHost);
+    scoped_feature_list_.InitWithFeatures({omnibox::kWebUIOmniboxPopup},
+                                          {omnibox::kWebUIOmniboxFullPopup});
   }
 
  private:
-  base::test::ScopedFeatureList scoped_feature_list_{
-      omnibox::kWebUIOmniboxPopup};
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-typedef OmniboxPopupBrowserTest OmniboxPopupTest;
-IN_PROC_BROWSER_TEST_F(OmniboxPopupTest, App) {
+#if BUILDFLAG(USE_JAVASCRIPT_COVERAGE)
+// TODO(crbug.com/40284073): Test fails with JS coverage turned on.
+#define MAYBE_App DISABLED_App
+#else
+#define MAYBE_App App
+#endif
+IN_PROC_BROWSER_TEST_F(OmniboxPopupTest, MAYBE_App) {
   RunTest("omnibox_popup/app_test.js", "mocha.run();");
 }
+
+class OmniboxPopupFullTest : public WebUIMochaBrowserTest {
+ protected:
+  OmniboxPopupFullTest() {
+    set_test_loader_host(chrome::kChromeUIOmniboxPopupHost);
+    scoped_feature_list_.InitWithFeatures(
+        {omnibox::kWebUIOmniboxPopup, omnibox::kWebUIOmniboxFullPopup}, {});
+  }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+#if BUILDFLAG(USE_JAVASCRIPT_COVERAGE)
+// TODO(crbug.com/40284073): Test fails with JS coverage turned on.
+#define MAYBE_App DISABLED_App
+#else
+#define MAYBE_App App
+#endif
+IN_PROC_BROWSER_TEST_F(OmniboxPopupFullTest, MAYBE_App) {
+  RunTest("omnibox_popup/full_app_test.js", "mocha.run();");
+}
diff --git a/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts b/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts
index 505cd71f..bf64c17 100644
--- a/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts
+++ b/chrome/test/data/webui/side_panel/read_anything/app_receives_toolbar_changes_test.ts
@@ -310,6 +310,15 @@
             chrome.readingMode.keyboardShortcutStopSource,
             await metrics.whenCalled('recordSpeechStopSource'));
       });
+
+      test('other key presses do not play', async () => {
+        const fPress = new KeyboardEvent('keydown', {key: 'f'});
+        app.$.appFlexParent.dispatchEvent(fPress);
+        await microtasksFinished();
+
+        assertFalse(speechController.isSpeechActive());
+        assertEquals(0, metrics.getCallCount('recordSpeechStopSource'));
+      });
     });
   });
 
diff --git a/chrome/test/data/webui/tab_search/split_new_tab_page_test.ts b/chrome/test/data/webui/tab_search/split_new_tab_page_test.ts
index 2de65aa8..2ccc569 100644
--- a/chrome/test/data/webui/tab_search/split_new_tab_page_test.ts
+++ b/chrome/test/data/webui/tab_search/split_new_tab_page_test.ts
@@ -114,6 +114,49 @@
     assertEquals(3, tabSearchItems.length);
   });
 
+  test('Formats urls properly', async () => {
+    await splitNewTabPageSetup();
+
+    const windowData = createWindowData();
+    windowData[0]!.tabs.push(
+        createTab({
+          index: 6,
+          lastActiveTimeTicks: {internalValue: BigInt(10)},
+          tabId: 8,
+          title: '',
+          url: {url: 'about:blank'},
+        }),
+        createTab({
+          index: 7,
+          lastActiveTimeTicks: {internalValue: BigInt(11)},
+          tabId: 9,
+          title: 'file.jpg',
+          url: {url: 'file://file.jpg'},
+        }),
+        createTab({
+          index: 8,
+          lastActiveTimeTicks: {internalValue: BigInt(12)},
+          tabId: 10,
+          title: 'Data',
+          url: {url: 'blob://data'},
+        }),
+    );
+    testApiProxy.getCallbackRouterRemote().tabsChanged(createProfileData({
+      windows: windowData,
+    }));
+    await eventToPromise('viewport-filled', splitNewTabPage.$.splitTabsList);
+
+    const tabSearchItems =
+        splitNewTabPage.shadowRoot.querySelectorAll('tab-search-item');
+    assertEquals(
+        loadTimeData.getString('blobUrlSource'),
+        tabSearchItems[1]!.data.hostname);
+    assertEquals(
+        loadTimeData.getString('fileUrlSource'),
+        tabSearchItems[2]!.data.hostname);
+    assertEquals('about:blank', tabSearchItems[3]!.data.hostname);
+  });
+
   test('Sorts list', async () => {
     await splitNewTabPageSetup();
     const tabSearchItems =
diff --git a/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc b/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc
index 637cb94..2b493ad 100644
--- a/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc
+++ b/chrome/test/fuzzing/kombucha_in_process_fuzzer.cc
@@ -10,6 +10,7 @@
 #include "chrome/app/chrome_command_ids.h"
 #include "chrome/browser/ui/accelerator_utils.h"
 #include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/tabs/tab_group_model.h"
 #include "chrome/browser/ui/ui_features.h"
 #include "chrome/browser/ui/views/tabs/tab.h"
@@ -175,7 +176,7 @@
     for (Browser* browser : extra_browsers) {
       CloseBrowserSynchronously(browser);
     }
-    SelectFirstBrowser();
+    SetBrowser(GetLastActiveBrowserWindowInterfaceWithAnyProfile());
   }
 
   TabStripModel* tab_strip_model = browser()->tab_strip_model();
diff --git a/chrome/test/media_router/performance/openscreen_cast_performance_test.py b/chrome/test/media_router/performance/openscreen_cast_performance_test.py
index a69e74e..eb78c12 100644
--- a/chrome/test/media_router/performance/openscreen_cast_performance_test.py
+++ b/chrome/test/media_router/performance/openscreen_cast_performance_test.py
@@ -105,10 +105,9 @@
 ]
 
 HOST_TUNNEL_CMD = [
-    'sshpass',
-    '-p',
-    PASSWORD,
     'ssh',
+    '-i',
+    '~/.ssh/id_ed25519',
     '-L',
     f'{CHROMEDRIVER_PORT}:127.0.0.1:{CHROMEDRIVER_PORT}',
     f'{USERNAME}@{SENDER}',
@@ -172,8 +171,14 @@
     Returns:
         subprocess.CompletedProcess or subprocess.Popen: The process object.
     """
-    ssh_command = ['sshpass', '-p', password, 'ssh',
-                   f'{username}@{hostname}', command]
+    ssh_command = [
+        'ssh',
+        '-i',
+        '~/.ssh/id_ed25519',
+        f'{username}@{hostname}',
+        command
+    ]
+
     if blocking:
         process = subprocess.run(
             ssh_command,
diff --git a/chrome/updater/app/server/win/com_classes_legacy.cc b/chrome/updater/app/server/win/com_classes_legacy.cc
index 46fe251..39cdff3 100644
--- a/chrome/updater/app/server/win/com_classes_legacy.cc
+++ b/chrome/updater/app/server/win/com_classes_legacy.cc
@@ -1255,7 +1255,7 @@
     substitutions.push_back(substitution_string.value());
   }
 
-  const HRESULT hr = app_command_runner_.value()->Run(substitutions, process_);
+  const HRESULT hr = app_command_runner_->Run(substitutions, process_);
   using LegacyAppCommandWebImplPtr =
       Microsoft::WRL::ComPtr<LegacyAppCommandWebImpl>;
   update_client::Callback callback = base::BindOnce(
diff --git a/chrome/updater/app/server/win/com_classes_legacy.h b/chrome/updater/app/server/win/com_classes_legacy.h
index a26aa24..a839cc6 100644
--- a/chrome/updater/app/server/win/com_classes_legacy.h
+++ b/chrome/updater/app/server/win/com_classes_legacy.h
@@ -320,7 +320,7 @@
   ~LegacyAppCommandWebImpl() override;
 
   base::Process process_;
-  HResultOr<scoped_refptr<AppCommandRunner>> app_command_runner_;
+  HResultOr<AppCommandRunner> app_command_runner_;
   UpdaterScope scope_ = UpdaterScope::kSystem;
   std::string app_id_;
   std::string command_id_;
diff --git a/chrome/updater/app/server/win/com_classes_legacy_unittest.cc b/chrome/updater/app/server/win/com_classes_legacy_unittest.cc
index 8b5afdbb..0c970728 100644
--- a/chrome/updater/app/server/win/com_classes_legacy_unittest.cc
+++ b/chrome/updater/app/server/win/com_classes_legacy_unittest.cc
@@ -204,7 +204,7 @@
             EXPECT_EQ(app_id, base::WideToUTF8(kAppId1));
             EXPECT_EQ(command_id, base::WideToUTF8(kCmdId1));
             EXPECT_EQ(error_params.error_code,
-                      GOOPDATEINSTALL_E_INSTALLER_FAILED_START);
+                      HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
             EXPECT_EQ(error_params.extra_code1, kErrorAppCommandLaunchFailed);
           }),
       app_command_web));
diff --git a/chrome/updater/auto_run_on_os_upgrade_task.cc b/chrome/updater/auto_run_on_os_upgrade_task.cc
index 942b9636..e07da97 100644
--- a/chrome/updater/auto_run_on_os_upgrade_task.cc
+++ b/chrome/updater/auto_run_on_os_upgrade_task.cc
@@ -93,7 +93,7 @@
           scope_, base::SysUTF8ToWide(app_id)),
       [&](const auto& app_command_runner) {
         base::Process process;
-        if (FAILED(app_command_runner->Run(
+        if (FAILED(app_command_runner.Run(
                 {base::SysUTF8ToWide(os_upgrade_string_)}, process))) {
           return;
         }
diff --git a/chrome/updater/auto_run_on_os_upgrade_task_unittest.cc b/chrome/updater/auto_run_on_os_upgrade_task_unittest.cc
index 87b3429..f1f09fe 100644
--- a/chrome/updater/auto_run_on_os_upgrade_task_unittest.cc
+++ b/chrome/updater/auto_run_on_os_upgrade_task_unittest.cc
@@ -18,7 +18,6 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/test/bind.h"
-#include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "chrome/updater/activity.h"
 #include "chrome/updater/persisted_data.h"
@@ -75,7 +74,6 @@
   std::unique_ptr<TestingPrefServiceSimple> pref_service_;
   base::CommandLine cmd_exe_command_line_{base::CommandLine::NO_PROGRAM};
   base::ScopedTempDir temp_programfiles_dir_;
-  base::test::TaskEnvironment environment_;
 };
 
 TEST_F(AutoRunOnOsUpgradeTaskTest, RunOnOsUpgradeForApp) {
diff --git a/chrome/updater/win/app_command_runner.cc b/chrome/updater/win/app_command_runner.cc
index ef8381f..12cca54 100644
--- a/chrome/updater/win/app_command_runner.cc
+++ b/chrome/updater/win/app_command_runner.cc
@@ -8,7 +8,6 @@
 
 #include <shellapi.h>
 
-#include <functional>
 #include <optional>
 #include <string>
 #include <utility>
@@ -18,25 +17,17 @@
 #include "base/command_line.h"
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
-#include "base/functional/bind.h"
-#include "base/functional/callback.h"
 #include "base/logging.h"
-#include "base/memory/ref_counted.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/path_service.h"
-#include "base/process/kill.h"
 #include "base/process/launch.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/strings/string_util_impl_helpers.h"
 #include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task/task_traits.h"
-#include "base/task/thread_pool.h"
 #include "base/version.h"
 #include "base/win/registry.h"
 #include "base/win/scoped_localalloc.h"
-#include "chrome/updater/constants.h"
 #include "chrome/updater/updater_branding.h"
 #include "chrome/updater/updater_scope.h"
 #include "chrome/updater/util/win_util.h"
@@ -134,10 +125,13 @@
 }  // namespace
 
 AppCommandRunner::AppCommandRunner() = default;
+AppCommandRunner::AppCommandRunner(const AppCommandRunner&) = default;
+AppCommandRunner& AppCommandRunner::operator=(const AppCommandRunner&) =
+    default;
 AppCommandRunner::~AppCommandRunner() = default;
 
 // static
-HResultOr<scoped_refptr<AppCommandRunner>> AppCommandRunner::LoadAppCommand(
+HResultOr<AppCommandRunner> AppCommandRunner::LoadAppCommand(
     UpdaterScope scope,
     const std::wstring& app_id,
     const std::wstring& command_id) {
@@ -152,11 +146,10 @@
     }
   }
 
-  scoped_refptr<AppCommandRunner> app_command_runner =
-      base::MakeRefCounted<AppCommandRunner>();
+  AppCommandRunner app_command_runner;
   hr = GetAppCommandFormatComponents(scope, command_format,
-                                     app_command_runner->executable_,
-                                     app_command_runner->parameters_);
+                                     app_command_runner.executable_,
+                                     app_command_runner.parameters_);
   if (FAILED(hr)) {
     return base::unexpected(hr);
   }
@@ -165,14 +158,14 @@
 }
 
 // static
-std::vector<scoped_refptr<AppCommandRunner>>
+std::vector<AppCommandRunner>
 AppCommandRunner::LoadAutoRunOnOsUpgradeAppCommands(
     UpdaterScope scope,
     const std::wstring& app_id) {
   const HKEY root = UpdaterScopeToHKeyRoot(scope);
   const std::wstring commands_key_name = GetAppCommandKey(app_id, L"");
 
-  std::vector<scoped_refptr<AppCommandRunner>> app_command_runners;
+  std::vector<AppCommandRunner> app_command_runners;
   for (base::win::RegistryKeyIterator it(root, commands_key_name.c_str(),
                                          KEY_WOW64_32KEY);
        it.Valid(); ++it) {
@@ -190,7 +183,7 @@
       continue;
     }
 
-    HResultOr<scoped_refptr<AppCommandRunner>> runner =
+    HResultOr<AppCommandRunner> runner =
         LoadAppCommand(scope, app_id, it.Name());
     if (runner.has_value()) {
       app_command_runners.push_back(*std::move(runner));
@@ -201,102 +194,48 @@
 }
 
 HRESULT AppCommandRunner::Run(base::span<const std::wstring> substitutions,
-                              base::Process& process) {
-  if (executable_.empty()) {
+                              base::Process& process) const {
+  if (executable_.empty() || process.IsValid()) {
     return E_UNEXPECTED;
   }
 
-  VLOG(2) << __func__ << ": " << executable_ << ": "
-          << base::JoinString(parameters_, L",") << " : "
-          << base::JoinString(substitutions, L",");
+  return ExecuteAppCommand(executable_, parameters_, substitutions, process);
+}
 
-  const std::optional<std::wstring> command_line_parameters =
-      FormatAppCommandLine(parameters_, substitutions);
-  if (!command_line_parameters) {
-    LOG(ERROR) << __func__ << "!command_line_parameters";
+// static
+HRESULT AppCommandRunner::StartProcess(const base::FilePath& executable,
+                                       const std::wstring& parameters,
+                                       base::Process& process) {
+  VLOG(2) << __func__ << ": " << executable << ": " << parameters;
+
+  if (executable.empty() || process.IsValid()) {
+    return E_UNEXPECTED;
+  }
+
+  // `executable` needs to be a full path to prevent `::CreateProcess` (which
+  // `base::LaunchProcess` uses internally) from using the search path for path
+  // resolution.
+  if (!executable.IsAbsolute()) {
+    LOG(ERROR) << __func__ << "!executable.IsAbsolute(): " << executable;
     return E_INVALIDARG;
   }
 
-  VLOG(2) << __func__ << ": " << executable_ << ": "
-          << *command_line_parameters;
+  base::LaunchOptions options = {};
+  options.feedback_cursor_off = true;
+  options.start_hidden = true;
 
-  // `executable_` needs to be a full path to prevent `::CreateProcess` (which
-  // `AppCommandRunner::LaunchProcess` uses internally) from using the search
-  // path for path resolution.
-  if (!executable_.IsAbsolute()) {
-    LOG(ERROR) << __func__ << "!executable_.IsAbsolute(): " << executable_;
-    return E_INVALIDARG;
-  }
-
-  base::WaitableEvent process_event;
-  base::ThreadPool::CreateSequencedTaskRunner(
-      {base::MayBlock(), base::WithBaseSyncPrimitives()})
-      ->PostTask(
-          FROM_HERE,
-          base::BindOnce(
-              [](scoped_refptr<AppCommandRunner> obj,
-                 const std::wstring& command_line_parameters,
-                 base::WaitableEvent& event) {
-                base::LaunchOptions options = {};
-                options.feedback_cursor_off = true;
-                options.start_hidden = true;
-
-                base::TerminationStatus final_status =
-                    base::TerminationStatus::TERMINATION_STATUS_MAX_ENUM;
-
-                int exit_code = -1;
-                std::ignore = base::GetAppOutputWithExitCodeAndTimeout(
-                    base::StrCat({base::CommandLine::QuoteForCommandLineToArgvW(
-                                      obj->executable_.value()),
-                                  L" ", command_line_parameters}),
-                    /*include_stderr=*/true, nullptr, &exit_code,
-                    kWaitForAppInstaller, options,
-                    [&](const base::Process& process,
-                        std::string_view partial_output) {
-                      if (!obj->process_) {
-                        obj->process_ = process.Duplicate();
-                        VLOG(1) << "AppCommand pid: " << obj->process_->Pid();
-                        event.Signal();
-                      }
-
-                      if (!partial_output.empty()) {
-                        VLOG(1) << "AppCommand output: " << partial_output;
-                      }
-                    },
-                    &final_status);
-
-                if (final_status ==
-                    base::TerminationStatus::TERMINATION_STATUS_LAUNCH_FAILED) {
-                  VLOG(1) << "AppCommand failed to launch";
-                  return GOOPDATEINSTALL_E_INSTALLER_FAILED_START;
-                }
-                if (final_status ==
-                    base::TerminationStatus::TERMINATION_STATUS_STILL_RUNNING) {
-                  VLOG(1) << "AppCommand timed out";
-                  return GOOPDATEINSTALL_E_INSTALLER_TIMED_OUT;
-                }
-
-                return exit_code;
-              },
-              base::WrapRefCounted(this), *command_line_parameters,
-              std::ref(process_event))
-              .Then(base::BindOnce(
-                  [](scoped_refptr<AppCommandRunner> obj,
-                     base::WaitableEvent& event, HRESULT hr) {
-                    obj->hr_ = hr;
-                    event.Signal();
-                  },
-                  base::WrapRefCounted(this), std::ref(process_event))));
-
-  process_event.Wait();
-  if (!process_) {
-    const HRESULT hr = hr_.value_or(E_UNEXPECTED);
-    LOG(ERROR) << __func__ << ": base::LaunchProcess failed: " << hr;
+  process = base::LaunchProcess(
+      base::StrCat(
+          {base::CommandLine::QuoteForCommandLineToArgvW(executable.value()),
+           L" ", parameters}),
+      options);
+  if (!process.IsValid()) {
+    const HRESULT hr = HRESULTFromLastError();
+    LOG(ERROR) << __func__ << "base::LaunchProcess failed: " << hr;
     return hr;
   }
 
-  process = process_->Duplicate();
-  VLOG(2) << __func__ << ": Started process with PID: " << process.Pid();
+  VLOG(2) << __func__ << "Started process with PID: " << process.Pid();
   return S_OK;
 }
 
@@ -379,4 +318,24 @@
   return formatted_command_line;
 }
 
+// static
+HRESULT AppCommandRunner::ExecuteAppCommand(
+    const base::FilePath& executable,
+    const std::vector<std::wstring>& parameters,
+    base::span<const std::wstring> substitutions,
+    base::Process& process) {
+  VLOG(2) << __func__ << ": " << executable << ": "
+          << base::JoinString(parameters, L",") << " : "
+          << base::JoinString(substitutions, L",");
+
+  const std::optional<std::wstring> command_line_parameters =
+      FormatAppCommandLine(parameters, substitutions);
+  if (!command_line_parameters) {
+    LOG(ERROR) << __func__ << "!command_line_parameters";
+    return E_INVALIDARG;
+  }
+
+  return StartProcess(executable, command_line_parameters.value(), process);
+}
+
 }  // namespace updater
diff --git a/chrome/updater/win/app_command_runner.h b/chrome/updater/win/app_command_runner.h
index d4d5b65..5ea31e0 100644
--- a/chrome/updater/win/app_command_runner.h
+++ b/chrome/updater/win/app_command_runner.h
@@ -14,7 +14,6 @@
 #include "base/containers/span.h"
 #include "base/files/file_path.h"
 #include "base/gtest_prod_util.h"
-#include "base/memory/ref_counted.h"
 #include "base/process/process.h"
 #include "chrome/updater/updater_scope.h"
 #include "chrome/updater/util/win_util.h"
@@ -23,35 +22,38 @@
 
 // AppCommandRunner loads and runs a pre-registered command line from the
 // registry.
-class AppCommandRunner : public base::RefCountedThreadSafe<AppCommandRunner> {
+class AppCommandRunner {
  public:
   AppCommandRunner();
+  AppCommandRunner(const AppCommandRunner&);
+  AppCommandRunner& operator=(const AppCommandRunner&);
+  ~AppCommandRunner();
 
   // Creates an instance of `AppCommandRunner` object corresponding to `app_id`
   // and `command_id`.
-  static HResultOr<scoped_refptr<AppCommandRunner>> LoadAppCommand(
+  static HResultOr<AppCommandRunner> LoadAppCommand(
       UpdaterScope scope,
       const std::wstring& app_id,
       const std::wstring& command_id);
 
   // Loads and returns a vector of `AppCommandRunner` objects corresponding to
   // "AutoRunOnOsUpgradeAppCommands" for `app_id`.
-  static std::vector<scoped_refptr<AppCommandRunner>>
-  LoadAutoRunOnOsUpgradeAppCommands(UpdaterScope scope,
-                                    const std::wstring& app_id);
+  static std::vector<AppCommandRunner> LoadAutoRunOnOsUpgradeAppCommands(
+      UpdaterScope scope,
+      const std::wstring& app_id);
 
   // Runs the AppCommand with the provided `substitutions` and populates
   // `process` if successful.
   HRESULT Run(base::span<const std::wstring> substitutions,
-              base::Process& process);
-
-  std::string output();
-
- protected:
-  friend class base::RefCountedThreadSafe<AppCommandRunner>;
-  virtual ~AppCommandRunner();
+              base::Process& process) const;
 
  private:
+  // Starts a process with separate `executable` and `parameters` components.
+  // `executable` needs to be an absolute path.
+  static HRESULT StartProcess(const base::FilePath& executable,
+                              const std::wstring& parameters,
+                              base::Process& process);
+
   // Separates a command line in `command_format` into an `executable` and
   // `parameters`. `executable` needs to be an absolute path, and additionally
   // needs to be under %programfiles% for System `scope`. Parameters on the
@@ -90,12 +92,15 @@
       const std::vector<std::wstring>& parameters,
       base::span<const std::wstring> substitutions);
 
+  // Helper method that calls `FormatAppCommandLine` and then `StartProcess`.
+  static HRESULT ExecuteAppCommand(const base::FilePath& executable,
+                                   const std::vector<std::wstring>& parameters,
+                                   base::span<const std::wstring> substitutions,
+                                   base::Process& process);
+
   base::FilePath executable_;
   std::vector<std::wstring> parameters_;
-  std::optional<base::Process> process_;
-  std::optional<HRESULT> hr_;
 
-  friend class base::RefCountedThreadSafe<AppCommandRunner>;
   FRIEND_TEST_ALL_PREFIXES(AppCommandFormatComponentsInvalidPathsTest,
                            TestCases);
   FRIEND_TEST_ALL_PREFIXES(AppCommandFormatComponentsProgramFilesPathsTest,
diff --git a/chrome/updater/win/app_command_runner_unittest.cc b/chrome/updater/win/app_command_runner_unittest.cc
index 69d16d52..5ec59ea 100644
--- a/chrome/updater/win/app_command_runner_unittest.cc
+++ b/chrome/updater/win/app_command_runner_unittest.cc
@@ -24,10 +24,7 @@
 #include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "base/test/gmock_expected_support.h"
-#include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
 #include "base/win/scoped_localalloc.h"
 #include "build/branding_buildflags.h"
 #include "chrome/updater/test/test_scope.h"
@@ -68,7 +65,7 @@
     test::DeleteAppClientKey(GetUpdaterScopeForTesting(), kAppId1);
   }
 
-  HResultOr<scoped_refptr<AppCommandRunner>> CreateAppCommandRunner(
+  HResultOr<AppCommandRunner> CreateAppCommandRunner(
       const std::wstring& app_id,
       const std::wstring& command_id,
       const std::wstring& command_line_format) {
@@ -78,7 +75,7 @@
                                             command_id);
   }
 
-  HResultOr<scoped_refptr<AppCommandRunner>> CreateProcessLauncherRunner(
+  HResultOr<AppCommandRunner> CreateProcessLauncherRunner(
       const std::wstring& app_id,
       const std::wstring& name,
       const std::wstring& pv,
@@ -93,7 +90,6 @@
 
   base::CommandLine cmd_exe_command_line_{base::CommandLine::NO_PROGRAM};
   base::ScopedTempDir temp_programfiles_dir_;
-  base::test::TaskEnvironment environment_;
 };
 
 class AppCommandRunnerTest : public AppCommandRunnerTestBase {};
@@ -368,8 +364,31 @@
   const int expected_exit_code;
 };
 
+class AppCommandExecuteTest
+    : public ::testing::WithParamInterface<AppCommandTestCase>,
+      public AppCommandRunnerTestBase {};
+
+INSTANTIATE_TEST_SUITE_P(AppCommandExecuteTestCases,
+                         AppCommandExecuteTest,
+                         ::testing::ValuesIn(std::vector<AppCommandTestCase>{
+                             {{L"/c", L"exit 7"}, {}, 7},
+                             {{L"/c", L"exit %1"}, {L"5420"}, 5420},
+                         }));
+
+TEST_P(AppCommandExecuteTest, TestCases) {
+  base::Process process;
+  ASSERT_HRESULT_SUCCEEDED(AppCommandRunner::ExecuteAppCommand(
+      cmd_exe_command_line_.GetProgram(), GetParam().input,
+      GetParam().substitutions, process));
+
+  int exit_code = 0;
+  EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
+                                             &exit_code));
+  EXPECT_EQ(exit_code, GetParam().expected_exit_code);
+}
+
 TEST_F(AppCommandRunnerTest, NoApp) {
-  HResultOr<scoped_refptr<AppCommandRunner>> app_command_runner =
+  HResultOr<AppCommandRunner> app_command_runner =
       AppCommandRunner::LoadAppCommand(GetUpdaterScopeForTesting(), kAppId1,
                                        kCmdId1);
   EXPECT_FALSE(app_command_runner.has_value());
@@ -378,7 +397,7 @@
 TEST_F(AppCommandRunnerTest, NoCmd) {
   test::CreateAppCommandRegistry(GetUpdaterScopeForTesting(), kAppId1, kCmdId1,
                                  kCmdLineValid);
-  HResultOr<scoped_refptr<AppCommandRunner>> app_command_runner =
+  HResultOr<AppCommandRunner> app_command_runner =
       AppCommandRunner::LoadAppCommand(GetUpdaterScopeForTesting(), kAppId1,
                                        kCmdId2);
   EXPECT_FALSE(app_command_runner.has_value());
@@ -396,11 +415,10 @@
                          }));
 
 TEST_P(RunAppCommandFormatTest, TestCases) {
-  scoped_refptr<AppCommandRunner> app_command_runner =
-      base::MakeRefCounted<AppCommandRunner>();
+  AppCommandRunner app_command_runner;
 
   base::Process process;
-  ASSERT_EQ(app_command_runner->Run(GetParam().substitutions, process),
+  ASSERT_EQ(app_command_runner.Run(GetParam().substitutions, process),
             E_UNEXPECTED);
 
   ASSERT_OK_AND_ASSIGN(
@@ -410,7 +428,7 @@
           base::StrCat({cmd_exe_command_line_.GetCommandLineString(), L" ",
                         base::JoinString(GetParam().input, L" ")})));
   ASSERT_HRESULT_SUCCEEDED(
-      app_command_runner->Run(GetParam().substitutions, process));
+      app_command_runner.Run(GetParam().substitutions, process));
 
   int exit_code = 0;
   EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
@@ -486,19 +504,20 @@
     return;
   }
 
+  HResultOr<AppCommandRunner> app_command_runner;
   base::Process process;
-  HResultOr<scoped_refptr<AppCommandRunner>> app_command_runner =
-      CreateProcessLauncherRunner(
-          kAppId1, GetParam().app_name, GetParam().app_version,
-          GetParam().cmd_id,
-          base::StrCat({cmd_exe_command_line_.GetCommandLineString(), L" ",
-                        base::JoinString(GetParam().input, L" ")}));
+  ASSERT_EQ(app_command_runner->Run({}, process), E_UNEXPECTED);
+
+  app_command_runner = CreateProcessLauncherRunner(
+      kAppId1, GetParam().app_name, GetParam().app_version, GetParam().cmd_id,
+      base::StrCat({cmd_exe_command_line_.GetCommandLineString(), L" ",
+                    base::JoinString(GetParam().input, L" ")}));
   ASSERT_EQ(app_command_runner.error_or(S_OK), GetParam().expected_hr);
   if (FAILED(GetParam().expected_hr)) {
     return;
   }
 
-  ASSERT_HRESULT_SUCCEEDED(app_command_runner.value()->Run({}, process));
+  ASSERT_HRESULT_SUCCEEDED(app_command_runner->Run({}, process));
 
   int exit_code = 0;
   EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
@@ -539,10 +558,9 @@
     GTEST_SKIP();
   }
 
-  scoped_refptr<AppCommandRunner> app_command_runner =
-      base::MakeRefCounted<AppCommandRunner>();
+  AppCommandRunner app_command_runner;
   base::Process process;
-  ASSERT_EQ(app_command_runner->Run({}, process), E_UNEXPECTED);
+  ASSERT_EQ(app_command_runner.Run({}, process), E_UNEXPECTED);
 
   if (GetParam().cmd_id_appcommand) {
     test::CreateAppCommandRegistry(
@@ -565,7 +583,7 @@
       AppCommandRunner::LoadAppCommand(GetUpdaterScopeForTesting(), kAppId1,
                                        GetParam().cmd_id_to_execute));
 
-  ASSERT_HRESULT_SUCCEEDED(app_command_runner->Run({}, process));
+  ASSERT_HRESULT_SUCCEEDED(app_command_runner.Run({}, process));
 
   int exit_code = 0;
   EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
@@ -610,7 +628,7 @@
                       base::JoinString(app_command.input, L" ")}));
   });
 
-  const std::vector<scoped_refptr<AppCommandRunner>> app_command_runners =
+  const std::vector<AppCommandRunner> app_command_runners =
       AppCommandRunner::LoadAutoRunOnOsUpgradeAppCommands(
           GetUpdaterScopeForTesting(), kAppId1);
 
@@ -618,9 +636,8 @@
   std::ranges::for_each(
       app_command_runners, [&](const auto& app_command_runner) {
         base::Process process;
-        EXPECT_HRESULT_SUCCEEDED(app_command_runner->Run({}, process));
+        EXPECT_HRESULT_SUCCEEDED(app_command_runner.Run({}, process));
         EXPECT_TRUE(process.WaitForExit(/*exit_code=*/nullptr));
-        base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
       });
 }
 
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index bfbcd6cd..9ee9ec0a 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-16442.0.0-1072259
\ No newline at end of file
+16443.0.0-1072279
\ No newline at end of file
diff --git a/chromeos/ash/components/boca/boca_session_manager.cc b/chromeos/ash/components/boca/boca_session_manager.cc
index 7740f52..add08d2 100644
--- a/chromeos/ash/components/boca/boca_session_manager.cc
+++ b/chromeos/ash/components/boca/boca_session_manager.cc
@@ -7,6 +7,7 @@
 #include <algorithm>
 #include <memory>
 #include <optional>
+#include <utility>
 
 #include "ash/constants/ash_constants.h"
 #include "ash/constants/ash_features.h"
@@ -424,9 +425,10 @@
       std::move(frame_received_callback), std::move(crd_state_callback));
 }
 
-void BocaSessionManager::EndSpotlightSession() {
+void BocaSessionManager::EndSpotlightSession(
+    base::OnceClosure on_stopped_callback) {
   CHECK(ash::features::IsBocaSpotlightRobotRequesterEnabled());
-  remoting_client_manager_->StopCrdClient(base::DoNothing());
+  remoting_client_manager_->StopCrdClient(std::move(on_stopped_callback));
 }
 
 std::string BocaSessionManager::GetDeviceRobotEmail() {
diff --git a/chromeos/ash/components/boca/boca_session_manager.h b/chromeos/ash/components/boca/boca_session_manager.h
index 640d5bf1..c8ee747 100644
--- a/chromeos/ash/components/boca/boca_session_manager.h
+++ b/chromeos/ash/components/boca/boca_session_manager.h
@@ -246,7 +246,7 @@
 
   // Calls the `SpotlightRemotingClientManager` to try and stop an existing
   // session and then free up any remaining resources.
-  void EndSpotlightSession();
+  virtual void EndSpotlightSession(base::OnceClosure on_stopped_callback);
 
   virtual std::string GetDeviceRobotEmail();
 
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 11602a7..94956cd 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -293,6 +293,9 @@
 BASE_FEATURE(kWebAppManifestProtocolHandlerSupport,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Controls whether Vids is preinstalled.
+BASE_FEATURE(kVidsAppPreinstall, base::FEATURE_ENABLED_BY_DEFAULT);
+
 bool IsBatteryBadgeIconEnabled() {
   return base::FeatureList::IsEnabled(kBatteryBadgeIcon);
 }
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 05a9790..021e4b9 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -124,6 +124,8 @@
 BASE_DECLARE_FEATURE(kNotebookLmAppShelfPinReset);
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 BASE_DECLARE_FEATURE(kWebAppManifestProtocolHandlerSupport);
+COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
+BASE_DECLARE_FEATURE(kVidsAppPreinstall);
 
 // Keep alphabetized.
 
diff --git a/chromeos/crosapi/mojom/vpn_service.mojom b/chromeos/crosapi/mojom/vpn_service.mojom
index 825f3bd..b44397f 100644
--- a/chromeos/crosapi/mojom/vpn_service.mojom
+++ b/chromeos/crosapi/mojom/vpn_service.mojom
@@ -70,29 +70,11 @@
   DestroyConfiguration@1(string configuration_name)
       => (VpnErrorResponse? error);
 
-  // Set |parameters| for the active VPN configuration after verifying that it
-  // belongs to the extension.
-  // See chrome.vpnProvider.setParameters(...)
-  // We use mojo_base.mojom.DictionaryValue as the type because:
-  // * The shill counterpart is stable and expects base::Value with type=dict.
-  // * Both the supplier and consumer of this information uses a type
-  //   interchangeable with mojo_base.mojom.DictionaryValue. While we could add
-  //   a translation layer to a strongly typed mojom struct, this adds an
-  //   overhead and the potential for errors with no benefit.
-  SetParameters@2(mojo_base.mojom.DictionaryValue parameters)
-      => (VpnErrorResponse? error);
+  // SetParameters@2 was removed.
 
-  // Sends an IP packet contained in |data| to the active VPN configuration
-  // after verifying that it belongs to the extension.
-  // See chrome.vpnProvider.sendPacket(...)
-  SendPacket@3(array<uint8> data)
-      => (VpnErrorResponse? error);
+  // SendPacket@3 was removed.
 
-  // Notifies new connection state to the active VPN configuration after
-  // verifying that it belongs to the extension.
-  // See chrome.vpnProvider.notifyConnectionStateChanged(...)
-  NotifyConnectionStateChanged@4(bool connection_success)
-      => (VpnErrorResponse? error);
+  // NotifyConnectionStateChanged@4 was removed.
 
   // Binds |pepper_vpn_proxy_observer| to the active configuration if it belongs
   // to the extension and has name equal to
diff --git a/clank b/clank
index e77b8ef..e1b431c 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit e77b8efbb4d973044f6b8d448e2c578c0900db51
+Subproject commit e1b431c9a8ec43eb47ae9e1bca1e1bfe86ee5445
diff --git a/components/autofill/core/browser/data_model/transliterator.cc b/components/autofill/core/browser/data_model/transliterator.cc
index 6f08b6d..a6abfcab 100644
--- a/components/autofill/core/browser/data_model/transliterator.cc
+++ b/components/autofill/core/browser/data_model/transliterator.cc
@@ -13,6 +13,7 @@
 #include "base/i18n/unicodestring.h"
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
+#include "base/strings/strcat.h"
 #include "base/strings/string_util.h"
 #include "components/autofill/core/browser/country_type.h"
 #include "components/autofill/core/browser/data_model/addresses/address.h"
@@ -54,9 +55,29 @@
 
 std::unique_ptr<base::i18n::Transliterator> CreateTransliterator(
     TransliterationId id) {
-  std::string transliteration_rules;
   std::unique_ptr<base::i18n::Transliterator> transliterator;
 
+  // Apply a simplified version of the "::de-ASCII" transliteration, which
+  // follows DIN 5007-2 ("ö" becomes "oe"). Here we map everything to lower case
+  // because that happens with "::Lower" anyway.
+  constexpr std::string_view kGermanRules =
+      "[ö {o \u0308} Ö {O \u0308}] → oe;"
+      "[ä {a \u0308} Ä {A \u0308}] → ae;"
+      "[ü {u \u0308} Ü {U \u0308}] → ue;";
+
+  // The following rules are happening in the following order:
+  // First there are `TransliterationId::kGerman` specific rules if they are
+  // present, then
+  // "::NFD;" performs a decomposition and normalization. (â becomes a and Ì‚)
+  // "::[:Nonspacing Mark:] Remove;" removes the " Ì‚"
+  // "::Lower;" converts the result to lower case
+  // "::NFC;" re-composes the decomposed characters
+  // "::Latin-ASCII;" converts various other Latin characters to an ASCII
+  //   representation (e.g. "Å‚", which does not get decomposed, to "l"; "ß"
+  //   to "ss").
+  constexpr std::string_view kDefaultRules =
+      "::NFD; ::[:Nonspacing Mark:] Remove; ::Lower; ::NFC; ::Latin-ASCII;";
+
   switch (id) {
     case TransliterationId::kKatakanaToHiragana:
       transliterator = base::i18n::CreateTransliterator("Katakana-Hiragana");
@@ -65,30 +86,12 @@
       transliterator = base::i18n::CreateTransliterator("Hiragana-Katakana");
       break;
     case TransliterationId::kGerman:
-      // Apply a simplified version of the "::de-ASCII" transliteration, which
-      // follows DIN 5007-2 ("ö" becomes "oe"). Here we map everything to
-      // lower case because that happens with "::Lower" anyway.
-      transliteration_rules =
-          "[ö {o \u0308} Ö {O \u0308}] → oe;"
-          "[ä {a \u0308} Ä {A \u0308}] → ae;"
-          "[ü {u \u0308} Ü {U \u0308}] → ue;";
-      [[fallthrough]];
-    case TransliterationId::kDefault:
-      // These rules are happening in the following order:
-      // First there are `TransliterationId::kGerman` specific rules if they are
-      // present, then
-      // "::NFD;" performs a decomposition and normalization.
-      // (â becomes a and Ì‚)
-      // "::[:Nonspacing Mark:] Remove;" removes the " Ì‚"
-      // "::Lower;" converts the result to lower case
-      // "::NFC;" re-composes the decomposed characters
-      // "::Latin-ASCII;" converts various other Latin characters to an ASCII
-      //   representation (e.g. "Å‚", which does not get decomposed, to "l"; "ß"
-      //   to "ss").
-      transliteration_rules +=
-          "::NFD; ::[:Nonspacing Mark:] Remove; ::Lower; ::NFC; ::Latin-ASCII;";
       transliterator = base::i18n::CreateTransliteratorFromRules(
-          "NormalizeForAddresses", transliteration_rules);
+          "DE_NormalizForAddress", base::StrCat({kGermanRules, kDefaultRules}));
+      break;
+    case TransliterationId::kDefault:
+      transliterator = base::i18n::CreateTransliteratorFromRules(
+          "NormalizeForAddress", kDefaultRules);
       break;
   }
 
diff --git a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
index 2beb3ee..8fd9f6ea 100644
--- a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator.cc
@@ -1266,9 +1266,9 @@
       switch (id) {
         case BnplIssuer::IssuerId::kBnplAffirm:
           return 4;
-        case BnplIssuer::IssuerId::kBnplZip:
-          return 3;
         case BnplIssuer::IssuerId::kBnplKlarna:
+          return 3;
+        case BnplIssuer::IssuerId::kBnplZip:
           return 2;
         case BnplIssuer::IssuerId::kBnplAfterpay:
           NOTREACHED();
diff --git a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
index 7dd34ce..c8a1478 100644
--- a/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
+++ b/components/autofill/core/browser/suggestions/payments/payments_suggestion_generator_unittest.cc
@@ -2194,10 +2194,10 @@
           /*labels=*/
           {{Suggestion::Text(l10n_util::GetStringFUTF16(
               IDS_AUTOFILL_BNPL_CREDIT_CARD_SUGGESTION_LABEL_THREE_ISSUERS,
-              // Affirm comes before Zip, and Zip comes before Klarna.
+              // Affirm comes before Klarna, and Klarna comes before Zip.
               bnpl_issuers[2].GetDisplayName(),
-              bnpl_issuers[1].GetDisplayName(),
-              bnpl_issuers[0].GetDisplayName()))}}));
+              bnpl_issuers[0].GetDisplayName(),
+              bnpl_issuers[1].GetDisplayName()))}}));
 }
 
 TEST_F(PaymentsSuggestionGeneratorTest, CreateBnplSuggestion_FlagDisabled) {
diff --git a/components/cast_receiver/renderer/public/content_renderer_client_mixins.h b/components/cast_receiver/renderer/public/content_renderer_client_mixins.h
index 2d8d796..d08d440b 100644
--- a/components/cast_receiver/renderer/public/content_renderer_client_mixins.h
+++ b/components/cast_receiver/renderer/public/content_renderer_client_mixins.h
@@ -9,10 +9,7 @@
 #include <string_view>
 
 #include "base/functional/callback_forward.h"
-
-namespace blink {
-class URLLoaderThrottleProvider;
-}  // namespace blink
+#include "third_party/blink/public/platform/url_loader_throttle_provider.h"
 
 namespace content {
 class RenderFrame;
diff --git a/components/component_updater/android/loader_policies/tpcd_metadata_component_loader_policy.cc b/components/component_updater/android/loader_policies/tpcd_metadata_component_loader_policy.cc
index 216245bb9..9a5929f 100644
--- a/components/component_updater/android/loader_policies/tpcd_metadata_component_loader_policy.cc
+++ b/components/component_updater/android/loader_policies/tpcd_metadata_component_loader_policy.cc
@@ -31,7 +31,7 @@
                                &raw_tpcd_metadata)) {
     return raw_tpcd_metadata;
   }
-  return nullptr;
+  return std::nullopt;
 }
 
 }  // namespace
diff --git a/components/cronet/android/cronet_bidirectional_stream_adapter.cc b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
index 41d95037..fb665d60 100644
--- a/components/cronet/android/cronet_bidirectional_stream_adapter.cc
+++ b/components/cronet/android/cronet_bidirectional_stream_adapter.cc
@@ -67,7 +67,7 @@
 }  // namespace
 
 CronetMetrics::CronetMetrics() = default;
-CronetMetrics::CronetMetrics(CronetMetrics& metrics) = default;
+CronetMetrics::CronetMetrics(const CronetMetrics& metrics) = default;
 CronetMetrics::~CronetMetrics() = default;
 
 PendingWriteData::PendingWriteData(
diff --git a/components/cronet/android/cronet_bidirectional_stream_adapter.h b/components/cronet/android/cronet_bidirectional_stream_adapter.h
index d8e50f3..04a43e8 100644
--- a/components/cronet/android/cronet_bidirectional_stream_adapter.h
+++ b/components/cronet/android/cronet_bidirectional_stream_adapter.h
@@ -43,7 +43,7 @@
   // not giving us a choice.
   // https://www.chromium.org/developers/coding-style/chromium-style-checker-errors/#constructordestructor-errors
   CronetMetrics();
-  CronetMetrics(CronetMetrics& metrics);
+  CronetMetrics(const CronetMetrics& metrics);
   ~CronetMetrics();
 };
 
diff --git a/components/cronet/native/engine.cc b/components/cronet/native/engine.cc
index 8df83fd0..7efc1f67 100644
--- a/components/cronet/native/engine.cc
+++ b/components/cronet/native/engine.cc
@@ -93,6 +93,132 @@
 
 namespace cronet {
 
+// The struct stream_engine for grpc support.
+// Holds net::URLRequestContextGetter and app-specific annotation.
+class Cronet_EngineImpl::StreamEngineImpl : public stream_engine {
+ public:
+  explicit StreamEngineImpl(net::URLRequestContextGetter* context_getter) {
+    context_getter_ = context_getter;
+    obj = context_getter_.get();
+    annotation = nullptr;
+  }
+
+  ~StreamEngineImpl() {
+    obj = nullptr;
+    annotation = nullptr;
+  }
+
+ private:
+  scoped_refptr<net::URLRequestContextGetter> context_getter_;
+};
+
+// Callback is owned by CronetContext. It is invoked and deleted
+// on the network thread.
+class Cronet_EngineImpl::Callback : public CronetContext::Callback {
+ public:
+  explicit Callback(Cronet_EngineImpl* engine);
+
+  Callback(const Callback&) = delete;
+  Callback& operator=(const Callback&) = delete;
+
+  ~Callback() override;
+
+  // CronetContext::Callback implementation:
+  void OnInitNetworkThread() override LOCKS_EXCLUDED(engine_->lock_);
+  void OnDestroyNetworkThread() override;
+  void OnEffectiveConnectionTypeChanged(
+      net::EffectiveConnectionType effective_connection_type) override;
+  void OnRTTOrThroughputEstimatesComputed(
+      int32_t http_rtt_ms,
+      int32_t transport_rtt_ms,
+      int32_t downstream_throughput_kbps) override;
+  void OnRTTObservation(int32_t rtt_ms,
+                        int32_t timestamp_ms,
+                        net::NetworkQualityObservationSource source) override;
+  void OnThroughputObservation(
+      int32_t throughput_kbps,
+      int32_t timestamp_ms,
+      net::NetworkQualityObservationSource source) override;
+  void OnStopNetLogCompleted() override LOCKS_EXCLUDED(engine_->lock_);
+  void OnBeforeTunnelRequest(
+      int chain_id,
+      net::ProxyDelegate::OnBeforeTunnelRequestCallback callback) override {
+    NOTREACHED();
+  }
+  void OnTunnelHeadersReceived(int chain_id,
+                               const net::HttpResponseHeaders& response_headers,
+                               net::CompletionOnceCallback callback) override {
+    NOTREACHED();
+  }
+
+ private:
+  // The engine which owns context that owns |this| callback.
+  const raw_ptr<Cronet_EngineImpl> engine_;
+
+  // All methods are invoked on the network thread.
+  THREAD_CHECKER(network_thread_checker_);
+};
+
+Cronet_EngineImpl::Callback::Callback(Cronet_EngineImpl* engine)
+    : engine_(engine) {
+  DETACH_FROM_THREAD(network_thread_checker_);
+}
+
+Cronet_EngineImpl::Callback::~Callback() = default;
+
+void Cronet_EngineImpl::Callback::OnInitNetworkThread() {
+  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
+  // It is possible that engine_->context_ is reset from main thread while
+  // being intialized on network thread.
+  base::AutoLock lock(engine_->lock_);
+  if (engine_->context_) {
+    // Initialize bidirectional stream engine for grpc.
+    engine_->stream_engine_ = std::make_unique<StreamEngineImpl>(
+        engine_->context_->CreateURLRequestContextGetter());
+    engine_->init_completed_.Signal();
+  }
+}
+
+void Cronet_EngineImpl::Callback::OnDestroyNetworkThread() {
+  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
+  DCHECK(!engine_->stream_engine_);
+}
+
+void Cronet_EngineImpl::Callback::OnEffectiveConnectionTypeChanged(
+    net::EffectiveConnectionType effective_connection_type) {
+  NOTIMPLEMENTED();
+}
+
+void Cronet_EngineImpl::Callback::OnRTTOrThroughputEstimatesComputed(
+    int32_t http_rtt_ms,
+    int32_t transport_rtt_ms,
+    int32_t downstream_throughput_kbps) {
+  NOTIMPLEMENTED();
+}
+
+void Cronet_EngineImpl::Callback::OnRTTObservation(
+    int32_t rtt_ms,
+    int32_t timestamp_ms,
+    net::NetworkQualityObservationSource source) {
+  NOTIMPLEMENTED();
+}
+
+void Cronet_EngineImpl::Callback::OnThroughputObservation(
+    int32_t throughput_kbps,
+    int32_t timestamp_ms,
+    net::NetworkQualityObservationSource source) {
+  NOTIMPLEMENTED();
+}
+
+void Cronet_EngineImpl::Callback::OnStopNetLogCompleted() {
+  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
+  CHECK(engine_);
+  base::AutoLock lock(engine_->lock_);
+  DCHECK(engine_->is_logging_);
+  engine_->is_logging_ = false;
+  engine_->stop_netlog_completed_.Signal();
+}
+
 Cronet_EngineImpl::Cronet_EngineImpl()
     : init_completed_(base::WaitableEvent::ResetPolicy::MANUAL,
                       base::WaitableEvent::InitialState::NOT_SIGNALED),
@@ -351,132 +477,6 @@
   return request_finished_registrations_.size() > 0;
 }
 
-// The struct stream_engine for grpc support.
-// Holds net::URLRequestContextGetter and app-specific annotation.
-class Cronet_EngineImpl::StreamEngineImpl : public stream_engine {
- public:
-  explicit StreamEngineImpl(net::URLRequestContextGetter* context_getter) {
-    context_getter_ = context_getter;
-    obj = context_getter_.get();
-    annotation = nullptr;
-  }
-
-  ~StreamEngineImpl() {
-    obj = nullptr;
-    annotation = nullptr;
-  }
-
- private:
-  scoped_refptr<net::URLRequestContextGetter> context_getter_;
-};
-
-// Callback is owned by CronetContext. It is invoked and deleted
-// on the network thread.
-class Cronet_EngineImpl::Callback : public CronetContext::Callback {
- public:
-  explicit Callback(Cronet_EngineImpl* engine);
-
-  Callback(const Callback&) = delete;
-  Callback& operator=(const Callback&) = delete;
-
-  ~Callback() override;
-
-  // CronetContext::Callback implementation:
-  void OnInitNetworkThread() override LOCKS_EXCLUDED(engine_->lock_);
-  void OnDestroyNetworkThread() override;
-  void OnEffectiveConnectionTypeChanged(
-      net::EffectiveConnectionType effective_connection_type) override;
-  void OnRTTOrThroughputEstimatesComputed(
-      int32_t http_rtt_ms,
-      int32_t transport_rtt_ms,
-      int32_t downstream_throughput_kbps) override;
-  void OnRTTObservation(int32_t rtt_ms,
-                        int32_t timestamp_ms,
-                        net::NetworkQualityObservationSource source) override;
-  void OnThroughputObservation(
-      int32_t throughput_kbps,
-      int32_t timestamp_ms,
-      net::NetworkQualityObservationSource source) override;
-  void OnStopNetLogCompleted() override LOCKS_EXCLUDED(engine_->lock_);
-  void OnBeforeTunnelRequest(
-      int chain_id,
-      net::ProxyDelegate::OnBeforeTunnelRequestCallback callback) override {
-    NOTREACHED();
-  }
-  void OnTunnelHeadersReceived(int chain_id,
-                               const net::HttpResponseHeaders& response_headers,
-                               net::CompletionOnceCallback callback) override {
-    NOTREACHED();
-  }
-
- private:
-  // The engine which owns context that owns |this| callback.
-  const raw_ptr<Cronet_EngineImpl> engine_;
-
-  // All methods are invoked on the network thread.
-  THREAD_CHECKER(network_thread_checker_);
-};
-
-Cronet_EngineImpl::Callback::Callback(Cronet_EngineImpl* engine)
-    : engine_(engine) {
-  DETACH_FROM_THREAD(network_thread_checker_);
-}
-
-Cronet_EngineImpl::Callback::~Callback() = default;
-
-void Cronet_EngineImpl::Callback::OnInitNetworkThread() {
-  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
-  // It is possible that engine_->context_ is reset from main thread while
-  // being intialized on network thread.
-  base::AutoLock lock(engine_->lock_);
-  if (engine_->context_) {
-    // Initialize bidirectional stream engine for grpc.
-    engine_->stream_engine_ = std::make_unique<StreamEngineImpl>(
-        engine_->context_->CreateURLRequestContextGetter());
-    engine_->init_completed_.Signal();
-  }
-}
-
-void Cronet_EngineImpl::Callback::OnDestroyNetworkThread() {
-  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
-  DCHECK(!engine_->stream_engine_);
-}
-
-void Cronet_EngineImpl::Callback::OnEffectiveConnectionTypeChanged(
-    net::EffectiveConnectionType effective_connection_type) {
-  NOTIMPLEMENTED();
-}
-
-void Cronet_EngineImpl::Callback::OnRTTOrThroughputEstimatesComputed(
-    int32_t http_rtt_ms,
-    int32_t transport_rtt_ms,
-    int32_t downstream_throughput_kbps) {
-  NOTIMPLEMENTED();
-}
-
-void Cronet_EngineImpl::Callback::OnRTTObservation(
-    int32_t rtt_ms,
-    int32_t timestamp_ms,
-    net::NetworkQualityObservationSource source) {
-  NOTIMPLEMENTED();
-}
-
-void Cronet_EngineImpl::Callback::OnThroughputObservation(
-    int32_t throughput_kbps,
-    int32_t timestamp_ms,
-    net::NetworkQualityObservationSource source) {
-  NOTIMPLEMENTED();
-}
-
-void Cronet_EngineImpl::Callback::OnStopNetLogCompleted() {
-  DCHECK_CALLED_ON_VALID_THREAD(network_thread_checker_);
-  CHECK(engine_);
-  base::AutoLock lock(engine_->lock_);
-  DCHECK(engine_->is_logging_);
-  engine_->is_logging_ = false;
-  engine_->stop_netlog_completed_.Signal();
-}
-
 void Cronet_EngineImpl::SetMockCertVerifierForTesting(
     std::unique_ptr<net::CertVerifier> mock_cert_verifier) {
   CHECK(!context_);
diff --git a/components/data_sharing/BUILD.gn b/components/data_sharing/BUILD.gn
index 7b83164..f9329a6c 100644
--- a/components/data_sharing/BUILD.gn
+++ b/components/data_sharing/BUILD.gn
@@ -15,6 +15,7 @@
 
   deps = [
     "//components/data_sharing/internal:unit_tests",
+    "//components/data_sharing/migration/internal:unit_tests",
     "//components/data_sharing/public:unit_tests",
   ]
 
diff --git a/components/data_sharing/migration/internal/BUILD.gn b/components/data_sharing/migration/internal/BUILD.gn
index 3d7aff7..0d35c064 100644
--- a/components/data_sharing/migration/internal/BUILD.gn
+++ b/components/data_sharing/migration/internal/BUILD.gn
@@ -9,11 +9,31 @@
 }
 
 source_set("internal") {
+  defines = [ "IS_DATA_SHARING_MIGRATION_IMPL=1" ]
+
   sources = [
     "base_migratable_sync_service.cc",
     "migratable_sync_service_coordinator_impl.cc",
     "migratable_sync_service_coordinator_impl.h",
+    "migration_state_database.h",
+    "migration_state_database_impl.cc",
+    "migration_state_database_impl.h",
   ]
 
-  deps = [ "//components/data_sharing/migration/public" ]
+  deps = [
+    ":migration_state_proto",
+    "//base",
+    "//components/data_sharing/public",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "migration_state_database_impl_unittest.cc" ]
+  deps = [
+    ":internal",
+    "//base",
+    "//base/test:test_support",
+    "//testing/gtest",
+  ]
 }
diff --git a/components/data_sharing/migration/internal/migration_state_database.h b/components/data_sharing/migration/internal/migration_state_database.h
new file mode 100644
index 0000000..5b2453c1
--- /dev/null
+++ b/components/data_sharing/migration/internal/migration_state_database.h
@@ -0,0 +1,49 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_H_
+#define COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_H_
+
+#include <optional>
+
+#include "base/files/file_path.h"
+#include "base/functional/callback_forward.h"
+#include "components/data_sharing/migration/internal/protocol/migration_state.pb.h"
+#include "components/data_sharing/migration/public/context_id.h"
+
+namespace data_sharing {
+
+// A SQLite database for storing data_sharing migration state. This database
+// stores a proto for each sync entity, keyed by the context id.
+class MigrationStateDatabase {
+ public:
+  // Callback for when the database has been initialized. The boolean argument
+  // indicates success or failure.
+  using InitCallback = base::OnceCallback<void(bool)>;
+
+  virtual ~MigrationStateDatabase() = default;
+
+  // Initializes the database at the given `db_path`. Must be called before any
+  // other methods.
+  virtual void Init(InitCallback callback) = 0;
+
+  // Synchronously retrieves the migration state for a given `context_id`.
+  // Returns std::nullopt if the entry is not found. Must be called after Init()
+  // has completed successfully.
+  virtual std::optional<data_sharing_pb::MigrationState> GetMigrationState(
+      const ContextId& context_id) const = 0;
+
+  // Synchronously adds or updates the migration state for a given
+  // `context_id`. The database will write to disk asynchronously after.
+  virtual void UpdateMigrationState(
+      const ContextId& context_id,
+      const data_sharing_pb::MigrationState& state) = 0;
+
+  // Synchronously deletes the migration state for a given `context_id`.
+  virtual void DeleteMigrationState(const ContextId& context_id) = 0;
+};
+
+}  // namespace data_sharing
+
+#endif  // COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_H_
diff --git a/components/data_sharing/migration/internal/migration_state_database_impl.cc b/components/data_sharing/migration/internal/migration_state_database_impl.cc
new file mode 100644
index 0000000..70dc7f6
--- /dev/null
+++ b/components/data_sharing/migration/internal/migration_state_database_impl.cc
@@ -0,0 +1,45 @@
+// Copyright 2025 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/data_sharing/migration/internal/migration_state_database_impl.h"
+
+namespace data_sharing {
+
+MigrationStateDatabaseImpl::MigrationStateDatabaseImpl(
+    const base::FilePath& profile_dir) {
+  // TODO(haileywang): Implement this.
+}
+
+MigrationStateDatabaseImpl::~MigrationStateDatabaseImpl() = default;
+
+void MigrationStateDatabaseImpl::Init(InitCallback callback) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(haileywang): Implement this.
+  is_initialized_ = true;
+  std::move(callback).Run(false);
+}
+
+std::optional<data_sharing_pb::MigrationState>
+MigrationStateDatabaseImpl::GetMigrationState(
+    const ContextId& context_id) const {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  CHECK(is_initialized_);
+  // TODO(haileywang): Implement this.
+  return std::nullopt;
+}
+
+void MigrationStateDatabaseImpl::UpdateMigrationState(
+    const ContextId& context_id,
+    const data_sharing_pb::MigrationState& state) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(haileywang): Implement this.
+}
+
+void MigrationStateDatabaseImpl::DeleteMigrationState(
+    const ContextId& context_id) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  // TODO(haileywang): Implement this.
+}
+
+}  // namespace data_sharing
diff --git a/components/data_sharing/migration/internal/migration_state_database_impl.h b/components/data_sharing/migration/internal/migration_state_database_impl.h
new file mode 100644
index 0000000..1564046
--- /dev/null
+++ b/components/data_sharing/migration/internal/migration_state_database_impl.h
@@ -0,0 +1,56 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_IMPL_H_
+#define COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_IMPL_H_
+
+#include <map>
+#include <memory>
+#include <string>
+
+#include "base/files/file_path.h"
+#include "base/memory/weak_ptr.h"
+#include "base/sequence_checker.h"
+#include "base/task/sequenced_task_runner.h"
+#include "components/data_sharing/migration/internal/migration_state_database.h"
+#include "components/data_sharing/migration/internal/protocol/migration_state.pb.h"
+#include "components/data_sharing/migration/public/context_id.h"
+
+namespace data_sharing {
+
+// A SQLite database for storing data_sharing migration state. This database
+// stores a proto for each sync entity, keyed by the context id. The data is
+// cached in memory for synchronous reads.
+class MigrationStateDatabaseImpl : public MigrationStateDatabase {
+ public:
+  explicit MigrationStateDatabaseImpl(const base::FilePath& profile_dir);
+  ~MigrationStateDatabaseImpl() override;
+  MigrationStateDatabaseImpl(const MigrationStateDatabaseImpl&) = delete;
+  MigrationStateDatabaseImpl& operator=(const MigrationStateDatabaseImpl&) =
+      delete;
+
+  // MigrationStateDatabase implementation.
+  void Init(InitCallback callback) override;
+  std::optional<data_sharing_pb::MigrationState> GetMigrationState(
+      const ContextId& context_id) const override;
+  void UpdateMigrationState(
+      const ContextId& context_id,
+      const data_sharing_pb::MigrationState& state) override;
+  void DeleteMigrationState(const ContextId& context_id) override;
+
+ private:
+  // In-memory cache of the migration state.
+  std::map<ContextId, data_sharing_pb::MigrationState> cache_;
+
+  // Whether database is initialized.
+  bool is_initialized_ = false;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+
+  base::WeakPtrFactory<MigrationStateDatabaseImpl> weak_ptr_factory_{this};
+};
+
+}  // namespace data_sharing
+
+#endif  // COMPONENTS_DATA_SHARING_MIGRATION_INTERNAL_MIGRATION_STATE_DATABASE_IMPL_H_
diff --git a/components/data_sharing/migration/internal/migration_state_database_impl_unittest.cc b/components/data_sharing/migration/internal/migration_state_database_impl_unittest.cc
new file mode 100644
index 0000000..e1ff8c0
--- /dev/null
+++ b/components/data_sharing/migration/internal/migration_state_database_impl_unittest.cc
@@ -0,0 +1,25 @@
+// Copyright 2025 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/data_sharing/migration/internal/migration_state_database_impl.h"
+
+#include "base/test/task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace data_sharing {
+
+class MigrationStateDatabaseImplTest : public testing::Test {
+ public:
+  MigrationStateDatabaseImplTest() = default;
+  ~MigrationStateDatabaseImplTest() override = default;
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(MigrationStateDatabaseImplTest, ShouldDoNothing) {
+  // TODO(haileywang): Implement this.
+}
+
+}  // namespace data_sharing
diff --git a/components/exo/surface_tree_host_unittest.cc b/components/exo/surface_tree_host_unittest.cc
index f40fbbb..0caab52 100644
--- a/components/exo/surface_tree_host_unittest.cc
+++ b/components/exo/surface_tree_host_unittest.cc
@@ -334,10 +334,6 @@
     return nullptr;
   }
   gpu::ContextSupport* ContextSupport() override { return nullptr; }
-  class GrDirectContext* GrContext() override {
-    ADD_FAILURE();
-    return nullptr;
-  }
   gpu::SharedImageInterface* SharedImageInterface() override {
     ADD_FAILURE();
     return nullptr;
diff --git a/components/os_crypt/async/browser/BUILD.gn b/components/os_crypt/async/browser/BUILD.gn
index 45836a6..9c18006 100644
--- a/components/os_crypt/async/browser/BUILD.gn
+++ b/components/os_crypt/async/browser/BUILD.gn
@@ -78,6 +78,20 @@
   }
 }
 
+if (is_posix && !is_apple) {
+  source_set("posix_key_provider") {
+    sources = [
+      "posix_key_provider.cc",
+      "posix_key_provider.h",
+    ]
+    deps = [
+      ":key_provider_interface",
+      "//base",
+      "//components/os_crypt/async/common",
+    ]
+  }
+}
+
 if (is_linux && use_dbus) {
   source_set("secret_portal_key_provider") {
     sources = [
@@ -99,14 +113,13 @@
 
   source_set("freedesktop_secret_key_provider") {
     sources = [
-      "fallback_linux_key_provider.cc",
-      "fallback_linux_key_provider.h",
       "freedesktop_secret_key_provider.cc",
       "freedesktop_secret_key_provider.h",
     ]
 
     deps = [
       ":key_provider_interface",
+      ":posix_key_provider",
       "//base",
       "//components/dbus",
       "//components/os_crypt/async/common",
@@ -182,6 +195,7 @@
     ]
     deps += [
       ":freedesktop_secret_key_provider",
+      ":posix_key_provider",
       ":secret_portal_key_provider",
       "//components/dbus",
       "//components/prefs:test_support",
diff --git a/components/os_crypt/async/browser/fallback_linux_key_provider.h b/components/os_crypt/async/browser/fallback_linux_key_provider.h
deleted file mode 100644
index eed0cb59..0000000
--- a/components/os_crypt/async/browser/fallback_linux_key_provider.h
+++ /dev/null
@@ -1,32 +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.
-
-#ifndef COMPONENTS_OS_CRYPT_ASYNC_BROWSER_FALLBACK_LINUX_KEY_PROVIDER_H_
-#define COMPONENTS_OS_CRYPT_ASYNC_BROWSER_FALLBACK_LINUX_KEY_PROVIDER_H_
-
-#include "components/os_crypt/async/browser/key_provider.h"
-
-namespace os_crypt_async {
-
-class FallbackLinuxKeyProvider : public KeyProvider {
- public:
-  explicit FallbackLinuxKeyProvider(bool use_for_encryption);
-
-  FallbackLinuxKeyProvider(const FallbackLinuxKeyProvider&) = delete;
-  FallbackLinuxKeyProvider& operator=(const FallbackLinuxKeyProvider&) = delete;
-
-  ~FallbackLinuxKeyProvider() override;
-
-  // KeyProvider:
-  void GetKey(KeyCallback callback) override;
-  bool UseForEncryption() override;
-  bool IsCompatibleWithOsCryptSync() override;
-
- private:
-  const bool use_for_encryption_;
-};
-
-}  // namespace os_crypt_async
-
-#endif  // COMPONENTS_OS_CRYPT_ASYNC_BROWSER_FALLBACK_LINUX_KEY_PROVIDER_H_
diff --git a/components/os_crypt/async/browser/freedesktop_secret_key_provider.cc b/components/os_crypt/async/browser/freedesktop_secret_key_provider.cc
index 58a9065..3f287a5 100644
--- a/components/os_crypt/async/browser/freedesktop_secret_key_provider.cc
+++ b/components/os_crypt/async/browser/freedesktop_secret_key_provider.cc
@@ -275,7 +275,7 @@
   default_collection_proxy_ = nullptr;
 
   if (password_store_ == "basic") {
-    // Use FallbackLinuxKeyProvider.
+    // Use PosixKeyProvider.
     FinalizeFailure(InitStatus::kDisabled, ErrorDetail::kNone);
   } else if (password_store_ == "gnome-libsecret") {
     InitializeFreedesktopSecretService();
diff --git a/components/os_crypt/async/browser/freedesktop_secret_key_provider_compat_unittest.cc b/components/os_crypt/async/browser/freedesktop_secret_key_provider_compat_unittest.cc
index d21aeb3..8a865866 100644
--- a/components/os_crypt/async/browser/freedesktop_secret_key_provider_compat_unittest.cc
+++ b/components/os_crypt/async/browser/freedesktop_secret_key_provider_compat_unittest.cc
@@ -13,9 +13,9 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_future.h"
-#include "components/os_crypt/async/browser/fallback_linux_key_provider.h"
 #include "components/os_crypt/async/browser/freedesktop_secret_key_provider.h"
 #include "components/os_crypt/async/browser/os_crypt_async.h"
+#include "components/os_crypt/async/browser/posix_key_provider.h"
 #include "components/os_crypt/sync/key_storage_linux.h"
 #include "components/os_crypt/sync/os_crypt.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -59,7 +59,7 @@
       provider->secret_for_testing_ = kSecretKey;
       providers.emplace_back(0, std::move(provider));
     } else {
-      providers.emplace_back(0, std::make_unique<FallbackLinuxKeyProvider>(
+      providers.emplace_back(0, std::make_unique<PosixKeyProvider>(
                                     /*use_for_encryption=*/true));
     }
     OSCryptAsync factory(std::move(providers));
diff --git a/components/os_crypt/async/browser/fallback_linux_key_provider.cc b/components/os_crypt/async/browser/posix_key_provider.cc
similarity index 66%
rename from components/os_crypt/async/browser/fallback_linux_key_provider.cc
rename to components/os_crypt/async/browser/posix_key_provider.cc
index 5f7cda1..7c4eff9 100644
--- a/components/os_crypt/async/browser/fallback_linux_key_provider.cc
+++ b/components/os_crypt/async/browser/posix_key_provider.cc
@@ -1,8 +1,8 @@
-// Copyright 2024 The Chromium Authors
+// Copyright 2025 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/os_crypt/async/browser/fallback_linux_key_provider.h"
+#include "components/os_crypt/async/browser/posix_key_provider.h"
 
 #include <array>
 #include <utility>
@@ -23,22 +23,26 @@
 
 }  // namespace
 
-FallbackLinuxKeyProvider::FallbackLinuxKeyProvider(bool use_for_encryption)
+PosixKeyProvider::PosixKeyProvider(bool use_for_encryption)
     : use_for_encryption_(use_for_encryption) {}
 
-FallbackLinuxKeyProvider::~FallbackLinuxKeyProvider() = default;
+PosixKeyProvider::~PosixKeyProvider() = default;
 
-void FallbackLinuxKeyProvider::GetKey(KeyCallback callback) {
+void PosixKeyProvider::GetKey(KeyCallback callback) {
   Encryptor::Key key(kV10Key, mojom::Algorithm::kAES128CBC);
   std::move(callback).Run(kEncryptionTag, std::move(key));
 }
 
-bool FallbackLinuxKeyProvider::UseForEncryption() {
+bool PosixKeyProvider::UseForEncryption() {
   return use_for_encryption_;
 }
 
-bool FallbackLinuxKeyProvider::IsCompatibleWithOsCryptSync() {
+bool PosixKeyProvider::IsCompatibleWithOsCryptSync() {
+#if BUILDFLAG(IS_LINUX)
   return false;
+#else
+  return true;
+#endif
 }
 
 }  // namespace os_crypt_async
diff --git a/components/os_crypt/async/browser/posix_key_provider.h b/components/os_crypt/async/browser/posix_key_provider.h
new file mode 100644
index 0000000..a35b10f
--- /dev/null
+++ b/components/os_crypt/async/browser/posix_key_provider.h
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_OS_CRYPT_ASYNC_BROWSER_POSIX_KEY_PROVIDER_H_
+#define COMPONENTS_OS_CRYPT_ASYNC_BROWSER_POSIX_KEY_PROVIDER_H_
+
+#include "components/os_crypt/async/browser/key_provider.h"
+
+namespace os_crypt_async {
+
+class PosixKeyProvider : public KeyProvider {
+ public:
+  explicit PosixKeyProvider(bool use_for_encryption);
+
+  PosixKeyProvider(const PosixKeyProvider&) = delete;
+  PosixKeyProvider& operator=(const PosixKeyProvider&) = delete;
+
+  ~PosixKeyProvider() override;
+
+  // KeyProvider:
+  void GetKey(KeyCallback callback) override;
+  bool UseForEncryption() override;
+  bool IsCompatibleWithOsCryptSync() override;
+
+ private:
+  const bool use_for_encryption_;
+};
+
+}  // namespace os_crypt_async
+
+#endif  // COMPONENTS_OS_CRYPT_ASYNC_BROWSER_POSIX_KEY_PROVIDER_H_
diff --git a/components/page_content_annotations/core/page_content_annotations_service.cc b/components/page_content_annotations/core/page_content_annotations_service.cc
index 58dee3f8..f878db9 100644
--- a/components/page_content_annotations/core/page_content_annotations_service.cc
+++ b/components/page_content_annotations/core/page_content_annotations_service.cc
@@ -519,7 +519,7 @@
 
   MaybeRecordVisibilityUKM(visit, content_annotations);
   NotifyPageContentAnnotatedObservers(
-      AnnotationType::kContentVisibility, visit.url,
+      AnnotationType::kContentVisibility, visit,
       PageContentAnnotationsResult::CreateContentVisibilityScoreResult(
           content_annotations->visibility_score));
 
@@ -887,14 +887,14 @@
 
 void PageContentAnnotationsService::NotifyPageContentAnnotatedObservers(
     AnnotationType annotation_type,
-    const GURL& url,
+    const HistoryVisit& visit,
     const PageContentAnnotationsResult& page_content_annotations_result) {
   if (page_content_annotations_observers_.find(annotation_type) ==
       page_content_annotations_observers_.end()) {
     return;
   }
   for (auto& observer : page_content_annotations_observers_[annotation_type]) {
-    observer.OnPageContentAnnotated(url, page_content_annotations_result);
+    observer.OnPageContentAnnotated(visit, page_content_annotations_result);
   }
 }
 
diff --git a/components/page_content_annotations/core/page_content_annotations_service.h b/components/page_content_annotations/core/page_content_annotations_service.h
index 58b6f05e..2cea359 100644
--- a/components/page_content_annotations/core/page_content_annotations_service.h
+++ b/components/page_content_annotations/core/page_content_annotations_service.h
@@ -135,7 +135,7 @@
   class PageContentAnnotationsObserver : public base::CheckedObserver {
    public:
     virtual void OnPageContentAnnotated(
-        const GURL& url,
+        const HistoryVisit& visit,
         const PageContentAnnotationsResult& result) = 0;
   };
 
@@ -333,7 +333,7 @@
   // |annotation_type|.
   void NotifyPageContentAnnotatedObservers(
       AnnotationType annotation_type,
-      const GURL& url,
+      const page_content_annotations::HistoryVisit& visit,
       const PageContentAnnotationsResult& page_content_annotations_result);
 
   // Callback invoked when a response for |optimization_type| has been received
diff --git a/components/page_content_annotations/core/page_content_cache_handler.h b/components/page_content_annotations/core/page_content_cache_handler.h
index fafc7832..9aaf2fb 100644
--- a/components/page_content_annotations/core/page_content_cache_handler.h
+++ b/components/page_content_annotations/core/page_content_cache_handler.h
@@ -58,7 +58,7 @@
   PageContentCache* page_content_cache() { return page_content_cache_.get(); }
 
  private:
-  std::unique_ptr<PageContentCache> page_content_cache_;
+  const std::unique_ptr<PageContentCache> page_content_cache_;
 };
 
 }  // namespace page_content_annotations
diff --git a/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.cc b/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.cc
index 779035adc..9bd01bd 100644
--- a/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.cc
@@ -27,6 +27,7 @@
 const char kGwsHeadChunkEndMarkName[] = "SearchHeadEnd";
 const char kGwsBodyChunkStartMarkName[] = "SearchBodyStart";
 const char kGwsBodyChunkEndMarkName[] = "SearchBodyEnd";
+const char kGwsSGLMarkName[] = "SearchSGL";
 
 }  // namespace internal
 
diff --git a/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.h b/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.h
index 5c351b1..bbec7ec 100644
--- a/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.h
+++ b/components/page_load_metrics/google/browser/gws_abandoned_page_load_metrics_observer.h
@@ -20,6 +20,7 @@
 extern const char kGwsHeadChunkEndMarkName[];
 extern const char kGwsBodyChunkStartMarkName[];
 extern const char kGwsBodyChunkEndMarkName[];
+extern const char kGwsSGLMarkName[];
 }  // namespace internal
 
 // Observes and records UMA for navigations to GWS which might or might get
diff --git a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
index 02a8fca..7f7fc5b7 100644
--- a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
@@ -81,6 +81,8 @@
     HISTOGRAM_PREFIX "ConnectTiming.FinalRequestSslDelay";
 
 const char kHistogramGWSAFTEnd[] = HISTOGRAM_PREFIX "PaintTiming.AFTEnd2";
+const char kHistogramGWSAFTEndWithPreNavigationLatency[] =
+    HISTOGRAM_PREFIX "PaintTiming.AFTEndWithPreNavigationLatency";
 const char kHistogramGWSAFTStart[] = HISTOGRAM_PREFIX "PaintTiming.AFTStart2";
 const char kHistogramGWSHeadChunkStart[] =
     HISTOGRAM_PREFIX "PaintTiming.HeadChunkStart";
@@ -110,6 +112,7 @@
 const char kHistogramGWSHCT[] = HISTOGRAM_PREFIX "CSI.HCT";
 const char kHistogramGWSSCT[] = HISTOGRAM_PREFIX "CSI.SCT";
 const char kHistogramGWSSRT[] = HISTOGRAM_PREFIX "CSI.SRT";
+const char kHistogramGWSSGL[] = HISTOGRAM_PREFIX "CSI.SGL";
 const char kHistogramGWSTimeBetweenHCTAndSCT[] =
     HISTOGRAM_PREFIX "CSI.TimeBetweenHCTAndSCT";
 
@@ -181,6 +184,12 @@
 
 namespace {
 
+BASE_FEATURE(kRecordPrenavigationLatency, base::FEATURE_ENABLED_BY_DEFAULT);
+
+bool IsPrenavigationLatencyEnabled() {
+  return base::FeatureList::IsEnabled(kRecordPrenavigationLatency);
+}
+
 bool IsNavigationFromNewTabPage(
     GWSPageLoadMetricsObserver::NavigationSourceType type) {
   switch (type) {
@@ -529,6 +538,15 @@
       body_chunk_start_time_ = mark->start_time;
     } else if (mark->mark_name == internal::kGwsBodyChunkEndMarkName) {
       record_histogram(internal::kHistogramGWSBodyChunkEnd, timing);
+    } else if (IsPrenavigationLatencyEnabled() &&
+               mark->mark_name == internal::kGwsSGLMarkName) {
+      // Because this is a performance mark for previous navigation, we should
+      // not correct the timing for prerender activation, or else we would get
+      // inconsistent timing.
+      // So, we use `mark->start_time` directly here rather than using the
+      // pre-adjusted `timing`.
+      record_histogram(internal::kHistogramGWSSGL, mark->start_time);
+      sgl_time_ = mark->start_time;
     }
   }
 }
@@ -579,6 +597,38 @@
     return;
   }
 
+  if (IsPrenavigationLatencyEnabled() && aft_end_time_.has_value()) {
+    // There are multiple patterns to record the prenavigation latency events:
+    // - For non prerendering cases: If we have prenavigation latency, we should
+    // add them to the AFT performance mark to get the total latency.
+    // - For prerendering cases:
+    //   - If the activation happens during this navigation, we should update
+    //     the base time to start from the activation time. This means that any
+    //     prenavigation event that happens before activation should be ignored
+    //     and be set to 0.
+    //   - If the activation happens before this navigation, the
+    //     current navigation would start as a normal (non-prerendered
+    //     navigation), since it should not start from `OnPrerenderStart`, and
+    //     start from `OnStart`. Hence, we would not need to correct the base
+    //     time, and the prenavigation latency should be recorded as it is to
+    //     be consistent with what is recorded in the server side.
+    auto base_time = aft_end_time_.value();
+    std::optional<base::TimeDelta> prenavigation_time = sgl_time_;
+    if (is_prerendered_) {
+      // If we are in prerendering, we need to correct the AFTEnd to start from
+      // the activation timing.
+      base_time =
+          page_load_metrics::CorrectEventAsNavigationOrActivationOrigined(
+              GetDelegate(), aft_end_time_.value());
+      prenavigation_time = std::nullopt;
+    }
+
+    // We record pre navigation time here as well.
+    PAGE_LOAD_HISTOGRAM(
+        internal::kHistogramGWSAFTEndWithPreNavigationLatency,
+        base_time + prenavigation_time.value_or(base::TimeDelta()));
+  }
+
   if (!WasStartedInForegroundOptionalEventInForeground(
           all_frames_largest_contentful_paint.Time(), GetDelegate())) {
     return;
diff --git a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.h b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.h
index 55508429..3b095ab 100644
--- a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.h
+++ b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.h
@@ -189,6 +189,7 @@
   std::optional<base::TimeDelta> body_chunk_start_time_;
   std::optional<base::TimeDelta> head_chunk_start_time_;
   std::optional<base::TimeDelta> head_chunk_end_time_;
+  std::optional<base::TimeDelta> sgl_time_;
 
   int64_t navigation_id_;
 };
diff --git a/components/segmentation_platform/PRESUBMIT.py b/components/segmentation_platform/PRESUBMIT.py
index 002277c..7f02276 100644
--- a/components/segmentation_platform/PRESUBMIT.py
+++ b/components/segmentation_platform/PRESUBMIT.py
@@ -49,8 +49,8 @@
         disabled_warnings=disabled_warnings)
 
 
-def _CheckHistograms(input_api, output_api):
-    """Checks if the histograms.txt file is up to date."""
+def _CheckUmaMetrics(input_api, output_api):
+    """Checks if the UMA metric lists are up to date."""
     # Path to the directory containing segmentation platform models.
     model_dir = input_api.os_path.join('components', 'segmentation_platform',
                                        'embedder', 'default_model')
@@ -73,22 +73,29 @@
         old_sys_path = input_api.sys.path
         sys_path_to_add = input_api.os_path.join(cwd, 'tools')
         input_api.sys.path.insert(0, sys_path_to_add)
-        import check_histograms
+        import generate_histogram_list
     finally:
         input_api.sys.path = old_sys_path
 
-    expected_histograms = (check_histograms.GetExpectedHistogramsFileContent())
-    actual_histograms = check_histograms.GetActualHistogramsFileContent()
+    warnings = []
+    expected_histograms = (
+        generate_histogram_list.GetExpectedHistogramsFileContent())
+    actual_histograms = generate_histogram_list.GetActualHistogramsFileContent(
+    )
+    expected_user_actions = (
+        generate_histogram_list.GetExpectedUserActionsFileContent())
+    actual_user_actions = (
+        generate_histogram_list.GetActualUserActionsFileContent())
 
-    if expected_histograms != actual_histograms:
+    if (expected_user_actions != actual_user_actions
+            or expected_histograms != actual_histograms):
         error_message = (
-            'The histograms.txt file is out of date.'
-            '\n\nPlease run:\n'
-            'python3 components/segmentation_platform/tools/check_histograms.py'
-        )
-        return [output_api.PresubmitPromptWarning(error_message, [])]
+            'The Segmentation histogram list is out of date.\n\n'
+            'Please run:\npython3 components/segmentation_platform'
+            '/tools/generate_histogram_list.py')
+        warnings.append(output_api.PresubmitPromptWarning(error_message, []))
 
-    return []
+    return warnings
 
 
 def _CommonChecks(input_api, output_api):
@@ -104,7 +111,7 @@
                 'The test launcher filter file does not match the ' +
                 f'available tests.\n\nPlease run:\n{tool_help_path}', []))
 
-    output.extend(_CheckHistograms(input_api, output_api))
+    output.extend(_CheckUmaMetrics(input_api, output_api))
     return output
 
 
diff --git a/components/segmentation_platform/internal/metadata/metadata_writer.h b/components/segmentation_platform/internal/metadata/metadata_writer.h
index 47e72ea..e60ae38 100644
--- a/components/segmentation_platform/internal/metadata/metadata_writer.h
+++ b/components/segmentation_platform/internal/metadata/metadata_writer.h
@@ -21,6 +21,7 @@
 
 namespace segmentation_platform {
 
+// LINT.IfChange
 namespace features {
 
 // Defines default values for a feature.
@@ -254,6 +255,7 @@
 }
 
 }  // namespace features
+// LINT.ThenChange(//components/segmentation_platform/tools/generate_histogram_list.py)
 
 template <typename EnumType>
 using FeaturePair = std::pair<EnumType, const features::Feature>;
diff --git a/components/segmentation_platform/tools/check_histograms.py b/components/segmentation_platform/tools/check_histograms.py
deleted file mode 100755
index 721f709..0000000
--- a/components/segmentation_platform/tools/check_histograms.py
+++ /dev/null
@@ -1,112 +0,0 @@
-#!/usr/bin/env python3
-# Copyright 2025 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-"""This script provides functionality for automatically keeping a list of
-histograms used by segmentation platform models up to date.
-
-By running this script as a binary, it automatically rewrites the golden file,
-but it can also be used as a Python module for presubmit scripts.
-"""
-
-import os
-import re
-import sys
-
-# The script needs to be run from the chromium src directory.
-if __name__ == '__main__' and not os.path.exists('components'):
-    sys.exit('This script must be run from the chromium src directory.')
-
-# Path to the directory containing segmentation platform models.
-MODEL_DIR = os.path.join('components', 'segmentation_platform', 'embedder',
-                         'default_model')
-
-# Name of the golden file.
-OUTPUT_FILENAME = 'histograms.txt'
-
-
-def _GetComponentDirectoryPath():
-    """Returns the path to the current component."""
-    return os.path.join('components', 'segmentation_platform')
-
-
-def _GetHistogramsFilePath():
-    """Returns the path to the golden file."""
-    component_directory = _GetComponentDirectoryPath()
-    return os.path.join(component_directory, 'tools', OUTPUT_FILENAME)
-
-
-def _FindHistograms(cwd):
-    """Finds all histograms used in the segmentation platform models."""
-    # Regex to find histogram names in various macros and structs.
-    # The patterns handle multi-line macro invocations.
-    histogram_patterns = [
-        re.compile(r'SEGMENTATION_UMA_ENUM\s*\(\s*"([^"]+)"', re.MULTILINE),
-        re.compile(r'From(?:Enum|Value)Histogram\s*\(\s*"([^"]+)"',
-                   re.MULTILINE),
-        re.compile(r'FromUserAction\s*\(\s*"([^"]+)"', re.MULTILINE),
-        # This pattern is more specific to UMAFeature structs to avoid
-        # capturing names from other structs like CustomInput.
-        re.compile(
-            r'MetadataWriter::UMAFeature\s*\{[^}]*\.name\s*=\s*"([^"]+)"',
-            re.MULTILINE),
-        re.compile(r'features::UserAction\s*\(\s*"([^"]+)"', re.MULTILINE),
-        re.compile(r'features::UMA\w*\s*\(\s*"([^"]+)"', re.MULTILINE),
-        re.compile(r'features::LatestOrDefaultValue\s*\(\s*"([^"]+)"',
-                   re.MULTILINE),
-    ]
-
-    histograms = set()
-    for root, _, files in os.walk(cwd):
-        for filename in files:
-            if filename.endswith('.cc') and not filename.endswith(
-                ('_unittest.cc', '_test.cc')):
-                file_path = os.path.join(root, filename)
-                with open(file_path, 'r', encoding='utf-8') as f:
-                    try:
-                        file_contents = f.read()
-                        for pattern in histogram_patterns:
-                            for match in pattern.finditer(file_contents):
-                                histograms.add(match.group(1))
-                    except Exception as e:
-                        print(f"Error reading file {file_path}: {e}")
-    return sorted(list(histograms))
-
-
-def _CreateHistogramsFileContent(histograms):
-    """Creates the content for the golden file."""
-    return '\n'.join(histograms) + '\n'
-
-
-def GetActualHistogramsFileContent():
-    """Reads the current content of the golden file."""
-    file_path = _GetHistogramsFilePath()
-    if not os.path.exists(file_path):
-        return ""
-    with open(file_path, 'r', encoding='utf-8') as f:
-        return f.read()
-
-
-def GetExpectedHistogramsFileContent():
-    """Creates the expected content of the golden file."""
-    histograms = _FindHistograms(MODEL_DIR)
-    return _CreateHistogramsFileContent(histograms)
-
-
-def _WriteHistogramsFile(file_path, content):
-    """Writes the content to the given file path."""
-    os.makedirs(os.path.dirname(file_path), exist_ok=True)
-    with open(file_path, 'w', encoding='utf-8') as f:
-        f.write(content)
-
-
-def main():
-    """Main function to update the golden file."""
-    output_file_path = _GetHistogramsFilePath()
-    expected_content = GetExpectedHistogramsFileContent()
-    _WriteHistogramsFile(output_file_path, expected_content)
-    print(f"Updated {output_file_path}")
-
-
-if __name__ == '__main__':
-    main()
diff --git a/components/segmentation_platform/tools/generate_histogram_list.py b/components/segmentation_platform/tools/generate_histogram_list.py
new file mode 100755
index 0000000..8d1a8f3
--- /dev/null
+++ b/components/segmentation_platform/tools/generate_histogram_list.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python3
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""This script provides functionality for automatically keeping a list of
+histograms and user actions used by segmentation platform models up to date.
+
+By running this script as a binary, it automatically rewrites the golden files,
+but it can also be used as a Python module for presubmit scripts.
+"""
+
+import os
+import re
+import sys
+
+# The script needs to be run from the chromium src directory.
+if __name__ == '__main__' and not os.path.exists('components'):
+    sys.exit('This script must be run from the chromium src directory.')
+
+# Path to the directory containing segmentation platform models.
+# TODO(haileywang): Also include home_modules/ folder.
+MODEL_DIR = os.path.join('components', 'segmentation_platform', 'embedder',
+                         'default_model')
+
+# Name of the golden files.
+# TODO(haileywang): Add ukm metrics.
+HISTOGRAMS_FILENAME = 'histograms.txt'
+USER_ACTIONS_FILENAME = 'user_actions.txt'
+
+
+def _GetComponentDirectoryPath():
+    """Returns the path to the current component."""
+    return os.path.join('components', 'segmentation_platform')
+
+
+def _GetHistogramsFilePath():
+    """Returns the path to the histograms golden file."""
+    component_directory = _GetComponentDirectoryPath()
+    return os.path.join(component_directory, 'tools', HISTOGRAMS_FILENAME)
+
+
+def _GetUserActionsFilePath():
+    """Returns the path to the user actions golden file."""
+    component_directory = _GetComponentDirectoryPath()
+    return os.path.join(component_directory, 'tools', USER_ACTIONS_FILENAME)
+
+
+def _FindMetrics(cwd, patterns):
+    """Finds all metrics matching the given patterns."""
+    metrics = set()
+    for root, _, files in os.walk(cwd):
+        for filename in files:
+            if not filename.endswith('.cc') or filename.endswith(
+                ('_unittest.cc', '_test.cc')):
+                continue
+
+            file_path = os.path.join(root, filename)
+            with open(file_path, 'r', encoding='utf-8') as f:
+                try:
+                    file_contents = f.read()
+                    for pattern in patterns:
+                        for match in pattern.finditer(file_contents):
+                            metrics.add(match.group(1))
+                except Exception as e:
+                    print(f"Error reading file {file_path}: {e}")
+    return sorted(list(metrics))
+
+
+def _FindHistograms(cwd):
+    """Finds all histograms used in the segmentation platform models."""
+    histogram_patterns = [
+        re.compile(r'From(?:Enum|Value)Histogram\s*\(\s*"([^"]+)"',
+                   re.MULTILINE),
+        re.compile(r'FromLatestOrDefaultValue\s*\(\s*"([^"]+)"', re.MULTILINE),
+        re.compile(
+            r'MetadataWriter::UMAFeature\s*\{[^}]*\.name\s*=\s*"([^"]+)"',
+            re.MULTILINE),
+        re.compile(r'features::UMA\w*\s*\(\s*"([^"]+)"', re.MULTILINE),
+        re.compile(r'features::LatestOrDefaultValue\s*\(\s*"([^"]+)"',
+                   re.MULTILINE),
+    ]
+    return _FindMetrics(cwd, histogram_patterns)
+
+
+def _FindUserActions(cwd):
+    """Finds all user actions used in the segmentation platform models."""
+    user_action_patterns = [
+        re.compile(r'FromUserAction\s*\(\s*"([^"]+)"', re.MULTILINE),
+        re.compile(r'features::UserAction\s*\(\s*"([^"]+)"', re.MULTILINE),
+    ]
+    return _FindMetrics(cwd, user_action_patterns)
+
+
+def _CreateFileContent(metrics):
+    """Creates the content for the golden file."""
+    return '\n'.join(metrics) + '\n'
+
+
+def GetActualHistogramsFileContent():
+    """Reads the current content of the histograms golden file."""
+    file_path = _GetHistogramsFilePath()
+    if not os.path.exists(file_path):
+        return ""
+    with open(file_path, 'r', encoding='utf-8') as f:
+        return f.read()
+
+
+def GetExpectedHistogramsFileContent():
+    """Creates the expected content of the histograms golden file."""
+    histograms = _FindHistograms(MODEL_DIR)
+    return _CreateFileContent(histograms)
+
+
+def GetActualUserActionsFileContent():
+    """Reads the current content of the user actions golden file."""
+    file_path = _GetUserActionsFilePath()
+    if not os.path.exists(file_path):
+        return ""
+    with open(file_path, 'r', encoding='utf-8') as f:
+        return f.read()
+
+
+def GetExpectedUserActionsFileContent():
+    """Creates the expected content of the user actions golden file."""
+    user_actions = _FindUserActions(MODEL_DIR)
+    return _CreateFileContent(user_actions)
+
+
+def _WriteFile(file_path, content):
+    """Writes the content to the given file path."""
+    os.makedirs(os.path.dirname(file_path), exist_ok=True)
+    with open(file_path, 'w', encoding='utf-8') as f:
+        f.write(content)
+
+
+def main():
+    """Main function to update the golden files."""
+    histograms_file_path = _GetHistogramsFilePath()
+    expected_histograms_content = GetExpectedHistogramsFileContent()
+    _WriteFile(histograms_file_path, expected_histograms_content)
+    print(f"Updated {histograms_file_path}")
+
+    user_actions_file_path = _GetUserActionsFilePath()
+    expected_user_actions_content = GetExpectedUserActionsFileContent()
+    _WriteFile(user_actions_file_path, expected_user_actions_content)
+    print(f"Updated {user_actions_file_path}")
+
+
+if __name__ == '__main__':
+    main()
diff --git a/components/segmentation_platform/tools/histograms.txt b/components/segmentation_platform/tools/histograms.txt
index cff75b7e..c30fca82 100644
--- a/components/segmentation_platform/tools/histograms.txt
+++ b/components/segmentation_platform/tools/histograms.txt
@@ -2,20 +2,14 @@
 Android.AdaptiveToolbarButton.Clicked
 Android.AdaptiveToolbarButton.Variant.OnPageLoad
 Android.DragDrop.FromWebContent.TargetType
-Android.HistoryPage.OpenItem
 Android.MultiInstance.NumActivities
-Android.MultiWindowMode.MultiInstance.Enter
 Android.PhotoPicker.DialogAction
 Autofill.KeyMetrics.FillingAcceptance.Address
 Autofill.KeyMetrics.FillingAcceptance.CreditCard
-Autofill.KeyMetrics.FillingAssistance.CreditCard
-Autofill_PolledCreditCardSuggestions
-Back
 Blink.FedCm.AccountsDialogShown
 Blink.FedCm.CancelReason
 Blink.FedCm.IsSignInUser
 Blink.FedCm.Status.RequestIdToken
-Bookmarks.FolderAdded
 Commerce.PriceDrops.ActiveTabNavigationComplete.IsProductDetailPage
 ContentSettings.RegularProfile.DefaultRequestDesktopSiteSetting
 ContentSuggestions.Feed.EngagementType
@@ -23,8 +17,6 @@
 DataUse.TrafficSize.User.Upstream.Foreground.NotCellular
 Download.Start.PerProfileType
 FirstRun.Stage
-Forward
-Home
 IOS.CredentialExtension.IsEnabled.Startup
 IOS.Incognito.TimeSpent
 IOS.IncognitoInterstitial.Settings
@@ -35,45 +27,11 @@
 IOS.PageLoadCount.Counts
 IOS.ParcelTracking.Tracked.AutoTrack
 IOS.Start.Impression
-IOSMagicStackSafetyCheckFreshSignal
-IncognitoMode_Started
 MagicStack.Clank.NewTabPage.Module.Click
 MagicStack.Clank.NewTabPage.Module.TopImpressionV2
-Media.Controls.Cast
-Media.Controls.CastOverlay
 Media.InputStreamDuration
 Media.OutputStreamDuration
-MetadataWriter
-MobileBookmarkManagerEntryOpened
-MobileBookmarkManagerOpen
-MobileMenuAddToBookmarks
-MobileMenuAllBookmarks
-MobileMenuDownloadManager
-MobileMenuDownloadPage
-MobileMenuHistory
-MobileMenuRecentTabs
-MobileMenuRequestDesktopSite
-MobileMenuSettings
-MobileMenuShare
-MobileMenuTranslate
-MobileNTPMostVisited
-MobileNewTabOpened
-MobileNewTabShown
-MobileOmniboxLens
-MobileOmniboxShortcutsOpenMostVisitedItem
-MobileOmniboxShortcutsOpenReadingList
-MobileOmniboxVoiceSearch
-MobilePageLoadedWithKeyboard
-MobileReadingListAdd
-MobileReadingListOpen
-MobileStackSwipeCancelled
 MobileStartup.LaunchCause
-MobileTabGridEntered
-MobileTabReturnedToCurrentTab
-MobileTabSwitched
-MobileToolbarForward
-NewTabPage.MostVisited.Clicked
-NewTabPage.SearchBox.Lens
 NewTabPage.TimeSpent
 Omnibox.SuggestionUsed.ClientSummarizedResultType
 Omnibox.SuggestionUsed.SearchVsUrl
@@ -86,21 +44,15 @@
 PasswordManager.ProfileStore.TotalAccountsHiRes3.WithScheme.Https
 PasswordManager.SaveUIDismissalReason
 PasswordManager.SavedPasswordIsGenerated
-PasswordManager_Autofilled
 SafeBrowsing.Settings.UserAction.Default
 Session.TotalDuration
 Session.TotalDuration.WithAccount
-SharingHubAndroid.SendTabToSelfSelected
 Signin.IOSNumberOfDeviceAccounts
 Startup.MobileSessionStartFromApps
-Suggestions.Content.Opened
 Sync.DeviceCount2
 Sync.DeviceCount2.Desktop
 Sync.DeviceCount2.Phone
 Sync.DeviceCount2.Tablet
-TabGroup.Created.OpenInNewTab
 TabGroups.UserGroupCount
-TasksSurface.FakeBox.Lens
 UMA.ProfileSignInStatusV2
 UMA.ProfileSyncStatusV2
-UserActionName
diff --git a/components/segmentation_platform/tools/user_actions.txt b/components/segmentation_platform/tools/user_actions.txt
new file mode 100644
index 0000000..6760318
--- /dev/null
+++ b/components/segmentation_platform/tools/user_actions.txt
@@ -0,0 +1,48 @@
+Android.HistoryPage.OpenItem
+Android.MultiWindowMode.MultiInstance.Enter
+Autofill.KeyMetrics.FillingAssistance.CreditCard
+Autofill_PolledCreditCardSuggestions
+Back
+Bookmarks.FolderAdded
+Forward
+Home
+IOSMagicStackSafetyCheckFreshSignal
+IncognitoMode_Started
+Media.Controls.Cast
+Media.Controls.CastOverlay
+MetadataWriter
+MobileBookmarkManagerEntryOpened
+MobileBookmarkManagerOpen
+MobileMenuAddToBookmarks
+MobileMenuAllBookmarks
+MobileMenuDownloadManager
+MobileMenuDownloadPage
+MobileMenuHistory
+MobileMenuRecentTabs
+MobileMenuRequestDesktopSite
+MobileMenuSettings
+MobileMenuShare
+MobileMenuTranslate
+MobileNTPMostVisited
+MobileNewTabOpened
+MobileNewTabShown
+MobileOmniboxLens
+MobileOmniboxShortcutsOpenMostVisitedItem
+MobileOmniboxShortcutsOpenReadingList
+MobileOmniboxVoiceSearch
+MobilePageLoadedWithKeyboard
+MobileReadingListAdd
+MobileReadingListOpen
+MobileStackSwipeCancelled
+MobileTabGridEntered
+MobileTabReturnedToCurrentTab
+MobileTabSwitched
+MobileToolbarForward
+NewTabPage.MostVisited.Clicked
+NewTabPage.SearchBox.Lens
+PasswordManager_Autofilled
+SharingHubAndroid.SendTabToSelfSelected
+Suggestions.Content.Opened
+TabGroup.Created.OpenInNewTab
+TasksSurface.FakeBox.Lens
+UserActionName
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.cc b/components/startup_metric_utils/browser/startup_metric_utils.cc
index 22d0cec..2a0d7a8 100644
--- a/components/startup_metric_utils/browser/startup_metric_utils.cc
+++ b/components/startup_metric_utils/browser/startup_metric_utils.cc
@@ -95,30 +95,8 @@
 namespace {
 const char kProcessType[] = "type";
 
-// An enumeration of startup temperatures. This must be kept in sync with
-// the UMA StartupType enumeration defined in histograms.xml.
-enum StartupTemperature {
-  // The startup was a cold start: nearly all of the binaries and resources
-  // were
-  // brought into memory using hard faults.
-  COLD_STARTUP_TEMPERATURE = 0,
-  // The startup was a warm start: the binaries and resources were mostly
-  // already resident in memory and effectively no hard faults were
-  // observed.
-  WARM_STARTUP_TEMPERATURE = 1,
-  // The startup type couldn't quite be classified as warm or cold, but
-  // rather
-  // was somewhere in between.
-  LUKEWARM_STARTUP_TEMPERATURE = 2,
-  // Startup temperature wasn't yet determined, or could not be determined.
-  UNDETERMINED_STARTUP_TEMPERATURE = 3,
-  // This must be after all meaningful values. All new values should be
-  // added
-  // above this one.
-  STARTUP_TEMPERATURE_COUNT,
-};
-
-StartupTemperature g_startup_temperature = UNDETERMINED_STARTUP_TEMPERATURE;
+startup_metric_utils::StartupTemperature g_startup_temperature =
+    startup_metric_utils::UNDETERMINED_STARTUP_TEMPERATURE;
 
 // Helper function for splitting out an UMA histogram based on startup
 // temperature. |histogram_function| is the histogram type, and corresponds to
@@ -143,20 +121,20 @@
   (*histogram_function)(histogram_basename, value);
   // Record to the cold/warm suffixed histogram as appropriate.
   switch (g_startup_temperature) {
-    case COLD_STARTUP_TEMPERATURE:
+    case startup_metric_utils::COLD_STARTUP_TEMPERATURE:
       (*histogram_function)(base::StrCat({histogram_basename, ".ColdStartup"}),
                             value);
       break;
-    case WARM_STARTUP_TEMPERATURE:
+    case startup_metric_utils::WARM_STARTUP_TEMPERATURE:
       (*histogram_function)(base::StrCat({histogram_basename, ".WarmStartup"}),
                             value);
       break;
-    case LUKEWARM_STARTUP_TEMPERATURE:
+    case startup_metric_utils::LUKEWARM_STARTUP_TEMPERATURE:
       // No suffix emitted for lukewarm startups.
       break;
-    case UNDETERMINED_STARTUP_TEMPERATURE:
+    case startup_metric_utils::UNDETERMINED_STARTUP_TEMPERATURE:
       break;
-    case STARTUP_TEMPERATURE_COUNT:
+    case startup_metric_utils::STARTUP_TEMPERATURE_COUNT:
       NOTREACHED();
   }
 }
@@ -477,26 +455,10 @@
     return;
   }
 
-  base::TimeTicks latency_origin;
-#if BUILDFLAG(IS_CHROMEOS)
-  // `application_start_ticks_` is inappropriate since the device often boots
-  // to a login screen, and an indefinite amount of time can elapse before a
-  // browser window is opened. Even when restoring a session after a crash
-  // (which has no login screen), the session is not restored automatically.
-  // The user must click a notification first before browser windows are
-  // created and restored, so using `application_start_ticks_` would have the
-  // same issue.
-  //
-  // If `web_contents_start_ticks_` is not set here, that could be intentional
-  // as this metric should not be recorded in certain cases (ex: a manually
-  // opened browser window).
-  if (web_contents_start_ticks_.is_null()) {
+  base::TimeTicks latency_origin = GetApplicationStartTicksForStartup();
+  if (latency_origin.is_null()) {
     return;
   }
-  latency_origin = web_contents_start_ticks_;
-#else
-  latency_origin = GetCommon().application_start_ticks_;
-#endif  // BUILDFLAG(IS_CHROMEOS)
   DCHECK(!latency_origin.is_null());
 
   EmitHistogramWithTemperatureAndTraceEvent(&base::UmaHistogramLongTimes100,
@@ -552,6 +514,33 @@
   return !WasMainWindowStartupInterrupted();
 }
 
+StartupTemperature BrowserStartupMetricRecorder::GetStartupTemperature() const {
+  return g_startup_temperature;
+}
+
+base::TimeTicks
+BrowserStartupMetricRecorder::GetApplicationStartTicksForStartup() const {
+#if BUILDFLAG(IS_CHROMEOS)
+  // `application_start_ticks_` is inappropriate since the device often boots
+  // to a login screen, and an indefinite amount of time can elapse before a
+  // browser window is opened. Even when restoring a session after a crash
+  // (which has no login screen), the session is not restored automatically.
+  // The user must click a notification first before browser windows are
+  // created and restored, so using `application_start_ticks_` would have the
+  // same issue.
+  //
+  // If `web_contents_start_ticks_` is not set here, that could be intentional
+  // as this metric should not be recorded in certain cases (ex: a manually
+  // opened browser window).
+  if (web_contents_start_ticks_.is_null()) {
+    return base::TimeTicks();
+  }
+  return web_contents_start_ticks_;
+#else
+  return GetCommon().application_start_ticks_;
+#endif  // BUILDFLAG(IS_CHROMEOS)
+}
+
 #if BUILDFLAG(IS_CHROMEOS)
 void BrowserStartupMetricRecorder::RecordWebContentsStartTime(
     base::TimeTicks ticks) {
diff --git a/components/startup_metric_utils/browser/startup_metric_utils.h b/components/startup_metric_utils/browser/startup_metric_utils.h
index 3600976..b131878 100644
--- a/components/startup_metric_utils/browser/startup_metric_utils.h
+++ b/components/startup_metric_utils/browser/startup_metric_utils.h
@@ -34,6 +34,27 @@
   kMaxValue = kFileSystemError,
 };
 
+// An enumeration of startup temperatures. This must be kept in sync with
+// the UMA StartupType enumeration defined in histograms.xml.
+// LINT.IfChange(StartupTemperature)
+enum StartupTemperature {
+  // The startup was a cold start: nearly all of the binaries and resources were
+  // brought into memory using hard faults.
+  COLD_STARTUP_TEMPERATURE = 0,
+  // The startup was a warm start: the binaries and resources were mostly
+  // already resident in memory and effectively no hard faults were observed.
+  WARM_STARTUP_TEMPERATURE = 1,
+  // The startup type couldn't quite be classified as warm or cold, but rather
+  // was somewhere in between.
+  LUKEWARM_STARTUP_TEMPERATURE = 2,
+  // Startup temperature wasn't yet determined, or could not be determined.
+  UNDETERMINED_STARTUP_TEMPERATURE = 3,
+  // This must be after all meaningful values. All new values should be added
+  // above this one.
+  STARTUP_TEMPERATURE_COUNT,
+};
+// LINT.ThenChange(//tools/metrics/histograms/metadata/startup/enums.xml:StartupTemperature)
+
 class COMPONENT_EXPORT(STARTUP_METRIC_UTILS)
     BrowserStartupMetricRecorder final {
  public:
@@ -132,6 +153,13 @@
 
   bool ShouldLogStartupHistogram() const;
 
+  // Returns the startup temperature if available.
+  StartupTemperature GetStartupTemperature() const;
+
+  // Returns the appropriate application start ticks for use in startup metrics.
+  // Returns a null TimeTicks if a value has not been recorded yet.
+  base::TimeTicks GetApplicationStartTicksForStartup() const;
+
 #if BUILDFLAG(IS_CHROMEOS)
   // On ChromeOS, the time at which the first browser window is opened may not
   // match the application start time mainly because the login screen is often
diff --git a/components/supervised_user/core/browser/supervised_user_test_environment.h b/components/supervised_user/core/browser/supervised_user_test_environment.h
index b12e074..88d82876 100644
--- a/components/supervised_user/core/browser/supervised_user_test_environment.h
+++ b/components/supervised_user/core/browser/supervised_user_test_environment.h
@@ -10,6 +10,7 @@
 #include <string_view>
 
 #include "base/memory/ref_counted.h"
+#include "components/prefs/pref_notifier_impl.h"
 #include "components/prefs/pref_service.h"
 #include "components/prefs/testing_pref_store.h"
 #include "components/safe_search_api/fake_url_checker_client.h"
diff --git a/components/sync/model/client_tag_based_remote_update_handler.cc b/components/sync/model/client_tag_based_remote_update_handler.cc
index 8157aa4..0fdc8d7 100644
--- a/components/sync/model/client_tag_based_remote_update_handler.cc
+++ b/components/sync/model/client_tag_based_remote_update_handler.cc
@@ -24,6 +24,7 @@
 #include "components/sync/protocol/data_type_state_helper.h"
 #include "components/sync/protocol/entity_specifics.pb.h"
 #include "components/sync/protocol/unique_position.pb.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
 
 namespace syncer {
 
@@ -68,7 +69,7 @@
   // If new encryption requirements come from the server, the entities that are
   // in `updates` will be recorded here so they can be ignored during the
   // re-encryption phase at the end.
-  std::unordered_set<std::string> already_updated;
+  absl::flat_hash_set<std::string> already_updated;
 
   for (syncer::UpdateResponseData& update : updates) {
     std::string storage_key_to_clear;
diff --git a/components/sync/model/processor_entity_tracker.cc b/components/sync/model/processor_entity_tracker.cc
index 3c063cd..d021cea 100644
--- a/components/sync/model/processor_entity_tracker.cc
+++ b/components/sync/model/processor_entity_tracker.cc
@@ -278,12 +278,11 @@
 
 std::vector<const ProcessorEntity*>
 ProcessorEntityTracker::IncrementSequenceNumberForAllExcept(
-    const std::unordered_set<std::string>& already_updated_storage_keys) {
+    const absl::flat_hash_set<std::string>& already_updated_storage_keys) {
   std::vector<const ProcessorEntity*> affected_entities;
   for (const auto& [client_tag_hash, entity] : entities_) {
     if (entity->storage_key().empty() ||
-        (already_updated_storage_keys.find(entity->storage_key()) !=
-         already_updated_storage_keys.end())) {
+        already_updated_storage_keys.contains(entity->storage_key())) {
       // Entities with empty storage key were already processed. ProcessUpdate()
       // incremented their sequence numbers and cached commit data. Their
       // metadata will be persisted in UpdateStorageKey().
diff --git a/components/sync/model/processor_entity_tracker.h b/components/sync/model/processor_entity_tracker.h
index b84b994..3a21c28 100644
--- a/components/sync/model/processor_entity_tracker.h
+++ b/components/sync/model/processor_entity_tracker.h
@@ -8,7 +8,6 @@
 #include <memory>
 #include <optional>
 #include <string>
-#include <unordered_set>
 #include <vector>
 
 #include "base/containers/flat_set.h"
@@ -16,6 +15,7 @@
 #include "components/sync/engine/commit_and_get_updates_types.h"
 #include "components/sync/protocol/data_type_state.pb.h"
 #include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_set.h"
 
 namespace sync_pb {
 class EntityMetadata;
@@ -129,7 +129,7 @@
   // Increments sequence number for all entities except those in
   // `already_updated_storage_keys`. Returns affected list of entities.
   std::vector<const ProcessorEntity*> IncrementSequenceNumberForAllExcept(
-      const std::unordered_set<std::string>& already_updated_storage_keys);
+      const absl::flat_hash_set<std::string>& already_updated_storage_keys);
 
   // Assigns a new storage key to the entity for the given `client_tag_hash`.
   // Clears previous storage key if entity already has one (the metadata of the
diff --git a/components/user_manager/scoped_user_manager.h b/components/user_manager/scoped_user_manager.h
index 0c6c2e9a..2406c54 100644
--- a/components/user_manager/scoped_user_manager.h
+++ b/components/user_manager/scoped_user_manager.h
@@ -9,6 +9,7 @@
 #include <utility>
 
 #include "base/memory/raw_ptr.h"
+#include "components/user_manager/user_manager.h"
 #include "components/user_manager/user_manager_export.h"
 
 namespace user_manager {
diff --git a/components/viz/common/gpu/context_provider.h b/components/viz/common/gpu/context_provider.h
index c39a52a..c5418c71 100644
--- a/components/viz/common/gpu/context_provider.h
+++ b/components/viz/common/gpu/context_provider.h
@@ -21,8 +21,6 @@
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/command_buffer/common/context_result.h"
 
-class GrDirectContext;
-
 namespace base {
 class Lock;
 }
@@ -94,11 +92,6 @@
   // must have been successfully bound to a thread before calling this.
   virtual gpu::ContextSupport* ContextSupport() = 0;
 
-  // Get a Skia GPU raster interface to the 3d context.  The context provider
-  // must have been successfully bound to a thread before calling this.  Returns
-  // nullptr if a GrContext fails to initialize on this context.
-  virtual class GrDirectContext* GrContext() = 0;
-
   virtual gpu::SharedImageInterface* SharedImageInterface() = 0;
 
   // Returns the capabilities of the currently bound 3d context.  The context
diff --git a/components/viz/common/gpu/raster_context_provider.h b/components/viz/common/gpu/raster_context_provider.h
index e3bce53..5188f0c 100644
--- a/components/viz/common/gpu/raster_context_provider.h
+++ b/components/viz/common/gpu/raster_context_provider.h
@@ -21,8 +21,6 @@
 #include "gpu/command_buffer/common/capabilities.h"
 #include "gpu/command_buffer/common/context_result.h"
 
-class GrDirectContext;
-
 namespace base {
 class Lock;
 }
@@ -96,11 +94,6 @@
   // must have been successfully bound to a thread before calling this.
   virtual gpu::ContextSupport* ContextSupport() = 0;
 
-  // Get a Skia GPU raster interface to the 3d context.  The context provider
-  // must have been successfully bound to a thread before calling this.  Returns
-  // nullptr if a GrContext fails to initialize on this context.
-  virtual class GrDirectContext* GrContext() = 0;
-
   virtual gpu::SharedImageInterface* SharedImageInterface() = 0;
 
   // Returns the capabilities of the currently bound 3d context.  The context
diff --git a/components/viz/service/display/direct_renderer.cc b/components/viz/service/display/direct_renderer.cc
index b97af79..382d6f0 100644
--- a/components/viz/service/display/direct_renderer.cc
+++ b/components/viz/service/display/direct_renderer.cc
@@ -252,10 +252,10 @@
 
   gfx::ColorSpace frame_color_space =
       RenderPassColorSpace(current_frame()->root_render_pass);
-  SharedImageFormat frame_si_format = GetSharedImageFormat(
-      current_frame()->display_color_spaces.GetOutputBufferFormat(
+  SharedImageFormat frame_si_format =
+      current_frame()->display_color_spaces.GetOutputFormat(
           current_frame()->root_render_pass->content_color_usage,
-          current_frame()->root_render_pass->has_transparent_background));
+          current_frame()->root_render_pass->has_transparent_background);
   gfx::Size surface_resource_size =
       CalculateSizeForOutputSurface(device_viewport_size);
 #if BUILDFLAG(IS_WIN)
diff --git a/components/viz/service/gl/gpu_service_impl.cc b/components/viz/service/gl/gpu_service_impl.cc
index 39e017d..32889fd 100644
--- a/components/viz/service/gl/gpu_service_impl.cc
+++ b/components/viz/service/gl/gpu_service_impl.cc
@@ -242,10 +242,11 @@
     if (dawn_context_provider_) {
       // GpuServiceImpl holds the instance of DawnContextProvider, so it
       // outlives the DawnContextProvider.
-      std::unique_ptr<dawn::platform::CachingInterface> caching_interface;
+      std::unique_ptr<gpu::webgpu::DawnCachingInterface> caching_interface;
       if (features::kSkiaGraphiteDawnUsePersistentCache.Get()) {
-        caching_interface =
-            std::make_unique<gpu::GpuPersistentCache>("GraphiteDawn");
+        caching_interface = dawn_caching_interface_factory_->CreateInstance(
+            gpu::kGraphiteDawnGpuDiskCacheHandle,
+            std::make_unique<gpu::GpuPersistentCache>("GraphiteDawn"));
       } else {
         auto cache_blob_callback = base::BindRepeating(
             [](GpuServiceImpl* self, const std::string& key,
@@ -948,10 +949,9 @@
     return;
   }
 
-  auto* persistent_cache = static_cast<gpu::GpuPersistentCache*>(
-      dawn_context_provider_->GetCachingInterface());
-  CHECK(persistent_cache);
-  persistent_cache->InitializeCache(std::move(backend_params));
+  auto* cache = dawn_context_provider_->GetCachingInterface();
+  CHECK(cache);
+  cache->InitializePersistentCache(std::move(backend_params));
 #endif
 }
 
diff --git a/components/viz/service/surfaces/surface_saved_frame.cc b/components/viz/service/surfaces/surface_saved_frame.cc
index bf33895..911ad5a 100644
--- a/components/viz/service/surfaces/surface_saved_frame.cc
+++ b/components/viz/service/surfaces/surface_saved_frame.cc
@@ -208,9 +208,8 @@
   const auto& display_color_spaces = directive_.display_color_spaces();
   bool has_transparent_background = render_pass.has_transparent_background;
 
-  auto image_format =
-      GetSharedImageFormat(display_color_spaces.GetOutputBufferFormat(
-          content_color_usage, has_transparent_background));
+  auto image_format = display_color_spaces.GetOutputFormat(
+      content_color_usage, has_transparent_background);
   auto color_space =
       display_color_spaces.GetRasterAndCompositeColorSpace(content_color_usage);
 
diff --git a/components/viz/test/test_context_provider.h b/components/viz/test/test_context_provider.h
index cd0a9dd..f7071ff 100644
--- a/components/viz/test/test_context_provider.h
+++ b/components/viz/test/test_context_provider.h
@@ -80,7 +80,6 @@
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::raster::RasterInterface* RasterInterface() override;
   gpu::ContextSupport* ContextSupport() override;
-  class GrDirectContext* GrContext() override;
   gpu::TestSharedImageInterface* SharedImageInterface() override;
   ContextCacheController* CacheController() override;
   base::Lock* GetLock() override;
@@ -88,6 +87,8 @@
   void RemoveObserver(ContextLostObserver* obs) override;
   unsigned int GetGrGLTextureFormat(SharedImageFormat format) const override;
 
+  class GrDirectContext* GrContext();
+
   TestGLES2Interface* TestContextGL();
   TestRasterInterface* GetTestRasterInterface();
 
diff --git a/components/viz/test/test_in_process_context_provider.cc b/components/viz/test/test_in_process_context_provider.cc
index d7f357a5..f7fc5d6 100644
--- a/components/viz/test/test_in_process_context_provider.cc
+++ b/components/viz/test/test_in_process_context_provider.cc
@@ -21,8 +21,6 @@
 #include "gpu/config/skia_limits.h"
 #include "gpu/ipc/gl_in_process_context.h"
 #include "gpu/ipc/raster_in_process_context.h"
-#include "gpu/skia_bindings/grcontext_for_gles2_interface.h"
-#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 
 namespace viz {
 
@@ -107,10 +105,6 @@
                         : raster_context_->GetContextSupport();
 }
 
-class GrDirectContext* TestInProcessContextProvider::GrContext() {
-  return nullptr;
-}
-
 gpu::SharedImageInterface*
 TestInProcessContextProvider::SharedImageInterface() {
   return gles2_context_ ? gles2_context_->GetSharedImageInterface()
diff --git a/components/viz/test/test_in_process_context_provider.h b/components/viz/test/test_in_process_context_provider.h
index aac1d12..7f9ad23 100644
--- a/components/viz/test/test_in_process_context_provider.h
+++ b/components/viz/test/test_in_process_context_provider.h
@@ -18,8 +18,6 @@
 #include "components/viz/common/gpu/raster_context_provider.h"
 #include "gpu/config/gpu_feature_info.h"
 
-class GrDirectContext;
-
 namespace gpu {
 class GLInProcessContext;
 class GpuProcessShmCount;
@@ -57,7 +55,6 @@
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::raster::RasterInterface* RasterInterface() override;
   gpu::ContextSupport* ContextSupport() override;
-  class GrDirectContext* GrContext() override;
   gpu::SharedImageInterface* SharedImageInterface() override;
   ContextCacheController* CacheController() override;
   base::Lock* GetLock() override;
diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
index 6dd9a24..572bf2e6 100644
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
@@ -477,11 +477,14 @@
  public:
   FileSystemAccessDirectoryHandleImplRemoveTest() {
     if (GetParam().is_feature_enabled) {
-      scoped_feature_list_.InitAndEnableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {blink::features::kFileSystemAccessWriteMode,
+           blink::features::kFileSystemAccessRevokeReadOnRemove},
+          {});
     } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {}, {blink::features::kFileSystemAccessWriteMode,
+               blink::features::kFileSystemAccessRevokeReadOnRemove});
     }
   }
 
@@ -511,6 +514,10 @@
   base::FilePath dir = dir_.GetPath().AppendASCII("dirname");
   ASSERT_TRUE(base::CreateDirectory(dir));
 
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  }
+
   auto handle = GetHandleWithPermissions(dir, /*read=*/true, /*write=*/true);
 
   base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future;
@@ -527,6 +534,9 @@
   ASSERT_TRUE(base::CreateDirectory(dir));
   base::FilePath file = dir.AppendASCII("test_file.txt");
   ASSERT_TRUE(base::WriteFile(file, "test data"));
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  }
 
   auto handle = GetHandleWithPermissions(dir, /*read=*/true, /*write=*/true);
 
@@ -576,7 +586,9 @@
   auto handle = CreateHandle();
   auto test_dir_path = dir_.GetPath().AppendASCII("test_dir");
 
-  if (!GetParam().is_feature_enabled) {
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  } else {
     SetUpGrantExpectations(*mock_read_grant_, PermissionStatus::GRANTED,
                            FileSystemAccessPermissionGrant::
                                PermissionRequestOutcome::kUserGranted);
@@ -609,11 +621,14 @@
  public:
   FileSystemAccessDirectoryHandleImplRemoveEntryTest() {
     if (GetParam().is_feature_enabled) {
-      scoped_feature_list_.InitAndEnableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {blink::features::kFileSystemAccessWriteMode,
+           blink::features::kFileSystemAccessRevokeReadOnRemove},
+          {});
     } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {}, {blink::features::kFileSystemAccessWriteMode,
+               blink::features::kFileSystemAccessRevokeReadOnRemove});
     }
   }
 
@@ -636,6 +651,10 @@
   LockType exclusive_lock_type = manager_->GetExclusiveLockType();
   LockType wfs_siloed_lock_type = manager_->GetWFSSiloedLockType();
 
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  }
+
   // Calling removeEntry() on an unlocked file should succeed.
   {
     base::CreateTemporaryFileInDir(dir, &file);
@@ -736,6 +755,9 @@
   ASSERT_TRUE(base::CreateDirectory(subdir_path));
   base::FilePath file_path = subdir_path.AppendASCII("test_file.txt");
   ASSERT_TRUE(base::WriteFile(file_path, "test data"));
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  }
 
   base::test::TestFuture<blink::mojom::FileSystemAccessErrorPtr> future;
   handle_->RemoveEntry("subdir", /*recurse=*/true, future.GetCallback());
@@ -772,7 +794,9 @@
   base::FilePath file_path = test_dir.AppendASCII("test_file.txt");
   ASSERT_TRUE(base::WriteFile(file_path, "test data"));
 
-  if (!GetParam().is_feature_enabled) {
+  if (GetParam().is_feature_enabled) {
+    EXPECT_CALL(permission_context_, NotifyEntryRemoved(_, _)).Times(1);
+  } else {
     SetUpGrantExpectations(*mock_read_grant_, PermissionStatus::GRANTED,
                            FileSystemAccessPermissionGrant::
                                PermissionRequestOutcome::kUserGranted);
diff --git a/content/browser/file_system_access/file_system_access_file_writer_impl_unittest.cc b/content/browser/file_system_access/file_system_access_file_writer_impl_unittest.cc
index df50e9b..20e96b97 100644
--- a/content/browser/file_system_access/file_system_access_file_writer_impl_unittest.cc
+++ b/content/browser/file_system_access/file_system_access_file_writer_impl_unittest.cc
@@ -649,6 +649,7 @@
           kFrameId, _))
       .WillOnce(base::test::RunOnceCallback<2>(
           FileSystemAccessPermissionContext::AfterWriteCheckResult::kAllow));
+  EXPECT_CALL(permission_context_, NotifyEntryModified(_, _)).Times(1);
 
   result = CloseSync();
   EXPECT_EQ(result, FileSystemAccessStatus::kOk);
@@ -699,6 +700,7 @@
         sb_callback = std::move(callback);
         loop.Quit();
       });
+  EXPECT_CALL(permission_context_, NotifyEntryModified(_, _)).Times(1);
 
   handle_->Close(base::DoNothing());
   loop.Run();
@@ -849,11 +851,14 @@
  public:
   FileSystemAccessFileWriterImplPermissionTest() {
     if (GetParam().is_feature_enabled) {
-      scoped_feature_list_.InitAndEnableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {blink::features::kFileSystemAccessWriteMode,
+           blink::features::kFileSystemAccessRevokeReadOnRemove},
+          {});
     } else {
-      scoped_feature_list_.InitAndDisableFeature(
-          blink::features::kFileSystemAccessWriteMode);
+      scoped_feature_list_.InitWithFeatures(
+          {}, {blink::features::kFileSystemAccessWriteMode,
+               blink::features::kFileSystemAccessRevokeReadOnRemove});
     }
   }
 
diff --git a/content/browser/gpu/gpu_internals_ui.cc b/content/browser/gpu/gpu_internals_ui.cc
index 5d8535c..8482380 100644
--- a/content/browser/gpu/gpu_internals_ui.cc
+++ b/content/browser/gpu/gpu_internals_ui.cc
@@ -382,8 +382,8 @@
     {
       std::vector<std::string> names;
       std::vector<gfx::ColorSpace> color_spaces;
-      std::vector<gfx::BufferFormat> buffer_formats;
-      display_color_spaces.ToStrings(&names, &color_spaces, &buffer_formats);
+      std::vector<viz::SharedImageFormat> formats;
+      display_color_spaces.ToStrings(&names, &color_spaces, &formats);
       for (size_t i = 0; i < names.size(); ++i) {
         display_info.Append(display::BuildGpuInfoEntry(
             base::StringPrintf("Color space (%s)", names[i].c_str()),
@@ -393,7 +393,7 @@
                 .ToString()));
         display_info.Append(display::BuildGpuInfoEntry(
             base::StringPrintf("Buffer format (%s)", names[i].c_str()),
-            gfx::BufferFormatToString(buffer_formats[i])));
+            formats[i].ToString()));
       }
     }
     display_info.Append(display::BuildGpuInfoEntry(
diff --git a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
index 1a410b0..e1ed28a 100644
--- a/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/context_lost_expectations.txt
@@ -237,6 +237,9 @@
 crbug.com/338574390 [ angle-metal asan graphite-disabled intel-0x3e9b mac ] GpuNormalTermination_NewWebGLNotBlocked [ RetryOnFailure ]
 crbug.com/338574390 [ angle-metal graphite-enabled amd-0x7340 mac ] ContextLost_WebGPUBlockedAfterJSNavigation [ Slow ]
 
+# Win11 / NVIDIA RTX 4070 Super
+crbug.com/450323460 [ win11 nvidia-0x2783 ] ContextLost_WebGPUStressRequestDeviceAndRemoveLoop [ RetryOnFailure ]
+
 ###############################
 # Permanent Slow Expectations #
 ###############################
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
index a32c4bb..298ab5b4 100644
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
@@ -565,6 +565,27 @@
 crbug.com/446861923 [ android android-pixel-10 android-chromium ] Pixel_Video_MP4_Rounded_Corner [ Failure ]
 crbug.com/446861923 [ android android-pixel-10 android-chromium ] Pixel_Video_VP9 [ Failure ]
 
+# Win11/RTX 4070 Super failures
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_Canvas2DRedBox [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_Canvas2DRedBoxScrgbLinear [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_CanvasDisplaySRGBAccelerated2D [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_GpuRasterization_ConcavePaths [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasAccelerated2DWorker [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasIBRCWorker [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasTransferBeforeStyleResize [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasTransferToImageBitmap [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_PaintWorkletTransform [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_ScissorTestWithPreserveDrawingBuffer [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_WebGLGreenTriangle_NoAA_NoAlpha [ RetryOnFailure ]
+crbug.com/450326412 [ win11 nvidia-0x2783 ] Pixel_WebglResizedCanvas [ RetryOnFailure ]
+crbug.com/450326413 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasWebGLPaintAfterResize [ RetryOnFailure ]
+crbug.com/450326413 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasWebglResizeOnWorker [ RetryOnFailure ]
+crbug.com/450326413 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasWebGLSoftwareCompositing [ RetryOnFailure ]
+crbug.com/450325666 [ win11 nvidia-0x2783 ] Pixel_DirectComposition_Video_VP9_Fullsize [ RetryOnFailure ]
+crbug.com/450325666 [ win11 nvidia-0x2783 ] Pixel_OffscreenCanvasUnaccelerated2DGPUCompositing [ RetryOnFailure ]
+crbug.com/450325666 [ win11 nvidia-0x2783 ] Pixel_WebGLTextureFromWebGLReadback [ RetryOnFailure ]
+crbug.com/450325666 [ win11 nvidia-0x2783 ] Pixel_WebGPUImportVideoFrame [ RetryOnFailure ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
index 5232a450..3d71b1fc 100644
--- a/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/screenshot_sync_expectations.txt
@@ -120,6 +120,10 @@
 # Gardener 2024-04-30 - timeouts
 crbug.com/324934210 [ mac angle-metal intel-0x3e9b passthrough asan ] ScreenshotSync_SWRasterWithCanvas [ Failure ]
 
+# Win11 / NVIDIA RTX 4070 Super
+crbug.com/450325666 [ win11 nvidia-0x2783 ] ScreenshotSync_GPURasterWithCanvas [ RetryOnFailure ]
+crbug.com/450325666 [ win11 nvidia-0x2783 ] ScreenshotSync_GPURasterWithDivs [ RetryOnFailure ]
+
 #######################################################################
 # Automated Entries After This Point - Do Not Manually Add Below Here #
 #######################################################################
diff --git a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
index b5e1a3c1..8da0235 100644
--- a/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/trace_test_expectations.txt
@@ -260,6 +260,9 @@
 
 # Win11/RTX 4070 Super failures after upgrading to driver 580.88
 crbug.com/438512194 [ win11 nvidia-0x2783 ] OverlayModeTraceTest_DirectComposition_Underlay [ RetryOnFailure ]
+crbug.com/450323461 [ win11 nvidia-0x2783 ] OverlayModeTraceTest_DirectComposition_Video_VP9_YUY2 [ RetryOnFailure ]
+crbug.com/450323461 [ win11 nvidia-0x2783 ] VideoPathTraceTest_DirectComposition_Video_MP4 [ RetryOnFailure ]
+crbug.com/450323461 [ win11 nvidia-0x2783 ] VideoPathTraceTest_DirectComposition_Video_SW_Decode [ RetryOnFailure ]
 
 ###############################
 # Permanent Slow Expectations #
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
index a693991c..05178135 100644
--- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
+++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -486,6 +486,9 @@
 crbug.com/443182226 [ win nvidia angle-vulkan passthrough ] conformance/misc/shader-precision-format.html [ Failure ]
 crbug.com/443182226 [ win nvidia angle-vulkan passthrough ] conformance/uniforms/no-over-optimization-on-uniform-array-* [ Failure ]
 
+# Win11 / NVIDIA RTX 4070 Super
+crbug.com/450326413 [ win11 nvidia-0x2783 ] conformance/textures/image_bitmap_from_canvas/tex-2d-rgb-rgb-unsigned_short_5_6_5.html [ RetryOnFailure ]
+
 ####################
 # Mac failures     #
 ####################
diff --git a/extensions/browser/api/declarative_net_request/ruleset_manager.cc b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
index cdf8ae2..2b36ce05 100644
--- a/extensions/browser/api/declarative_net_request/ruleset_manager.cc
+++ b/extensions/browser/api/declarative_net_request/ruleset_manager.cc
@@ -187,7 +187,19 @@
     const net::HttpResponseHeaders* response_headers,
     bool is_incognito_context) const {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(response_headers);
+
+  if (!response_headers) {
+    // NOTE: This can happen for auth challenges from CORS preflight requests
+    // that get routed to the respective main request's handler (since they
+    // share the same `request_id`), which happens when `extraHeaders` is
+    // enabled.
+    //
+    // At this point, the main request is paused waiting for the preflight, and
+    // has not received its own headers, so `response_headers` is null. We must
+    // return early. See https://crbug.com/444248440.
+    return {};
+  }
+
   return EvaluateRequestInternal(request, response_headers,
                                  is_incognito_context);
 }
diff --git a/extensions/common/api/_permission_features.json b/extensions/common/api/_permission_features.json
index a72e301..afce21c 100644
--- a/extensions/common/api/_permission_features.json
+++ b/extensions/common/api/_permission_features.json
@@ -479,12 +479,6 @@
       "A4CC6F00ACF41015AF38F1D5C98E97C2B8B3B320",  // http://crbug.com/1483151
       "4E09F1C1EEC4D27F1F7DF18BA3643307107A7C41"   // http://crbug.com/1483151
     ]
-  },
-  {
-    "channel": "dev",
-    "extension_types": ["extension"],
-    "platforms": ["chromeos"],
-    "session_types": ["kiosk"]
   }],
   "networkingPrivate": {
     "channel": "stable",
@@ -722,20 +716,12 @@
       "extension", "legacy_packaged_app", "hosted_app", "platform_app"
     ]
   },
-  "usb": [
-    {
-      "channel": "stable",
-      "extension_types": ["platform_app"],
-      // "desktop_android" is not supported.
-      "platforms": ["chromeos", "linux", "mac", "win"]
-    },
-    {
-      "channel": "dev",
-      "extension_types": ["extension"],
-      "platforms": ["chromeos"],
-      "session_types": ["kiosk"]
-    }
-  ],
+  "usb": {
+    "channel": "stable",
+    "extension_types": ["platform_app"],
+    // "desktop_android" is not supported.
+    "platforms": ["chromeos", "linux", "mac", "win"]
+  },
   "usbDevices": [
     {
       "channel": "stable",
@@ -750,12 +736,6 @@
         "4839A26B29CD1BD021B2E126EF6D28C9CB84018B",  // http://crbug.com/710541
         "8F44FBB4474CCDF23450B166C9E83E85BD03AE24"   // http://crbug.com/710541
       ]
-    },
-    {
-      "channel": "dev",
-      "extension_types": ["extension"],
-      "platforms": ["chromeos"],
-      "session_types": ["kiosk"]
     }
   ],
   "videoCapture": [
@@ -772,17 +752,12 @@
       ]
     }
   ],
-  "virtualKeyboard": [{
+  "virtualKeyboard": {
     "channel": "stable",
     "extension_types": ["platform_app"],
     "platforms": ["chromeos"],
     "session_types": ["kiosk"]
-  }, {
-    "channel": "dev",
-    "extension_types": ["extension"],
-    "platforms": ["chromeos"],
-    "session_types": ["kiosk"]
-  }],
+  },
   "virtualKeyboardPrivate": {
     "channel": "stable",
     "extension_types": ["extension", "platform_app"],
diff --git a/gpu/command_buffer/service/dawn_caching_interface.cc b/gpu/command_buffer/service/dawn_caching_interface.cc
index 8384784c..49d5202e 100644
--- a/gpu/command_buffer/service/dawn_caching_interface.cc
+++ b/gpu/command_buffer/service/dawn_caching_interface.cc
@@ -14,6 +14,8 @@
 #include "base/trace_event/memory_dump_manager.h"
 #include "base/trace_event/memory_dump_request_args.h"
 #include "base/trace_event/trace_event.h"
+#include "components/persistent_cache/entry.h"
+#include "gpu/command_buffer/service/gpu_persistent_cache.h"
 #include "gpu/command_buffer/service/service_utils.h"
 #include "gpu/config/gpu_preferences.h"
 #include "net/base/io_buffer.h"
@@ -26,28 +28,83 @@
     : memory_cache_backend_(std::move(backend)),
       cache_blob_callback_(std::move(callback)) {}
 
+DawnCachingInterface::DawnCachingInterface(
+    scoped_refptr<detail::DawnMemoryCache> backend,
+    std::unique_ptr<GpuPersistentCache> persistent_cache)
+    : memory_cache_backend_(std::move(backend)),
+      persistent_cache_(std::move(persistent_cache)) {}
+
 DawnCachingInterface::~DawnCachingInterface() = default;
 
+void DawnCachingInterface::InitializePersistentCache(
+    persistent_cache::BackendParams backend_params) {
+  CHECK(persistent_cache_);
+  // TODO(crbug.com/399642827): PersistentCache's sqlite backend has default
+  // in-memory page cache of 2 MB.
+  // See https://www.sqlite.org/pragma.html#pragma_cache_size
+  // Since we have our own memory cache here, we might want to disable the
+  // page cache or at least reduce its max size.
+  persistent_cache_->InitializeCache(std::move(backend_params));
+}
+
 size_t DawnCachingInterface::LoadData(const void* key,
                                       size_t key_size,
                                       void* value_out,
                                       size_t value_size) {
-  if (memory_cache() == nullptr) {
+  std::string key_str(static_cast<const char*>(key), key_size);
+  if (memory_cache() != nullptr) {
+    size_t bytes_read =
+        memory_cache()->LoadData(key_str, value_out, value_size);
+    if (bytes_read > 0) {
+      return bytes_read;
+    }
+  }
+
+  if (!persistent_cache_) {
     return 0u;
   }
-  std::string key_str(static_cast<const char*>(key), key_size);
-  return memory_cache()->LoadData(key_str, value_out, value_size);
+
+  std::unique_ptr<persistent_cache::Entry> entry =
+      persistent_cache_->LoadEntry(key_str);
+  if (!entry) {
+    return 0u;
+  }
+
+  size_t bytes_copied = 0;
+  if (value_size > 0) {
+    bytes_copied = entry->CopyContentTo(
+        UNSAFE_TODO(base::span(static_cast<uint8_t*>(value_out), value_size)));
+  }
+
+  if (memory_cache()) {
+    memory_cache()->StoreData(key_str, entry->GetContentSpan().data(),
+                              entry->GetContentSize());
+  }
+
+  if (bytes_copied > 0) {
+    return bytes_copied;
+  }
+
+  return entry->GetContentSize();
 }
 
 void DawnCachingInterface::StoreData(const void* key,
                                      size_t key_size,
                                      const void* value,
                                      size_t value_size) {
-  if (memory_cache() == nullptr || value == nullptr || value_size <= 0) {
+  if (value == nullptr || value_size <= 0) {
     return;
   }
+
   std::string key_str(static_cast<const char*>(key), key_size);
-  memory_cache()->StoreData(key_str, value, value_size);
+  if (memory_cache() != nullptr) {
+    memory_cache()->StoreData(key_str, value, value_size);
+  }
+
+  if (persistent_cache_) {
+    persistent_cache_->StoreData(key_str.data(), key_str.size(), value,
+                                 value_size);
+  }
 
   // Send the cache entry to be stored on the host-side if applicable.
   if (cache_blob_callback_) {
@@ -77,25 +134,39 @@
 DawnCachingInterfaceFactory::CreateInstance(
     const gpu::GpuDiskCacheHandle& handle,
     DawnCachingInterface::CacheBlobCallback callback) {
+  return base::WrapUnique(new DawnCachingInterface(
+      GetOrCreateMemoryCache(handle), std::move(callback)));
+}
+
+std::unique_ptr<DawnCachingInterface>
+DawnCachingInterfaceFactory::CreateInstance(
+    const gpu::GpuDiskCacheHandle& handle,
+    std::unique_ptr<GpuPersistentCache> persistent_cache) {
+  return base::WrapUnique(new DawnCachingInterface(
+      GetOrCreateMemoryCache(handle), std::move(persistent_cache)));
+}
+
+std::unique_ptr<DawnCachingInterface>
+DawnCachingInterfaceFactory::CreateInstance() {
+  return base::WrapUnique(new DawnCachingInterface(backend_factory_.Run()));
+}
+
+scoped_refptr<detail::DawnMemoryCache>
+DawnCachingInterfaceFactory::GetOrCreateMemoryCache(
+    const gpu::GpuDiskCacheHandle& handle) {
   DCHECK(gpu::GetHandleType(handle) == gpu::GpuDiskCacheType::kDawnWebGPU ||
          gpu::GetHandleType(handle) == gpu::GpuDiskCacheType::kDawnGraphite);
 
   if (const auto it = backends_.find(handle); it != backends_.end()) {
-    return base::WrapUnique(
-        new DawnCachingInterface(it->second, std::move(callback)));
+    return it->second;
   }
 
   scoped_refptr<detail::DawnMemoryCache> backend = backend_factory_.Run();
   if (backend != nullptr) {
     backends_[handle] = backend;
   }
-  return base::WrapUnique(
-      new DawnCachingInterface(std::move(backend), std::move(callback)));
-}
 
-std::unique_ptr<DawnCachingInterface>
-DawnCachingInterfaceFactory::CreateInstance() {
-  return base::WrapUnique(new DawnCachingInterface(backend_factory_.Run()));
+  return backend;
 }
 
 void DawnCachingInterfaceFactory::ReleaseHandle(
diff --git a/gpu/command_buffer/service/dawn_caching_interface.h b/gpu/command_buffer/service/dawn_caching_interface.h
index 8671f23..4d0ff048 100644
--- a/gpu/command_buffer/service/dawn_caching_interface.h
+++ b/gpu/command_buffer/service/dawn_caching_interface.h
@@ -19,10 +19,14 @@
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "base/trace_event/memory_dump_provider.h"
+#include "components/persistent_cache/persistent_cache.h"
 #include "gpu/gpu_gles2_export.h"
 #include "gpu/ipc/common/gpu_disk_cache_type.h"
 
 namespace gpu {
+
+class GpuPersistentCache;
+
 namespace webgpu {
 
 class DawnCachingInterfaceFactory;
@@ -88,15 +92,9 @@
 
 }  // namespace detail
 
-// Provides a wrapper class around an in-memory DawnMemoryCache. This class was
-// originally designed to handle both disk and in-memory cache backends, but
-// because it lives on the GPU process and does not have permissions (due to
-// sandbox restrictions) to disk, the disk functionality was removed. Should it
-// become necessary to provide interfaces over a disk level disk_cache::Backend,
-// please refer to the file history for reference. Note that the big difference
-// between in-memory and disk backends are the sync vs async nature of the two
-// respectively. Because we are only handling in-memory backends now, the logic
-// can be simplified to handle everything synchronously.
+// Provides a wrapper class around an in-memory DawnMemoryCache and a disk
+// cache. The disk cache controller can be provided either via a
+// CacheBlobCallback or a GpuPersistentCache pointer.
 class GPU_GLES2_EXPORT DawnCachingInterface
     : public dawn::platform::CachingInterface {
  public:
@@ -106,11 +104,13 @@
 
   ~DawnCachingInterface() override;
 
+  void InitializePersistentCache(
+      persistent_cache::BackendParams backend_params);
+
   size_t LoadData(const void* key,
                   size_t key_size,
                   void* value_out,
                   size_t value_size) override;
-
   void StoreData(const void* key,
                  size_t key_size,
                  const void* value,
@@ -128,12 +128,21 @@
   // the factory.
   explicit DawnCachingInterface(scoped_refptr<detail::DawnMemoryCache> backend,
                                 CacheBlobCallback callback = {});
+  explicit DawnCachingInterface(
+      scoped_refptr<detail::DawnMemoryCache> backend,
+      std::unique_ptr<GpuPersistentCache> persistent_cache);
 
   // Caching interface owns a reference to the backend.
   scoped_refptr<detail::DawnMemoryCache> memory_cache_backend_ = nullptr;
 
   // The callback provides ability to store cache entries to persistent disk.
   CacheBlobCallback cache_blob_callback_;
+
+  // The interface that allows storing and loading cache entries directly
+  // to/from disk.
+  // TODO(crbug.com/399642827): Remove the above callback once we migrate
+  // everything to use GpuPersistentCache API.
+  std::unique_ptr<GpuPersistentCache> persistent_cache_;
 };
 
 // Factory class for producing and managing DawnCachingInterfaces.
@@ -158,6 +167,10 @@
       const gpu::GpuDiskCacheHandle& handle,
       DawnCachingInterface::CacheBlobCallback callback = {});
 
+  std::unique_ptr<DawnCachingInterface> CreateInstance(
+      const gpu::GpuDiskCacheHandle& handle,
+      std::unique_ptr<GpuPersistentCache> persistent_cache);
+
   // Returns a pointer to a DawnCachingInterface that owns the in memory
   // backend. This is used for incognito cases where the cache should not be
   // persisted to disk.
@@ -182,6 +195,9 @@
                     base::trace_event::ProcessMemoryDump* pmd) override;
 
  private:
+  scoped_refptr<detail::DawnMemoryCache> GetOrCreateMemoryCache(
+      const gpu::GpuDiskCacheHandle& handle);
+
   // Creates a default backend for assignment.
   static scoped_refptr<detail::DawnMemoryCache> CreateDefaultInMemoryBackend();
 
diff --git a/gpu/command_buffer/service/dawn_caching_interface_unittest.cc b/gpu/command_buffer/service/dawn_caching_interface_unittest.cc
index 9041d2c..28b22ce 100644
--- a/gpu/command_buffer/service/dawn_caching_interface_unittest.cc
+++ b/gpu/command_buffer/service/dawn_caching_interface_unittest.cc
@@ -12,7 +12,12 @@
 #include <string>
 #include <string_view>
 
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
 #include "base/test/scoped_feature_list.h"
+#include "components/persistent_cache/backend_params.h"
+#include "components/persistent_cache/sqlite/vfs/sandboxed_file.h"
+#include "gpu/command_buffer/service/gpu_persistent_cache.h"
 #include "gpu/command_buffer/service/mocks.h"
 #include "gpu/config/gpu_finch_features.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -292,5 +297,80 @@
   }
 }
 
+// Verifies that data stored in a persistent cache can be loaded back.
+TEST_F(DawnCachingInterfaceTest, StoreAndLoadWithPersistentCache) {
+  base::ScopedTempDir temp_dir;
+  ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+  auto shared_lock = base::UnsafeSharedMemoryRegion::Create(
+      sizeof(persistent_cache::LockState));
+  ASSERT_TRUE(shared_lock.IsValid());
+  auto OpenPersistentCache =
+      [&temp_dir, &shared_lock]() -> std::unique_ptr<GpuPersistentCache> {
+    auto db_path = temp_dir.GetPath().AppendASCII("test.db");
+    auto journal_path = temp_dir.GetPath().AppendASCII("test.journal");
+
+    persistent_cache::BackendParams params;
+    params.type = persistent_cache::BackendType::kSqlite;
+    params.db_file =
+        base::File(db_path, base::File::FLAG_OPEN_ALWAYS |
+                                base::File::FLAG_READ | base::File::FLAG_WRITE);
+    params.journal_file = base::File(
+        journal_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
+                          base::File::FLAG_WRITE);
+    params.shared_lock = shared_lock.Duplicate();
+    CHECK(params.db_file.IsValid());
+    CHECK(params.journal_file.IsValid());
+
+    auto persistent_cache = std::make_unique<GpuPersistentCache>("Test");
+    persistent_cache->InitializeCache(std::move(params));
+    return persistent_cache;
+  };
+
+  // Store data to the persistent cache via store interface.
+  {
+    scoped_refptr<detail::DawnMemoryCache> memory_cache =
+        base::MakeRefCounted<detail::DawnMemoryCache>(1024);
+    DawnCachingInterfaceFactory store_factory(base::BindRepeating(
+        [](scoped_refptr<detail::DawnMemoryCache> cache) { return cache; },
+        memory_cache));
+    auto store_interface =
+        store_factory.CreateInstance(handle_, OpenPersistentCache());
+    store_interface->StoreData(kKey.data(), kKeySize, kData.data(), kDataSize);
+
+    // Check that the entry exists in the memory cache.
+    char buffer[kDataSize];
+    EXPECT_EQ(kDataSize, memory_cache->LoadData(std::string(kKey), nullptr, 0));
+    EXPECT_EQ(kDataSize,
+              memory_cache->LoadData(std::string(kKey), buffer, kDataSize));
+    EXPECT_EQ(0, memcmp(buffer, kData.data(), kDataSize));
+  }
+
+  // Use the same persistent cache but with different memory cache.
+  {
+    scoped_refptr<detail::DawnMemoryCache> memory_cache2 =
+        base::MakeRefCounted<detail::DawnMemoryCache>(1024);
+    DawnCachingInterfaceFactory load_factory(base::BindRepeating(
+        [](scoped_refptr<detail::DawnMemoryCache> cache) { return cache; },
+        memory_cache2));
+    auto load_interface =
+        load_factory.CreateInstance(handle_, OpenPersistentCache());
+
+    EXPECT_EQ(0u, memory_cache2->LoadData(std::string(kKey), nullptr, 0));
+
+    // Verify that we can query the existing entry.
+    char buffer[kDataSize];
+    EXPECT_EQ(kDataSize,
+              load_interface->LoadData(kKey.data(), kKeySize, nullptr, 0));
+    EXPECT_EQ(kDataSize, load_interface->LoadData(kKey.data(), kKeySize, buffer,
+                                                  kDataSize));
+    EXPECT_EQ(0, memcmp(buffer, kData.data(), kDataSize));
+
+    // Check that the memory cache now contains the same entry after the
+    // LoadData() call above
+    EXPECT_EQ(kDataSize,
+              memory_cache2->LoadData(std::string(kKey), nullptr, 0));
+  }
+}
+
 }  // namespace
 }  // namespace gpu::webgpu
diff --git a/gpu/command_buffer/service/dawn_context_provider.cc b/gpu/command_buffer/service/dawn_context_provider.cc
index a0f6ae6..1ce5b762 100644
--- a/gpu/command_buffer/service/dawn_context_provider.cc
+++ b/gpu/command_buffer/service/dawn_context_provider.cc
@@ -444,7 +444,7 @@
                   const GpuDriverBugWorkarounds& workarounds,
                   DawnContextProvider::ValidateAdapterFn validate_adapter_fn);
   void SetCachingInterface(
-      std::unique_ptr<dawn::platform::CachingInterface> caching_interface);
+      std::unique_ptr<webgpu::DawnCachingInterface> caching_interface);
 
   wgpu::Device GetDevice() const { return device_; }
   wgpu::BackendType backend_type() const { return backend_type_; }
@@ -456,7 +456,7 @@
 
   webgpu::DawnPlatform* GetDawnPlatform() { return &platform_; }
 
-  dawn::platform::CachingInterface* GetCachingInterface() {
+  webgpu::DawnCachingInterface* GetCachingInterface() {
     return caching_interface_.get();
   }
 
@@ -670,7 +670,7 @@
   bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
                     base::trace_event::ProcessMemoryDump* pmd) override;
 
-  std::unique_ptr<dawn::platform::CachingInterface> caching_interface_;
+  std::unique_ptr<webgpu::DawnCachingInterface> caching_interface_;
 
   Platform platform_;
   std::unique_ptr<webgpu::DawnInstance> instance_;
@@ -982,7 +982,7 @@
 }
 
 void DawnSharedContext::SetCachingInterface(
-    std::unique_ptr<dawn::platform::CachingInterface> caching_interface) {
+    std::unique_ptr<webgpu::DawnCachingInterface> caching_interface) {
   CHECK(!caching_interface_);
   caching_interface_ = std::move(caching_interface);
 }
@@ -1239,14 +1239,13 @@
 }
 
 void DawnContextProvider::SetCachingInterface(
-    std::unique_ptr<dawn::platform::CachingInterface> caching_interface) {
+    std::unique_ptr<webgpu::DawnCachingInterface> caching_interface) {
   CHECK(dawn_shared_context_->HasOneRef());
   CHECK(!graphite_shared_context_);
   dawn_shared_context_->SetCachingInterface(std::move(caching_interface));
 }
 
-dawn::platform::CachingInterface* DawnContextProvider::GetCachingInterface()
-    const {
+webgpu::DawnCachingInterface* DawnContextProvider::GetCachingInterface() const {
   return dawn_shared_context_->GetCachingInterface();
 }
 
diff --git a/gpu/command_buffer/service/dawn_context_provider.h b/gpu/command_buffer/service/dawn_context_provider.h
index 013449e..6a8adfe 100644
--- a/gpu/command_buffer/service/dawn_context_provider.h
+++ b/gpu/command_buffer/service/dawn_context_provider.h
@@ -86,9 +86,9 @@
   // Sets the caching interface. This must be called before graphite context
   // is created and before device is shared with any other threads.
   void SetCachingInterface(
-      std::unique_ptr<dawn::platform::CachingInterface> caching_interface);
+      std::unique_ptr<webgpu::DawnCachingInterface> caching_interface);
 
-  dawn::platform::CachingInterface* GetCachingInterface() const;
+  webgpu::DawnCachingInterface* GetCachingInterface() const;
 
   bool use_thread_safe_shared_context() const;
 
diff --git a/gpu/command_buffer/service/gpu_persistent_cache.cc b/gpu/command_buffer/service/gpu_persistent_cache.cc
index dbff0c2..2957d7d 100644
--- a/gpu/command_buffer/service/gpu_persistent_cache.cc
+++ b/gpu/command_buffer/service/gpu_persistent_cache.cc
@@ -71,9 +71,25 @@
                                     size_t key_size,
                                     void* value,
                                     size_t value_size) {
+  std::string_view key_str(static_cast<const char*>(key), key_size);
+  std::unique_ptr<persistent_cache::Entry> entry = LoadEntry(key_str);
+  if (!entry) {
+    return 0;
+  }
+
+  if (value_size > 0) {
+    return entry->CopyContentTo(
+        UNSAFE_TODO(base::span(static_cast<uint8_t*>(value), value_size)));
+  }
+
+  return entry->GetContentSize();
+}
+
+std::unique_ptr<persistent_cache::Entry> GpuPersistentCache::LoadEntry(
+    std::string_view key) {
   ScopedHistogramTimer timer(GetHistogramName("Load"));
   SCOPED_LOCK(lock_);
-  TRACE_EVENT1("gpu", "GpuPersistentCache::LoadData", "persistent_cache_",
+  TRACE_EVENT1("gpu", "GpuPersistentCache::LoadEntry", "persistent_cache_",
                !!persistent_cache_);
 
   // Track cache available for the 1st kMaxLoadStoreForTrackingCacheAvailable
@@ -85,23 +101,11 @@
 
   if (!persistent_cache_) {
     timer.SetEnabled(false);
-    return 0;
+    return nullptr;
   }
 
-  std::string_view key_str(static_cast<const char*>(key), key_size);
-  std::unique_ptr<persistent_cache::Entry> entry =
-      persistent_cache_->Find(key_str);
+  return persistent_cache_->Find(key);
 
-  if (!entry) {
-    return 0;
-  }
-
-  if (value_size > 0) {
-    return entry->CopyContentTo(
-        UNSAFE_TODO(base::span(static_cast<uint8_t*>(value), value_size)));
-  }
-
-  return entry->GetContentSize();
 }
 
 void GpuPersistentCache::StoreData(const void* key,
diff --git a/gpu/command_buffer/service/gpu_persistent_cache.h b/gpu/command_buffer/service/gpu_persistent_cache.h
index d066973..4100aa1 100644
--- a/gpu/command_buffer/service/gpu_persistent_cache.h
+++ b/gpu/command_buffer/service/gpu_persistent_cache.h
@@ -18,7 +18,8 @@
 
 namespace persistent_cache {
 class PersistentCache;
-}
+class Entry;
+}  // namespace persistent_cache
 
 namespace gpu {
 
@@ -44,6 +45,8 @@
                  const void* value,
                  size_t value_size) override;
 
+  std::unique_ptr<persistent_cache::Entry> LoadEntry(std::string_view key);
+
  private:
   std::string GetHistogramName(std::string_view metric) const;
 
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
index cc818010..dd81502 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -1006,7 +1006,7 @@
     SharedImageManager* manager,
     MemoryTypeTracker* tracker,
     VideoDevice device) {
-  if (texture_d3d11_device_ != device && !dxgi_shared_handle_state_) {
+  if (texture_d3d11_device_ != device) {
     // Readback is the only option for a caller cannot create a representation
     // for this shared image.  When the caller cannot use a shared device
     // (GL/Ganesh) create a copy since this is much more efficient than forcing
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
index 0aa7f21..08f3da2 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.cc
@@ -12,7 +12,10 @@
 
 #include "base/memory/shared_memory_mapping.h"
 #include "base/strings/string_number_conversions.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/trace_event/trace_event.h"
 #include "base/win/scoped_handle.h"
+#include "components/viz/common/resources/shared_image_format_utils.h"
 #include "gpu/command_buffer/common/shared_image_usage.h"
 #include "gpu/command_buffer/service/dxgi_shared_handle_manager.h"
 #include "gpu/command_buffer/service/shared_image/d3d_image_backing.h"
@@ -20,8 +23,10 @@
 #include "gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h"
 #include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
 #include "gpu/config/gpu_finch_features.h"
+#include "gpu/ipc/common/dxgi_helpers.h"
 #include "ui/gfx/buffer_format_util.h"
 #include "ui/gfx/buffer_types.h"
+#include "ui/gfx/buffer_usage_util.h"
 #include "ui/gfx/color_space_win.h"
 #include "ui/gl/direct_composition_support.h"
 #include "ui/gl/gl_angle_util_win.h"
@@ -225,13 +230,107 @@
     D3DImageBackingFactory::SwapChainBackings&&) = default;
 
 // static
+gfx::GpuMemoryBufferHandle
+D3DImageBackingFactory::CreateGpuMemoryBufferHandleOnIO(
+    scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+    const gfx::Size& size,
+    viz::SharedImageFormat format,
+    gfx::BufferUsage usage) {
+  gfx::GpuMemoryBufferHandle result;
+  base::WaitableEvent event;
+
+  io_runner->PostTask(
+      FROM_HERE, base::BindOnce(
+                     [](gfx::GpuMemoryBufferHandle* out_gmb_handle,
+                        base::WaitableEvent* waitable_event,
+                        scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+                        const gfx::Size& size, viz::SharedImageFormat format,
+                        gfx::BufferUsage usage) {
+                       *out_gmb_handle =
+                           D3DImageBackingFactory::CreateGpuMemoryBufferHandle(
+                               io_runner, size, format, usage);
+
+                       waitable_event->Signal();
+                     },
+                     &result, &event, io_runner, size, format, usage));
+
+  event.Wait();
+
+  return result;
+}
+
+// static
 gfx::GpuMemoryBufferHandle D3DImageBackingFactory::CreateGpuMemoryBufferHandle(
     scoped_refptr<base::SingleThreadTaskRunner> io_runner,
     const gfx::Size& size,
     viz::SharedImageFormat format,
     gfx::BufferUsage usage) {
-  return GetGpuMemoryBufferFactoryDXGI(io_runner)->CreateNativeGmbHandle(
-      size, format, usage);
+  if (io_runner && !io_runner->BelongsToCurrentThread()) {
+    // Thread-hop is required!
+    return CreateGpuMemoryBufferHandleOnIO(io_runner, size, format, usage);
+  }
+
+  TRACE_EVENT0("gpu", "D3DImageBackingFactory::CrceateGpuMemoryBufferHandle");
+
+  gfx::GpuMemoryBufferHandle handle;
+  auto d3d11_device =
+      GetGpuMemoryBufferFactoryDXGI(io_runner)->GetOrCreateD3D11Device();
+  if (!d3d11_device) {
+    return handle;
+  }
+
+  DXGI_FORMAT dxgi_format = gpu::ToDXGIFormat(format);
+  if (dxgi_format == DXGI_FORMAT_UNKNOWN) {
+    return handle;
+  }
+
+  auto buffer_size = viz::SharedMemorySizeForSharedImageFormat(format, size);
+  if (!buffer_size) {
+    return handle;
+  }
+
+  // We are binding as a shader resource and render target regardless of usage,
+  // so make sure that the usage is one that we support.
+  DCHECK(usage == gfx::BufferUsage::GPU_READ ||
+         usage == gfx::BufferUsage::SCANOUT ||
+         usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE)
+      << "Incorrect usage, usage=" << gfx::BufferUsageToString(usage);
+
+  D3D11_TEXTURE2D_DESC desc = {
+      static_cast<UINT>(size.width()),
+      static_cast<UINT>(size.height()),
+      1,
+      1,
+      dxgi_format,
+      {1, 0},
+      D3D11_USAGE_DEFAULT,
+      D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
+      0,
+      D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
+          D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
+
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
+
+  if (FAILED(d3d11_device->CreateTexture2D(&desc, nullptr, &d3d11_texture))) {
+    return handle;
+  }
+
+  Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
+  if (FAILED(d3d11_texture.As(&dxgi_resource))) {
+    return handle;
+  }
+
+  HANDLE texture_handle;
+  if (FAILED(dxgi_resource->CreateSharedHandle(
+          nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
+          nullptr, &texture_handle))) {
+    return handle;
+  }
+
+  handle = gfx::GpuMemoryBufferHandle(
+      gfx::DXGIHandle(base::win::ScopedHandle(texture_handle)));
+
+  return handle;
 }
 
 // static
@@ -239,9 +338,23 @@
     scoped_refptr<base::SingleThreadTaskRunner> io_runner,
     gfx::GpuMemoryBufferHandle buffer_handle,
     base::UnsafeSharedMemoryRegion shared_memory) {
-  return GetGpuMemoryBufferFactoryDXGI(io_runner)
-      ->FillSharedMemoryRegionWithBufferContents(std::move(buffer_handle),
-                                                 std::move(shared_memory));
+  DCHECK_EQ(buffer_handle.type, gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE);
+  auto* gmb_factory = GetGpuMemoryBufferFactoryDXGI(io_runner);
+
+  auto d3d11_device = gmb_factory->GetOrCreateD3D11Device();
+  if (!d3d11_device) {
+    return false;
+  }
+
+  base::WritableSharedMemoryMapping mapping = shared_memory.Map();
+  if (!mapping.IsValid()) {
+    return false;
+  }
+
+  return CopyDXGIBufferToShMem(buffer_handle.dxgi_handle().buffer_handle(),
+                               mapping.GetMemoryAsSpan<uint8_t>(),
+                               d3d11_device.Get(),
+                               &gmb_factory->staging_texture());
 }
 
 // static
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
index a320320..686e1b74 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing_factory.h
@@ -148,6 +148,12 @@
   }
 
  private:
+  static gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandleOnIO(
+      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
+      const gfx::Size& size,
+      viz::SharedImageFormat format,
+      gfx::BufferUsage usage);
+
   std::unique_ptr<SharedImageBacking> CreateSharedBufferD3D12(
       const Mailbox& mailbox,
       const gfx::Size& size,
diff --git a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.cc b/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.cc
index e0b9491..1820025 100644
--- a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.cc
+++ b/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.cc
@@ -4,20 +4,8 @@
 
 #include "gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h"
 
-#include <vector>
-
-#include "base/memory/unsafe_shared_memory_region.h"
-#include "base/synchronization/waitable_event.h"
 #include "base/task/single_thread_task_runner.h"
-#include "base/trace_event/trace_event.h"
-#include "components/viz/common/resources/shared_image_format_utils.h"
-#include "gpu/command_buffer/service/shared_image/shared_image_format_service_utils.h"
-#include "gpu/ipc/common/dxgi_helpers.h"
-#include "ui/gfx/buffer_format_util.h"
-#include "ui/gfx/buffer_types.h"
-#include "ui/gfx/buffer_usage_util.h"
 #include "ui/gl/gl_angle_util_win.h"
-#include "ui/gl/gl_bindings.h"
 
 namespace gpu {
 
@@ -110,124 +98,4 @@
   return d3d11_device_;
 }
 
-gfx::GpuMemoryBufferHandle
-GpuMemoryBufferFactoryDXGI::CreateNativeGmbHandleOnIO(
-    const gfx::Size& size,
-    viz::SharedImageFormat format,
-    gfx::BufferUsage usage) {
-  DCHECK(io_runner_);
-
-  gfx::GpuMemoryBufferHandle result;
-  base::WaitableEvent event;
-
-  io_runner_->PostTask(
-      FROM_HERE,
-      base::BindOnce(
-          [](gfx::GpuMemoryBufferHandle* out_gmb_handle,
-             base::WaitableEvent* waitable_event,
-             GpuMemoryBufferFactoryDXGI* factory, const gfx::Size& size,
-             viz::SharedImageFormat format, gfx::BufferUsage usage) {
-            *out_gmb_handle =
-                factory->CreateNativeGmbHandle(size, format, usage);
-
-            waitable_event->Signal();
-          },
-          &result, &event, this, size, format, usage));
-
-  event.Wait();
-
-  return result;
-}
-
-gfx::GpuMemoryBufferHandle GpuMemoryBufferFactoryDXGI::CreateNativeGmbHandle(
-    const gfx::Size& size,
-    viz::SharedImageFormat format,
-    gfx::BufferUsage usage) {
-  if (io_runner_ && !io_runner_->BelongsToCurrentThread()) {
-    // Thread-hop is required!
-    return CreateNativeGmbHandleOnIO(size, format, usage);
-  }
-
-  TRACE_EVENT0("gpu", "GpuMemoryBufferFactoryDXGI::CreateNativeGmbHandle");
-
-  gfx::GpuMemoryBufferHandle handle;
-  auto d3d11_device = GetOrCreateD3D11Device();
-  if (!d3d11_device) {
-    return handle;
-  }
-
-  DXGI_FORMAT dxgi_format = gpu::ToDXGIFormat(format);
-  if (dxgi_format == DXGI_FORMAT_UNKNOWN) {
-    return handle;
-  }
-
-  auto buffer_size = viz::SharedMemorySizeForSharedImageFormat(format, size);
-  if (!buffer_size) {
-    return handle;
-  }
-
-  // We are binding as a shader resource and render target regardless of usage,
-  // so make sure that the usage is one that we support.
-  DCHECK(usage == gfx::BufferUsage::GPU_READ ||
-         usage == gfx::BufferUsage::SCANOUT ||
-         usage == gfx::BufferUsage::SCANOUT_CPU_READ_WRITE)
-      << "Incorrect usage, usage=" << gfx::BufferUsageToString(usage);
-
-  D3D11_TEXTURE2D_DESC desc = {
-      static_cast<UINT>(size.width()),
-      static_cast<UINT>(size.height()),
-      1,
-      1,
-      dxgi_format,
-      {1, 0},
-      D3D11_USAGE_DEFAULT,
-      D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET,
-      0,
-      D3D11_RESOURCE_MISC_SHARED_NTHANDLE |
-          D3D11_RESOURCE_MISC_SHARED_KEYEDMUTEX};
-
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> d3d11_texture;
-
-  if (FAILED(d3d11_device->CreateTexture2D(&desc, nullptr, &d3d11_texture))) {
-    return handle;
-  }
-
-  Microsoft::WRL::ComPtr<IDXGIResource1> dxgi_resource;
-  if (FAILED(d3d11_texture.As(&dxgi_resource))) {
-    return handle;
-  }
-
-  HANDLE texture_handle;
-  if (FAILED(dxgi_resource->CreateSharedHandle(
-          nullptr, DXGI_SHARED_RESOURCE_READ | DXGI_SHARED_RESOURCE_WRITE,
-          nullptr, &texture_handle))) {
-    return handle;
-  }
-
-  handle = gfx::GpuMemoryBufferHandle(
-      gfx::DXGIHandle(base::win::ScopedHandle(texture_handle)));
-
-  return handle;
-}
-
-bool GpuMemoryBufferFactoryDXGI::FillSharedMemoryRegionWithBufferContents(
-    gfx::GpuMemoryBufferHandle buffer_handle,
-    base::UnsafeSharedMemoryRegion shared_memory) {
-  DCHECK_EQ(buffer_handle.type, gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE);
-
-  auto d3d11_device = GetOrCreateD3D11Device();
-  if (!d3d11_device) {
-    return false;
-  }
-
-  base::WritableSharedMemoryMapping mapping = shared_memory.Map();
-  if (!mapping.IsValid()) {
-    return false;
-  }
-
-  return CopyDXGIBufferToShMem(buffer_handle.dxgi_handle().buffer_handle(),
-                               mapping.GetMemoryAsSpan<uint8_t>(),
-                               d3d11_device.Get(), &staging_texture_);
-}
-
 }  // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h b/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h
index 8891eb2..2db15b8 100644
--- a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h
+++ b/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h
@@ -36,22 +36,12 @@
   GpuMemoryBufferFactoryDXGI& operator=(const GpuMemoryBufferFactoryDXGI&) =
       delete;
 
-  gfx::GpuMemoryBufferHandle CreateNativeGmbHandle(
-      const gfx::Size& size,
-      viz::SharedImageFormat format,
-      gfx::BufferUsage usage);
-  bool FillSharedMemoryRegionWithBufferContents(
-      gfx::GpuMemoryBufferHandle buffer_handle,
-      base::UnsafeSharedMemoryRegion shared_memory);
+  Microsoft::WRL::ComPtr<ID3D11Device> GetOrCreateD3D11Device();
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture() {
+    return staging_texture_;
+  }
 
  private:
-  Microsoft::WRL::ComPtr<ID3D11Device> GetOrCreateD3D11Device();
-
-  gfx::GpuMemoryBufferHandle CreateNativeGmbHandleOnIO(
-      const gfx::Size& size,
-      viz::SharedImageFormat format,
-      gfx::BufferUsage usage);
-
   Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_
       GUARDED_BY_CONTEXT(thread_checker_);
 
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc
index 841443d7..e057ed5 100644
--- a/gpu/config/gpu_info_collector.cc
+++ b/gpu/config/gpu_info_collector.cc
@@ -91,7 +91,6 @@
 scoped_refptr<gl::GLContext> InitializeGLContext(gl::GLSurface* surface) {
   TRACE_EVENT("gpu,startup", "gpu_info_collector::InitializeGLContext");
   gl::GLContextAttribs attribs;
-  attribs.client_major_es_version = 2;
   scoped_refptr<gl::GLContext> context(
       gl::init::CreateGLContext(nullptr, surface, attribs));
   if (!context.get()) {
diff --git a/internal b/internal
index a60d46c..796b60e 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit a60d46ccb6f87592fb259207f7a7dc29797258fe
+Subproject commit 796b60e971aab3ab6e82cb1514b01b17a06c62dc
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 86587e0..1ee56132 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -297,6 +297,12 @@
       <message name="IDS_IOS_AI_HUB_POPUP_BLOCKER_LABEL" desc="The button label for the Pop-up blocker feature of the AI hub.">
         Pop-ups blocked
       </message>
+      <message name="IDS_IOS_AI_HUB_PRICE_TRACKING_BUTTON_LABEL" desc="The button label for tracking prices in the Price tracking feature of the AI hub.">
+        Tracking
+      </message>
+      <message name="IDS_IOS_AI_HUB_PRICE_TRACKING_LABEL" desc="The label for the Price tracking feature of the AI hub.">
+        Price history
+      </message>
       <message name="IDS_IOS_AI_HUB_READER_MODE_LABEL" desc="The button label for the Reader mode entry point of the AI hub.">
         Reading Mode
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_BUTTON_LABEL.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_BUTTON_LABEL.png.sha1
new file mode 100644
index 0000000..407bfa1
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_BUTTON_LABEL.png.sha1
@@ -0,0 +1 @@
+0841787bbbfcecc18f82e5c0efbde2176d07340d
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_LABEL.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_LABEL.png.sha1
new file mode 100644
index 0000000..407bfa1
--- /dev/null
+++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_AI_HUB_PRICE_TRACKING_LABEL.png.sha1
@@ -0,0 +1 @@
+0841787bbbfcecc18f82e5c0efbde2176d07340d
\ No newline at end of file
diff --git a/ios/chrome/browser/fullscreen/ui_bundled/test/test_fullscreen_controller.h b/ios/chrome/browser/fullscreen/ui_bundled/test/test_fullscreen_controller.h
index 9af4c2b2..ef64c36 100644
--- a/ios/chrome/browser/fullscreen/ui_bundled/test/test_fullscreen_controller.h
+++ b/ios/chrome/browser/fullscreen/ui_bundled/test/test_fullscreen_controller.h
@@ -72,7 +72,7 @@
 
  private:
   // The model.
-  std::unique_ptr<FullscreenModel> model_ = std::make_unique<FullscreenModel>();
+  std::unique_ptr<FullscreenModel> model_;
   // The broadcaster.
   ChromeBroadcaster* broadcaster_ = nil;
   // The observers.
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
index cc02c31..6562954 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/BUILD.gn
@@ -10,11 +10,13 @@
     "page_action_menu_mediator.mm",
   ]
   deps = [
+    "//components/content_settings/core/browser",
     "//components/prefs",
     "//components/search",
     "//components/search_engines",
     "//components/signin/public/identity_manager",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/content_settings/model",
     "//ios/chrome/browser/dom_distiller/model",
     "//ios/chrome/browser/intelligence/bwg/coordinator",
     "//ios/chrome/browser/intelligence/bwg/model",
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
index 09d3e7f..33405b0c 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_coordinator.h"
 
+#import "ios/chrome/browser/content_settings/model/host_content_settings_map_factory.h"
 #import "ios/chrome/browser/dom_distiller/model/distiller_service_factory.h"
 #import "ios/chrome/browser/intelligence/bwg/model/bwg_service_factory.h"
 #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h"
@@ -52,13 +53,17 @@
 
   ReaderModeTabHelper* readerModeTabHelper =
       ReaderModeTabHelper::FromWebState(activeWebState);
+
+  HostContentSettingsMap* hostContentSettingsMap =
+      ios::HostContentSettingsMapFactory::GetForProfile(self.profile);
   _mediator = [[PageActionMenuMediator alloc]
-         initWithWebState:activeWebState
-       profilePrefService:self.profile->GetPrefs()
-       templateURLService:ios::TemplateURLServiceFactory::GetForProfile(
-                              self.profile)
-               BWGService:BwgServiceFactory::GetForProfile(self.profile)
-      readerModeTabHelper:readerModeTabHelper];
+            initWithWebState:activeWebState
+          profilePrefService:self.profile->GetPrefs()
+          templateURLService:ios::TemplateURLServiceFactory::GetForProfile(
+                                 self.profile)
+                  BWGService:BwgServiceFactory::GetForProfile(self.profile)
+         readerModeTabHelper:readerModeTabHelper
+      hostContentSettingsMap:hostContentSettingsMap];
 
   id<PageActionMenuCommands> pageActionMenuHandler = HandlerForProtocol(
       self.browser->GetCommandDispatcher(), PageActionMenuCommands);
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h
index 419912c2..a7f4113 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h
@@ -14,6 +14,7 @@
 class PrefService;
 class ReaderModeTabHelper;
 class TemplateURLService;
+class HostContentSettingsMap;
 
 @protocol PageActionMenuCommands;
 
@@ -30,6 +31,7 @@
               templateURLService:(TemplateURLService*)templateURLService
                       BWGService:(BwgService*)BWGService
              readerModeTabHelper:(ReaderModeTabHelper*)readerModeTabHelper
+          hostContentSettingsMap:(HostContentSettingsMap*)hostContentSettingsMap
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm
index af63d2ce..149198e 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm
+++ b/ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/intelligence/page_action_menu/coordinator/page_action_menu_mediator.h"
 
 #import "base/strings/sys_string_conversions.h"
+#import "components/content_settings/core/browser/host_content_settings_map.h"
 #import "components/prefs/pref_service.h"
 #import "components/search/search.h"
 #import "components/search_engines/template_url_service.h"
@@ -55,13 +56,18 @@
 
   // The tab helper for Reader mode.
   raw_ptr<ReaderModeTabHelper> _readerModeTabHelper;
+
+  // The host content settings map for managing site permissions.
+  raw_ptr<HostContentSettingsMap> _hostContentSettingsMap;
 }
 
 - (instancetype)initWithWebState:(web::WebState*)webState
               profilePrefService:(PrefService*)profilePrefs
               templateURLService:(TemplateURLService*)templateURLService
                       BWGService:(BwgService*)BWGService
-             readerModeTabHelper:(ReaderModeTabHelper*)readerModeTabHelper {
+             readerModeTabHelper:(ReaderModeTabHelper*)readerModeTabHelper
+          hostContentSettingsMap:
+              (HostContentSettingsMap*)hostContentSettingsMap {
   self = [super init];
   if (self) {
     _webState = webState;
@@ -69,6 +75,7 @@
     _templateURLService = templateURLService;
     _BWGService = BWGService;
     _readerModeTabHelper = readerModeTabHelper;
+    _hostContentSettingsMap = hostContentSettingsMap;
     _webStateObserver = std::make_unique<web::WebStateObserverBridge>(self);
     _webState->AddObserver(_webStateObserver.get());
   }
@@ -144,9 +151,23 @@
       return state == web::PermissionStateAllowed;
     }
     case PageActionMenuPopupBlocker: {
+      if (!_hostContentSettingsMap) {
+        return NO;
+      }
+      GURL url = _webState->GetLastCommittedURL();
+      ContentSetting setting = _hostContentSettingsMap->GetContentSetting(
+          url, url, ContentSettingsType::POPUPS);
+
+      // Show row only if blocking is active AND there are blocked popups.
       BlockedPopupTabHelper* helper =
           BlockedPopupTabHelper::GetOrCreateForWebState(_webState);
-      return helper && helper->GetBlockedPopupCount() > 0;
+      bool hasBlockedPopups = helper && helper->GetBlockedPopupCount() > 0;
+
+      return setting == CONTENT_SETTING_BLOCK && hasBlockedPopups;
+    }
+    case PageActionMenuPriceTracking: {
+      // TODO(crbug.com/447143165): Add price tracking detection.
+      return NO;
     }
   }
 }
@@ -203,6 +224,7 @@
       break;
     case PageActionMenuTranslate:
     case PageActionMenuPopupBlocker:
+    case PageActionMenuPriceTracking:
       CHECK(false)
           << "revokePermission called with non-permission feature type: "
           << featureType;
@@ -283,10 +305,56 @@
     micFeature.toggleState = YES;
     [features addObject:micFeature];
   }
+  // Price tracking feature.
+  if ([self isFeatureAvailable:PageActionMenuPriceTracking]) {
+    PageActionMenuFeature* priceTrackingFeature = [[PageActionMenuFeature alloc]
+        initWithFeatureType:PageActionMenuPriceTracking
+                      title:l10n_util::GetNSString(
+                                IDS_IOS_AI_HUB_PRICE_TRACKING_LABEL)
+                       icon:CustomSymbolWithPointSize(kDownTrendSymbol,
+                                                      kFeatureRowIconSize)
+                 actionType:PageActionMenuButtonAction];
+    priceTrackingFeature.actionText =
+        l10n_util::GetNSString(IDS_IOS_AI_HUB_PRICE_TRACKING_BUTTON_LABEL);
+    [features addObject:priceTrackingFeature];
+  }
 
   return features;
 }
 
+- (void)allowBlockedPopups {
+  if (!_webState || !_hostContentSettingsMap) {
+    return;
+  }
+
+  BlockedPopupTabHelper* helper =
+      BlockedPopupTabHelper::GetOrCreateForWebState(_webState);
+  if (!helper) {
+    return;
+  }
+
+  // Get the blocked popups.
+  std::vector<BlockedPopupTabHelper::Popup> popups = helper->GetBlockedPopups();
+
+  GURL currentUrl = _webState->GetLastCommittedURL();
+
+  // Open each blocked popup and allow future popups from this site.
+  for (const auto& popup : popups) {
+    web::WebState::OpenURLParams params(popup.popup_url, popup.referrer,
+                                        WindowOpenDisposition::NEW_POPUP,
+                                        ui::PAGE_TRANSITION_LINK, true);
+    _webState->OpenURL(params);
+
+    // Set popup permission to ALLOW for the referrer site.
+    _hostContentSettingsMap->SetContentSettingCustomScope(
+        ContentSettingsPattern::FromURL(popup.referrer.url),
+        ContentSettingsPattern::Wildcard(), ContentSettingsType::POPUPS,
+        CONTENT_SETTING_ALLOW);
+  }
+
+  [self.consumer updateFeatureRowsAvailability];
+}
+
 #pragma mark - CRWWebStateObserver
 
 - (void)webStateDidStartLoading:(web::WebState*)webState {
@@ -345,4 +413,10 @@
       ->current_language();
 }
 
+// Returns true if price tracking is currently active for the page.
+- (BOOL)isPriceTrackingAvailable {
+  // TODO(crbug.com/447143165): Implement price tracking detection.
+  return NO;
+}
+
 @end
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_feature.h b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_feature.h
index 8524e7b..4a9bc24 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_feature.h
+++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_feature.h
@@ -13,6 +13,7 @@
   PageActionMenuPopupBlocker,
   PageActionMenuCameraPermission,
   PageActionMenuMicrophonePermission,
+  PageActionMenuPriceTracking,
 };
 
 // Types of actions a feature perform.
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h
index b2370d6..a8b0c48 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h
+++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_mutator.h
@@ -45,6 +45,12 @@
 // Returns array of currently active features to display.
 - (NSArray<PageActionMenuFeature*>*)activeFeatures;
 
+// Allows all blocked popups for the current site.
+- (void)allowBlockedPopups;
+
+// Returns whether price tracking is available for the current page.
+- (BOOL)isPriceTrackingAvailable;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_INTELLIGENCE_PAGE_ACTION_MENU_UI_PAGE_ACTION_MENU_MUTATOR_H_
diff --git a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
index e827933..f666b76c 100644
--- a/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
+++ b/ios/chrome/browser/intelligence/page_action_menu/ui/page_action_menu_view_controller.mm
@@ -961,7 +961,10 @@
       // TODO(crbug.com/447649727): Handle translate "Show original" action.
       break;
     case PageActionMenuPopupBlocker:
-      // TODO(crbug.com/447649727): Handle popup "Always show" action.
+      [self.mutator allowBlockedPopups];
+      break;
+    case PageActionMenuPriceTracking:
+      // TODO(crbug.com/447143165): Handle price tracking action.
       break;
     default:
       break;
diff --git a/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest.mm b/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest.mm
index 3675e889..1df1e44 100644
--- a/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest.mm
+++ b/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest.mm
@@ -112,8 +112,9 @@
 
 // Scroll to the top of the Reading List.
 void ScrollToTop() {
-  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
-      performAction:[ChromeActionsAppInterface scrollToTop]];
+  XCUIApplication* springboardApplication = [[XCUIApplication alloc]
+      initWithBundleIdentifier:@"com.apple.springboard"];
+  [springboardApplication.statusBars.firstMatch tap];
 }
 
 // Asserts that the "mark" toolbar button is visible and has the a11y label of
@@ -170,7 +171,7 @@
 void PerformActionOnEntry(NSString* entryTitle, id<GREYAction> action) {
   ScrollToTop();
   [[[EarlGrey selectElementWithMatcher:VisibleReadingListItem(entryTitle)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100)
+         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
       onElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
       performAction:action];
 }
@@ -190,7 +191,7 @@
 void AssertEntryVisible(NSString* entryTitle) {
   ScrollToTop();
   [[[EarlGrey selectElementWithMatcher:VisibleReadingListItem(entryTitle)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100)
+         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
       onElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
       assertWithMatcher:grey_notNil()];
 }
@@ -207,6 +208,7 @@
                   @"The number of entries have changed");
   GREYAssertEqual((size_t)2, kNumberUnreadEntries,
                   @"The number of entries have changed");
+  ScrollToTop();
 }
 
 // Asserts that the entry `title` is not visible.
@@ -216,7 +218,7 @@
   NSError* error;
 
   [[[EarlGrey selectElementWithMatcher:VisibleReadingListItem(title)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100)
+         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
       onElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
       assertWithMatcher:grey_notNil()
                   error:&error];
@@ -824,7 +826,7 @@
   AddEntriesAndOpenReadingList();
 
   [[[EarlGrey selectElementWithMatcher:VisibleReadingListItem(kReadTitle)]
-         usingSearchAction:grey_scrollInDirection(kGREYDirectionDown, 100)
+         usingSearchAction:grey_swipeSlowInDirection(kGREYDirectionUp)
       onElementWithMatcher:grey_accessibilityID(kReadingListViewID)]
       performAction:grey_swipeFastInDirection(kGREYDirectionLeft)];
 
@@ -1250,9 +1252,8 @@
       verifyOpenInIncognitoActionWithURL:distillablePageURL.GetContent()];
 }
 
-// TODO(crbug.com/446871565): This test is flaky.
 // Tests the Mark as Read/Unread context menu action for a reading list entry.
-- (void)FLAKY_testContextMenuMarkAsReadAndBack {
+- (void)testContextMenuMarkAsReadAndBack {
 #if TARGET_IPHONE_SIMULATOR
   // TODO(crbug.com/433982582): Flaky on an iPhone simulator.
   if ([ChromeEarlGrey isIPhoneIdiom]) {
@@ -1271,6 +1272,9 @@
                   [ReadingListAppInterface unreadEntriesCount],
                   @"Wrong number of unread entry.");
 
+  // TODO(crbug.com/446889046): Investigate if there is a better solution to fix
+  // flakiness on iOS26.
+  base::test::ios::SpinRunLoopWithMinDelay(base::Seconds(1));
   // Mark an unread entry as read.
   LongPressEntry(kUnreadTitle);
 
@@ -1285,6 +1289,9 @@
                   [ReadingListAppInterface unreadEntriesCount],
                   @"Wrong number of unread entry after marking read.");
 
+  // TODO(crbug.com/446889046): Investigate if there is a better solution to fix
+  // flakiness on iOS26.
+  base::test::ios::SpinRunLoopWithMinDelay(base::Seconds(1));
   // Now mark it back as unread.
   LongPressEntry(kUnreadTitle);
 
diff --git a/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.mm b/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.mm
index 8913c2f..d84437fc 100644
--- a/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.mm
+++ b/ios/chrome/browser/reading_list/ui_bundled/reading_list_egtest_utils.mm
@@ -33,13 +33,13 @@
 id<GREYMatcher> VisibleReadingListItem(NSString* entryTitle) {
   return grey_allOf(grey_accessibilityID(entryTitle),
                     grey_kindOfClassName(@"TableViewURLCell"),
-                    grey_sufficientlyVisible(), nil);
+                    grey_minimumVisiblePercent(0.95), nil);
 }
 
 id<GREYMatcher> VisibleLocalItemIcon(NSString* title) {
   return grey_allOf(grey_ancestor(ReadingListItem(title)),
                     grey_accessibilityID(kTableViewURLCellMetadataImageID),
-                    grey_sufficientlyVisible(), nil);
+                    grey_minimumVisiblePercent(0.95), nil);
 }
 
 // Opens the reading list menu.
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_export_coordinator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_export_coordinator.mm
index 9394444..d401adc 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_export_coordinator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_export_coordinator.mm
@@ -58,9 +58,11 @@
 }
 
 - (void)confirmationAlertSecondaryAction {
+  if (_importCoordinator) {
+    return;
+  }
   RecordActionOnSafariExportEducationScreen(
       SafariDataImportExportEducationAction::kContinue);
-  CHECK(!_importCoordinator);
   _importCoordinator = [[SafariDataImportImportCoordinator alloc]
       initWithBaseNavigationController:_navigationController
                                browser:self.browser];
@@ -80,8 +82,10 @@
        didShowViewController:(UIViewController*)viewController
                     animated:(BOOL)animated {
   CHECK_EQ(navigationController, _navigationController);
-  if (viewController == _navigationController.viewControllers[0]) {
+  if (_importCoordinator &&
+      viewController == _navigationController.viewControllers[0]) {
     /// Handle user going back from import stage.
+    RecordSafariDataImportTapsBackAtImportStage(_importCoordinator.importStage);
     [_importCoordinator stop];
     _importCoordinator = nil;
   }
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.h b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.h
index fe11923e..40e461f 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.h
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.h
@@ -8,6 +8,7 @@
 #import "ios/chrome/browser/shared/coordinator/chrome_coordinator/chrome_coordinator.h"
 
 @protocol SafariDataImportChildCoordinatorDelegate;
+enum class SafariDataImportStage;
 
 /// Coordinator for the safari data import screen.
 @interface SafariDataImportImportCoordinator : ChromeCoordinator
@@ -16,6 +17,9 @@
 @property(nonatomic, weak) id<SafariDataImportChildCoordinatorDelegate>
     delegate;
 
+/// The current stage of import.
+@property(nonatomic, readonly) SafariDataImportStage importStage;
+
 /// Coordinator should be initialized with a base navigation view controller.
 - (instancetype)initWithBaseNavigationController:
                     (UINavigationController*)navigationController
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
index 67e1dc11..7596ef5 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_import_coordinator.mm
@@ -110,6 +110,10 @@
 
 #pragma mark - Accessors
 
+- (SafariDataImportStage)importStage {
+  return _containerViewController.importStage;
+}
+
 - (SafariDataImportImportMediator*)mediator {
   if (!_mediator) {
     /// Use original profile as the user has explicitly requested this operation
@@ -216,7 +220,7 @@
 #pragma mark - PromoStyleViewControllerDelegate
 
 - (void)didTapPrimaryActionButton {
-  switch (_containerViewController.importStage) {
+  switch (self.importStage) {
     case SafariDataImportStage::kNotStarted:
       if ([self showFilePicker]) {
         [self transitionToNextImportStage];
@@ -244,18 +248,16 @@
 #pragma mark - SafariDataImportImportStageTransitionHandler
 
 - (void)transitionToNextImportStage {
-  CHECK_NE(_containerViewController.importStage,
-           SafariDataImportStage::kImported)
+  CHECK_NE(self.importStage, SafariDataImportStage::kImported)
       << "No next import stage.";
-  int nextImportStageInt =
-      static_cast<int>(_containerViewController.importStage) + 1;
+  int nextImportStageInt = static_cast<int>(self.importStage) + 1;
   _containerViewController.email = self.mediator.email;
   _containerViewController.importStage =
       static_cast<SafariDataImportStage>(nextImportStageInt);
 }
 
 - (void)resetToInitialImportStage:(BOOL)userInitiated {
-  SafariDataImportStage currentStage = _containerViewController.importStage;
+  SafariDataImportStage currentStage = self.importStage;
   CHECK_EQ(currentStage, SafariDataImportStage::kFileLoading)
       << "Not supported for stage: " << static_cast<int>(currentStage);
   /// If the user has not explicitly canceled the import, alert the user that
@@ -374,7 +376,7 @@
 
 /// Dismisses Safari import workflow.
 - (void)dismissWorkflow {
-  RecordSafariDataImportEndsAtImportStage(_containerViewController.importStage);
+  RecordSafariDataImportEndsAtImportStage(self.importStage);
   [self.delegate safariDataImportCoordinatorWillDismissWorkflow:self];
 }
 
diff --git a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
index 4161012c..64e952b 100644
--- a/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
+++ b/ios/chrome/browser/safari_data_import/coordinator/safari_data_import_main_coordinator.mm
@@ -97,9 +97,11 @@
 #pragma mark - ConfirmationAlertActionHandler
 
 - (void)confirmationAlertPrimaryAction {
+  if (_exportCoordinator) {
+    return;
+  }
   RecordSafariImportActionOnEntryPoint(
       SafariDataImportEntryPointAction::kImport, _entryPoint);
-  CHECK(!_exportCoordinator);
   [_mediator notifyUsedOrDismissed];
   _exportCoordinator = [[SafariDataImportExportCoordinator alloc]
       initWithBaseViewController:_viewController
diff --git a/ios/chrome/browser/safari_data_import/public/metrics.h b/ios/chrome/browser/safari_data_import/public/metrics.h
index 4930397b..b451dbb6 100644
--- a/ios/chrome/browser/safari_data_import/public/metrics.h
+++ b/ios/chrome/browser/safari_data_import/public/metrics.h
@@ -64,6 +64,10 @@
 // successfully displayed.
 void RecordSafariDataImportFailure(bool alert_displayed);
 
+// Records the current stage of import when the user taps the "back" button.
+// Only applicable for users who reach the import screen.
+void RecordSafariDataImportTapsBackAtImportStage(SafariDataImportStage stage);
+
 // Records the current stage of import when the user exits the workflow. Only
 // applicable for users who reach the import screen.
 void RecordSafariDataImportEndsAtImportStage(SafariDataImportStage stage);
diff --git a/ios/chrome/browser/safari_data_import/public/metrics.mm b/ios/chrome/browser/safari_data_import/public/metrics.mm
index 4acba77..83bd572 100644
--- a/ios/chrome/browser/safari_data_import/public/metrics.mm
+++ b/ios/chrome/browser/safari_data_import/public/metrics.mm
@@ -34,6 +34,11 @@
                                 action);
 }
 
+void RecordSafariDataImportTapsBackAtImportStage(SafariDataImportStage stage) {
+  base::UmaHistogramEnumeration("IOS.SafariImport.Import.TapBackOnStage",
+                                stage);
+}
+
 void RecordSafariDataImportEndsAtImportStage(SafariDataImportStage stage) {
   base::UmaHistogramEnumeration("IOS.SafariImport.Import.ExitOnStage", stage);
 }
diff --git a/ios/chrome/browser/web/model/blocked_popup_tab_helper.h b/ios/chrome/browser/web/model/blocked_popup_tab_helper.h
index cc8a798..c1bdb66 100644
--- a/ios/chrome/browser/web/model/blocked_popup_tab_helper.h
+++ b/ios/chrome/browser/web/model/blocked_popup_tab_helper.h
@@ -63,6 +63,9 @@
     const web::Referrer referrer;
   };
 
+  // Returns a copy of the currently blocked popups.
+  std::vector<Popup> GetBlockedPopups() const { return popups_; }
+
  private:
   friend class web::LazyWebStateUserData<BlockedPopupTabHelper>;
 
diff --git a/ios_internal b/ios_internal
index deec601..f34aa19 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit deec601008dc93b675f5a8d94df26732d38a3d59
+Subproject commit f34aa19784ed9d36ae10f877a4347e2e23aab6cb
diff --git a/media/audio/BUILD.gn b/media/audio/BUILD.gn
index cbda18b..9388ffac 100644
--- a/media/audio/BUILD.gn
+++ b/media/audio/BUILD.gn
@@ -457,6 +457,7 @@
     "power_observer_helper_unittest.cc",
     "reconfigurable_audio_bus_pool_unittest.cc",
     "simple_sources_unittest.cc",
+    "wav_audio_handler_unittest.cc",
   ]
 
   deps = [
@@ -511,7 +512,6 @@
     sources += [
       "flac_audio_handler_unittest.cc",
       "test_data.h",
-      "wav_audio_handler_unittest.cc",
     ]
   }
 
diff --git a/media/audio/wav_audio_handler.cc b/media/audio/wav_audio_handler.cc
index 1d71c7f..d43e3f9 100644
--- a/media/audio/wav_audio_handler.cc
+++ b/media/audio/wav_audio_handler.cc
@@ -5,7 +5,9 @@
 #include "media/audio/wav_audio_handler.h"
 
 #include <algorithm>
+#include <array>
 #include <cstring>
+#include <optional>
 
 #include "base/check.h"
 #include "base/check_op.h"
@@ -25,136 +27,175 @@
 namespace media {
 namespace {
 
-const uint8_t kChunkId[] = {'R', 'I', 'F', 'F'};
-const uint8_t kFormat[] = {'W', 'A', 'V', 'E'};
-const uint8_t kFmtSubchunkId[] = {'f', 'm', 't', ' '};
-const uint8_t kDataSubchunkId[] = {'d', 'a', 't', 'a'};
+constexpr auto kChunkId = std::to_array<uint8_t>({'R', 'I', 'F', 'F'});
+constexpr auto kFormat = std::to_array<uint8_t>({'W', 'A', 'V', 'E'});
+constexpr auto kFmtSubchunkId = std::to_array<uint8_t>({'f', 'm', 't', ' '});
+constexpr auto kDataSubchunkId = std::to_array<uint8_t>({'d', 'a', 't', 'a'});
 
 // The size of a chunk header in wav file format. A chunk header consists of a
 // tag ('fmt ' or 'data') and 4 bytes of chunk length.
-const size_t kChunkHeaderSize = 8;
+constexpr size_t kChunkHeaderSize = 8;
 
 // The minimum size of 'fmt' chunk.
-const size_t kFmtChunkMinimumSize = 16;
-const size_t kFmtChunkExtensibleMinimumSize = 40;
+constexpr size_t kFmtChunkMinimumSize = 16;
+constexpr size_t kFmtChunkExtensibleMinimumSize = 40;
 
 // The offsets of 'fmt' fields.
-const size_t kAudioFormatOffset = 0;
-const size_t kChannelOffset = 2;
-const size_t kSampleRateOffset = 4;
-const size_t kBitsPerSampleOffset = 14;
-const size_t kValidBitsPerSampleOffset = 18;
-const size_t kSubFormatOffset = 24;
+constexpr size_t kAudioFormatOffset = 0;
+constexpr size_t kChannelOffset = 2;
+constexpr size_t kSampleRateOffset = 4;
+constexpr size_t kBitsPerSampleOffset = 14;
+constexpr size_t kValidBitsPerSampleOffset = 18;
+constexpr size_t kSubFormatOffset = 24;
 
-// A convenience struct for passing WAV parameters around. AudioParameters is
+// A convenience class for passing WAV parameters around. AudioParameters is
 // too heavyweight for this. Keep this class internal to this implementation.
-struct WavAudioParameters {
-  // TODO(crbug.com/340824112): note that zero-initializing this field does not
-  // correspond to any enumerator value defined in the `AudioFormat` enum.
-  // However, not initializing is also problematic: `ParseFmtChunk()` simply
-  // early-returns on failure, leaving random fields uninitialized and causing
-  // MSan errors elsewhere. A better long-term solution would be for
-  // `ParseFmtChunk` to return a `std::optional<WavAudioParameters>`. For now,
-  // zero-initializing this field has a (small) benefit that it won't
-  // correspond to any valid format and is guaranteed to fail the
-  // `ParamsAreValid()` check.
-  WavAudioHandler::AudioFormat audio_format = {};
-  uint16_t num_channels = 0;
-  uint32_t sample_rate = 0;
-  uint16_t bits_per_sample = 0;
-  uint16_t valid_bits_per_sample = 0;
-  bool is_extensible = false;
+class WavAudioParameters {
+ public:
+  WavAudioParameters() = default;
+
+  WavAudioParameters(WavAudioHandler::AudioFormat audio_format,
+                     uint16_t num_channels,
+                     uint32_t sample_rate,
+                     uint16_t bits_per_sample,
+                     uint16_t valid_bits_per_sample = 0,
+                     bool is_extensible = false)
+      : audio_format_(audio_format),
+        num_channels_(num_channels),
+        sample_rate_(sample_rate),
+        bits_per_sample_(bits_per_sample),
+        valid_bits_per_sample_(valid_bits_per_sample),
+        is_extensible_(is_extensible) {}
+
+  WavAudioHandler::AudioFormat audio_format() const { return audio_format_; }
+  uint16_t num_channels() const { return num_channels_; }
+  uint32_t sample_rate() const { return sample_rate_; }
+  uint16_t bits_per_sample() const { return bits_per_sample_; }
+  uint16_t valid_bits_per_sample() const { return valid_bits_per_sample_; }
+  bool is_extensible() const { return is_extensible_; }
+
+  bool IsValid() const {
+    return
+        // Check number of channels
+        num_channels_ != 0u &&
+        num_channels_ <= static_cast<uint16_t>(limits::kMaxChannels) &&
+        // Check sample rate
+        sample_rate_ != 0u &&
+        (
+            // Check bits per second for PCM data
+            (audio_format_ == WavAudioHandler::AudioFormat::kAudioFormatPCM &&
+             (bits_per_sample_ == 8u || bits_per_sample_ == 16u ||
+              bits_per_sample_ == 32u)) ||
+            // Check bits per second for float data
+            (audio_format_ == WavAudioHandler::AudioFormat::kAudioFormatFloat &&
+             (bits_per_sample_ == 32u || bits_per_sample_ == 64u))) &&
+        // Check extensible format bps
+        (!is_extensible_ || valid_bits_per_sample_ == bits_per_sample_);
+  }
+
+ private:
+  WavAudioHandler::AudioFormat audio_format_ =
+      WavAudioHandler::AudioFormat::kAudioFormatPCM;
+  uint16_t num_channels_ = 0;
+  uint32_t sample_rate_ = 0;
+  uint16_t bits_per_sample_ = 0;
+  uint16_t valid_bits_per_sample_ = 0;
+  bool is_extensible_ = false;
 };
 
-bool ParamsAreValid(const WavAudioParameters& params) {
-  return (
-      // Check number of channels
-      params.num_channels != 0u &&
-      params.num_channels <= static_cast<uint16_t>(limits::kMaxChannels) &&
-      // Check sample rate
-      params.sample_rate != 0u &&
-      (
-          // Check bits per second for PCM data
-          (params.audio_format ==
-               WavAudioHandler::AudioFormat::kAudioFormatPCM &&
-           (params.bits_per_sample == 8u || params.bits_per_sample == 16u ||
-            params.bits_per_sample == 32u)) ||
-          // Check bits per second for float data
-          (params.audio_format ==
-               WavAudioHandler::AudioFormat::kAudioFormatFloat &&
-           (params.bits_per_sample == 32u || params.bits_per_sample == 64u))) &&
-      // Check extensible format bps
-      (!params.is_extensible ||
-       params.valid_bits_per_sample == params.bits_per_sample));
-}
+// Result struct containing both audio data and parameters from ParseWavData.
+struct ParseWavResult {
+  base::raw_span<const uint8_t> audio_data;
+  WavAudioParameters params;
+};
 
 // Parse a "fmt " chunk from wav data into its parameters. The `data` is in
 // little endian encoding.
-bool ParseFmtChunk(base::span<const uint8_t> data, WavAudioParameters& params) {
-  // If the chunk is too small, return false.
+std::optional<WavAudioParameters> ParseFmtChunk(
+    base::span<const uint8_t> data) {
+  // If the chunk is too small, return nullopt.
   if (data.size() < kFmtChunkMinimumSize) {
-    LOG(ERROR) << "Data size " << data.size() << " is too short.";
-    return false;
+    DVLOG(1) << "Data size " << data.size() << " is too short.";
+    return std::nullopt;
   }
 
   // Read in serialized parameters.
-  params.audio_format =
+  WavAudioHandler::AudioFormat audio_format =
       static_cast<WavAudioHandler::AudioFormat>(base::U16FromLittleEndian(
           data.subspan<kAudioFormatOffset,
                        sizeof(WavAudioHandler::AudioFormat)>()));
-  params.num_channels =
+  uint16_t num_channels =
       base::U16FromLittleEndian(data.subspan<kChannelOffset, 2u>());
-  params.sample_rate =
+  uint32_t sample_rate =
       base::U32FromLittleEndian(data.subspan<kSampleRateOffset, 4u>());
-  params.bits_per_sample =
+  uint16_t bits_per_sample =
       base::U16FromLittleEndian(data.subspan<kBitsPerSampleOffset, 2u>());
 
-  if (params.audio_format ==
-      WavAudioHandler::AudioFormat::kAudioFormatExtensible) {
+  WavAudioParameters params;
+
+  if (audio_format == WavAudioHandler::AudioFormat::kAudioFormatExtensible) {
     if (data.size() < kFmtChunkExtensibleMinimumSize) {
-      LOG(ERROR) << "Data size " << data.size() << " is too short.";
-      return false;
+      DVLOG(1) << "Data size " << data.size() << " is too short.";
+      return std::nullopt;
     }
 
-    params.is_extensible = true;
-    params.audio_format =
+    WavAudioHandler::AudioFormat actual_format =
         static_cast<WavAudioHandler::AudioFormat>(base::U16FromLittleEndian(
             data.subspan<kSubFormatOffset,
                          sizeof(WavAudioHandler::AudioFormat)>()));
-    params.valid_bits_per_sample = base::U16FromLittleEndian(
+    uint16_t valid_bits_per_sample = base::U16FromLittleEndian(
         data.subspan<kValidBitsPerSampleOffset, 2u>());
+
+    params = WavAudioParameters(actual_format, num_channels, sample_rate,
+                                bits_per_sample, valid_bits_per_sample, true);
   } else {
-    params.is_extensible = false;
+    params = WavAudioParameters(audio_format, num_channels, sample_rate,
+                                bits_per_sample);
   }
-  return true;
+
+  // Validate the parameters before returning to ensure we only return
+  // completely valid WavAudioParameters, never partially-valid results.
+  if (!params.IsValid()) {
+    DVLOG(1) << "Format chunk contains invalid parameters. "
+             << "num_channels: " << params.num_channels() << " "
+             << "sample_rate: " << params.sample_rate() << " "
+             << "bits_per_sample: " << params.bits_per_sample() << " "
+             << "valid_bits_per_sample: " << params.valid_bits_per_sample()
+             << " "
+             << "is_extensible: " << params.is_extensible();
+    return std::nullopt;
+  }
+
+  return params;
 }
 
-// The `wav_data` is encoded in little endian, as will be `audio_data_out`.
-bool ParseWavData(base::span<const uint8_t> wav_data,
-                  base::span<const uint8_t>& audio_data_out,
-                  WavAudioParameters& params_out) {
+// The `wav_data` is encoded in little endian, as will be the returned audio
+// data.
+std::optional<ParseWavResult> ParseWavData(base::span<const uint8_t> wav_data) {
   // The header should look like: |R|I|F|F|1|2|3|4|W|A|V|E|
   auto buf = base::SpanReader(wav_data);
 
   // Read the chunk ID and compare to "RIFF".
   std::optional<base::span<const uint8_t, 4u>> chunk_id = buf.Read<4u>();
   if (chunk_id != kChunkId) {
-    DLOG(ERROR) << "missing or incorrect chunk ID in wav header";
-    return false;
+    DVLOG(1) << "missing or incorrect chunk ID in wav header";
+    return std::nullopt;
   }
   // The RIFF chunk length comes next, but we don't actually care what it says.
   if (!buf.Skip(sizeof(uint32_t))) {
-    DLOG(ERROR) << "missing length in wav header";
-    return false;
+    DVLOG(1) << "missing length in wav header";
+    return std::nullopt;
   }
   // Read format and compare to "WAVE".
   std::optional<base::span<const uint8_t, 4u>> format = buf.Read<4u>();
   if (format != kFormat) {
-    DLOG(ERROR) << "missing or incorrect format ID in wav header";
-    return false;
+    DVLOG(1) << "missing or incorrect format ID in wav header";
+    return std::nullopt;
   }
 
+  ParseWavResult result;
   bool got_format = false;
+
   // If the number of remaining bytes is smaller than |kChunkHeaderSize|, it's
   // just junk at the end.
   while (buf.remaining() >= kChunkHeaderSize) {
@@ -172,31 +213,26 @@
     // chunk. Skip it otherwise.
     if (chunk_fmt == kFmtSubchunkId) {
       got_format = true;
-      if (!ParseFmtChunk(chunk_payload, params_out))
-        return false;
+      std::optional<WavAudioParameters> params = ParseFmtChunk(chunk_payload);
+      if (!params) {
+        return std::nullopt;
+      }
+      result.params = std::move(*params);
     } else if (chunk_fmt == kDataSubchunkId) {
-      audio_data_out = chunk_payload;
+      result.audio_data = chunk_payload;
     } else {
       DVLOG(1) << "Skipping unknown data chunk: "
                << base::as_string_view(chunk_fmt) << ".";
     }
   }
 
-  // Check that data format has been read in and is valid.
+  // Check that data format has been read in.
   if (!got_format) {
-    LOG(ERROR) << "Invalid: No \"" << kFmtSubchunkId << "\" header found!";
-    return false;
-  } else if (!ParamsAreValid(params_out)) {
-    LOG(ERROR) << "Format is invalid. "
-               << "num_channels: " << params_out.num_channels << " "
-               << "sample_rate: " << params_out.sample_rate << " "
-               << "bits_per_sample: " << params_out.bits_per_sample << " "
-               << "valid_bits_per_sample: " << params_out.valid_bits_per_sample
-               << " "
-               << "is_extensible: " << params_out.is_extensible;
-    return false;
+    DVLOG(1) << "Invalid: No \"" << base::as_string_view(kFmtSubchunkId)
+             << "\" header found!";
+    return std::nullopt;
   }
-  return true;
+  return result;
 }
 
 }  // namespace
@@ -221,17 +257,16 @@
 // static
 std::unique_ptr<WavAudioHandler> WavAudioHandler::Create(
     base::span<const uint8_t> wav_data) {
-  WavAudioParameters params;
-  base::span<const uint8_t> audio_data;
-
   // Attempt to parse the WAV data.
-  if (!ParseWavData(wav_data, audio_data, params)) {
+  std::optional<ParseWavResult> result = ParseWavData(wav_data);
+  if (!result) {
     return nullptr;
   }
 
-  return base::WrapUnique(
-      new WavAudioHandler(audio_data, params.num_channels, params.sample_rate,
-                          params.bits_per_sample, params.audio_format));
+  return base::WrapUnique(new WavAudioHandler(
+      result->audio_data, result->params.num_channels(),
+      result->params.sample_rate(), result->params.bits_per_sample(),
+      result->params.audio_format()));
 }
 
 bool WavAudioHandler::Initialize() {
@@ -256,6 +291,7 @@
 
   if (AtEnd()) {
     bus->Zero();
+    *frames_written = 0;
     return true;
   }
   const int bytes_per_frame = num_channels_ * bits_per_sample_ / 8;
diff --git a/media/audio/wav_audio_handler_fuzzer.cc b/media/audio/wav_audio_handler_fuzzer.cc
index 4ae7f805..4db4120 100644
--- a/media/audio/wav_audio_handler_fuzzer.cc
+++ b/media/audio/wav_audio_handler_fuzzer.cc
@@ -8,7 +8,6 @@
 #include <stdint.h>
 
 #include <memory>
-#include <string_view>
 
 #include "base/containers/span.h"
 #include "base/logging.h"
@@ -18,11 +17,10 @@
   Environment() { logging::SetMinLogLevel(logging::LOGGING_FATAL); }
 };
 
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+extern "C" int LLVMFuzzerTestOneInput(base::span<const uint8_t> data_span) {
   static Environment env;
-  std::string_view wav_data(reinterpret_cast<const char*>(data), size);
   std::unique_ptr<media::WavAudioHandler> handler =
-      media::WavAudioHandler::Create(base::as_byte_span(wav_data));
+      media::WavAudioHandler::Create(data_span);
 
   // Abort early to avoid crashing inside AudioBus's ValidateConfig() function.
   if (!handler || !handler->Initialize() ||
diff --git a/media/audio/wav_audio_handler_unittest.cc b/media/audio/wav_audio_handler_unittest.cc
index 40e8e3a..520679e 100644
--- a/media/audio/wav_audio_handler_unittest.cc
+++ b/media/audio/wav_audio_handler_unittest.cc
@@ -6,6 +6,7 @@
 
 #include <stddef.h>
 
+#include <array>
 #include <memory>
 #include <string>
 #include <string_view>
@@ -18,19 +19,19 @@
 namespace media {
 namespace {
 // WAV header comes first in the test data.
-const size_t kWavHeaderSize = 12;
-const size_t kWavDataSizeIndex = 4;
+constexpr size_t kWavHeaderSize = 12;
+constexpr size_t kWavDataSizeIndex = 4;
 
 // "fmt " header comes next.
-const size_t kFormatHeaderIndex = kWavHeaderSize;
-const size_t kFormatHeaderSize = 8;
-const size_t kFormatPayloadSize = 16;
-const size_t kChannelIndex = kWavHeaderSize + kFormatHeaderSize + 2;
-const size_t kBitsPerSampleIndex = kWavHeaderSize + kFormatHeaderSize + 14;
-const size_t kSampleRateIndex = kWavHeaderSize + kFormatHeaderSize + 4;
+constexpr size_t kFormatHeaderIndex = kWavHeaderSize;
+constexpr size_t kFormatHeaderSize = 8;
+constexpr size_t kFormatPayloadSize = 16;
+constexpr size_t kChannelIndex = kWavHeaderSize + kFormatHeaderSize + 2;
+constexpr size_t kBitsPerSampleIndex = kWavHeaderSize + kFormatHeaderSize + 14;
+constexpr size_t kSampleRateIndex = kWavHeaderSize + kFormatHeaderSize + 4;
 
 // "data" header comes last.
-const size_t kDataHeaderIndex =
+constexpr size_t kDataHeaderIndex =
     kWavHeaderSize + kFormatHeaderSize + kFormatPayloadSize;
 
 }  // namespace
@@ -201,24 +202,6 @@
   EXPECT_FALSE(handler);
 }
 
-TEST(WavAudioHandlerTest, TestOtherSectionTypesIsOkay) {
-  // Append some other subsection header "abcd", the class should just consume
-  // and keep going.
-  std::string data(kTestAudioData, kTestAudioDataSize);
-  data.append("abcd\x04\x00\x00\x00\x01\x02\x03\x04");
-  data[kWavDataSizeIndex] += 12;  // This should not overflow.
-
-  auto handler = WavAudioHandler::Create(base::as_byte_span(data));
-  EXPECT_TRUE(handler);
-  EXPECT_TRUE(handler->Initialize());
-  ASSERT_EQ(2, handler->GetNumChannels());
-  ASSERT_EQ(16, handler->bits_per_sample_for_testing());
-  ASSERT_EQ(48000, handler->GetSampleRate());
-  ASSERT_EQ(1, handler->total_frames_for_testing());
-  ASSERT_EQ(20u, handler->GetDuration().InMicroseconds());
-  ASSERT_EQ(4u, handler->data().size());
-}
-
 TEST(WavAudioHandlerTest, TestNoFmtSectionIsNotValid) {
   // Write over the "fmt " header. No valid handler should be returned.
   std::string data(kTestAudioData, kTestAudioDataSize);
@@ -250,4 +233,470 @@
   ASSERT_EQ(0u, handler->data().size());
 }
 
+// Test extensible format with insufficient data size.
+TEST(WavAudioHandlerTest, ExtensibleFormatTooShort) {
+  // clang-format off
+  constexpr auto kInvalidExtensibleWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x1C, 0x00, 0x00, 0x00,  // chunk size (28 bytes = 8 + 20 for fmt chunk only).
+      'W', 'A', 'V', 'E',
+      // fmt chunk with extensible format but insufficient size.
+      'f', 'm', 't', ' ',
+      0x14, 0x00, 0x00, 0x00,  // chunk size (20 bytes, less than required 40).
+      0xFE, 0xFF,              // WAVE_FORMAT_EXTENSIBLE.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x10, 0xB1, 0x02, 0x00,  // byte rate (44100 * 2 * 2 = 176400).
+      0x04, 0x00,              // block align (2 channels * 2 bytes).
+      0x10, 0x00,              // 16 bits per sample.
+      0x10, 0x00,              // valid bits per sample.
+      0x00, 0x00, 0x00, 0x00,  // channel mask.
+      // Missing subformat GUID (should be 16 more bytes for extensible format).
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kInvalidExtensibleWav));
+  EXPECT_FALSE(handler);
+}
+
+// Test invalid parameters validation.
+TEST(WavAudioHandlerTest, InvalidParametersValidation) {
+  // Test unsupported PCM bit depth.
+  // clang-format off
+  constexpr auto kUnsupportedPcmBitsWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x28, 0x00, 0x00, 0x00,  // chunk size (40 bytes = 8 + 16 + 8 + 8).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x38, 0x09, 0x04, 0x00,  // byte rate (44100 * 2 * 3 = 264600).
+      0x06, 0x00,              // block align (2 channels * 3 bytes).
+      0x18, 0x00,              // 24 bits per sample (not supported for PCM).
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x08, 0x00, 0x00, 0x00,  // data size (8 bytes).
+      0x00, 0x00, 0x00, 0x00,  // sample data (padding to match 24-bit format).
+      0x00, 0x00, 0x00, 0x00
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kUnsupportedPcmBitsWav));
+  EXPECT_FALSE(handler);
+
+  // Test unsupported float bit depth.
+  // clang-format off
+  constexpr auto kUnsupportedFloatBitsWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x28, 0x00, 0x00, 0x00,  // chunk size (40 bytes = 8 + 16 + 8 + 8).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x03, 0x00,              // IEEE float format.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x38, 0x09, 0x04, 0x00,  // byte rate (44100 * 2 * 3 = 264600).
+      0x06, 0x00,              // block align (2 channels * 3 bytes).
+      0x18, 0x00,              // 24 bits per sample (not supported for float).
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x08, 0x00, 0x00, 0x00,  // data size (8 bytes).
+      0x00, 0x00, 0x00, 0x00,  // sample data (padding to match 24-bit format).
+      0x00, 0x00, 0x00, 0x00
+  });
+  // clang-format on
+
+  auto handler2 = WavAudioHandler::Create(base::span(kUnsupportedFloatBitsWav));
+  EXPECT_FALSE(handler2);
+}
+
+// Test invalid RIFF chunk ID.
+TEST(WavAudioHandlerTest, InvalidRiffChunkId) {
+  // clang-format off
+  constexpr auto kInvalidRiffWav = std::to_array<uint8_t>({
+      // Invalid RIFF header.
+      'X', 'I', 'F', 'F',      // Wrong chunk ID (should be "RIFF").
+      0x24, 0x00, 0x00, 0x00,  // chunk size (36 bytes = 8 + 16 + 8 + 4).
+      'W', 'A', 'V', 'E',      // format.
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x10, 0xB1, 0x02, 0x00,  // byte rate (44100 * 2 * 2 = 176400).
+      0x04, 0x00,              // block align (2 channels * 2 bytes).
+      0x10, 0x00,              // 16 bits per sample.
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x00, 0x00, 0x00, 0x00   // sample data.
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kInvalidRiffWav));
+  EXPECT_FALSE(handler);
+}
+
+// Test missing length field.
+TEST(WavAudioHandlerTest, MissingLengthField) {
+  // clang-format off
+  constexpr auto kTruncatedWav = std::to_array<uint8_t>({
+      // RIFF header without length.
+      'R', 'I', 'F', 'F'
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kTruncatedWav));
+  EXPECT_FALSE(handler);
+}
+
+// Test invalid format ID.
+TEST(WavAudioHandlerTest, InvalidFormatId) {
+  // clang-format off
+  constexpr auto kInvalidFormatWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x24, 0x00, 0x00, 0x00,  // chunk size (36 bytes = 8 + 16 + 8 + 4).
+      'X', 'A', 'V', 'E',      // Wrong format ID (should be "WAVE").
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x10, 0xB1, 0x02, 0x00,  // byte rate (44100 * 2 * 2 = 176400).
+      0x04, 0x00,              // block align (2 channels * 2 bytes).
+      0x10, 0x00,              // 16 bits per sample.
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x00, 0x00, 0x00, 0x00   // sample data.
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kInvalidFormatWav));
+  EXPECT_FALSE(handler);
+}
+
+// Test missing format chunk.
+TEST(WavAudioHandlerTest, MissingFormatChunk) {
+  // clang-format off
+  constexpr auto kNoFormatWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x0C, 0x00, 0x00, 0x00,  // chunk size (12 bytes = 8 + 4 for data chunk).
+      'W', 'A', 'V', 'E',
+      // Only data chunk, no fmt chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x00, 0x00, 0x00, 0x00   // sample data.
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kNoFormatWav));
+  EXPECT_FALSE(handler);
+}
+
+// Test accessor methods and basic functionality.
+TEST(WavAudioHandlerTest, AccessorMethodsAndBasicFunctionality) {
+  // clang-format off
+  constexpr auto kValidWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x24, 0x00, 0x00, 0x00,  // chunk size (36 bytes = 8 + 16 + 8 + 8).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x10, 0xB1, 0x02, 0x00,  // byte rate (44100 * 2 * 2 = 176400).
+      0x04, 0x00,              // block align (2 channels * 2 bytes).
+      0x10, 0x00,              // 16 bits per sample.
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x08, 0x00, 0x00, 0x00,  // data size (8 bytes).
+      0x00, 0x00, 0x01, 0x00,  // sample data (2 frames * 2 channels * 2 bytes).
+      0x00, 0x00, 0x01, 0x00
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kValidWav));
+  ASSERT_TRUE(handler);
+
+  // Test accessor methods.
+  EXPECT_EQ(2, handler->GetNumChannels());
+  EXPECT_EQ(44100, handler->GetSampleRate());
+
+  // Test GetDuration.
+  EXPECT_GT(handler->GetDuration().InMicroseconds(), 0);
+
+  // Test CopyTo functionality.
+  auto bus = AudioBus::Create(2, 2);
+  size_t frames_written = 0;
+  EXPECT_TRUE(handler->CopyTo(bus.get(), &frames_written));
+  EXPECT_EQ(2u, frames_written);
+
+  // Test Reset functionality.
+  handler->Reset();
+  EXPECT_FALSE(handler->AtEnd());
+}
+
+// Test 64-bit float format support.
+TEST(WavAudioHandlerTest, Float64FormatSupport) {
+  // clang-format off
+  // Use WAVE_FORMAT_EXTENSIBLE with padding chunk to ensure data is 8-byte aligned.
+  // Structure: 12 (RIFF) + 48 (fmt) + 12 (pad with 4 bytes data) + 8 (data header) = 80
+  // Data starts at offset 80, which is 8-byte aligned (80 % 8 == 0).
+  alignas(8) constexpr auto kFloat64Wav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x68, 0x00, 0x00, 0x00,  // chunk size (104 bytes = 4 + 48 + 12 + 8 + 32).
+      'W', 'A', 'V', 'E',
+      // fmt chunk with WAVE_FORMAT_EXTENSIBLE (40 bytes data).
+      'f', 'm', 't', ' ',
+      0x28, 0x00, 0x00, 0x00,  // chunk size (40 bytes for extensible format).
+      0xFE, 0xFF,              // WAVE_FORMAT_EXTENSIBLE.
+      0x02, 0x00,              // 2 channels.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x40, 0xC4, 0x0A, 0x00,  // byte rate (44100 * 2 * 8 = 705600).
+      0x10, 0x00,              // block align (2 channels * 8 bytes).
+      0x40, 0x00,              // 64 bits per sample.
+      0x16, 0x00,              // extension size (22 bytes).
+      0x40, 0x00,              // valid bits per sample (64).
+      0x03, 0x00, 0x00, 0x00,  // channel mask (3 = front left | front right).
+      // Subformat GUID for IEEE float: 00000003-0000-0010-8000-00aa00389b71.
+      0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+      0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71,
+      // Padding chunk to align data section (12 bytes total: 4 ID + 4 size + 4 data).
+      'P', 'A', 'D', ' ',
+      0x04, 0x00, 0x00, 0x00,  // chunk size (4 bytes).
+      0x00, 0x00, 0x00, 0x00,  // padding data (4 bytes).
+      // data chunk (now starts at offset 72, and data at 80, which is 8-byte aligned).
+      'd', 'a', 't', 'a',
+      0x20, 0x00, 0x00, 0x00,  // data size (32 bytes = 2 frames * 2 channels * 8 bytes).
+      // Sample data: 2 frames of 64-bit float data (starts at offset 80).
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // frame 1, channel 1 (0.0).
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // frame 1, channel 2 (0.0).
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  // frame 2, channel 1 (0.0).
+      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00   // frame 2, channel 2 (0.0).
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kFloat64Wav));
+  ASSERT_TRUE(handler);
+  EXPECT_EQ(64, handler->bits_per_sample_for_testing());
+
+  auto bus = AudioBus::Create(2, 2);
+  size_t frames_written = 0;
+  EXPECT_TRUE(handler->CopyTo(bus.get(), &frames_written));
+  EXPECT_EQ(2u, frames_written);
+}
+
+// Test 8-bit and 32-bit PCM format support.
+TEST(WavAudioHandlerTest, PcmFormatVariations) {
+  // Test 8-bit PCM.
+  // clang-format off
+  alignas(8) constexpr auto k8BitPcmWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x24, 0x00, 0x00, 0x00,  // chunk size (36 bytes = 8 + 16 + 8 + 4).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x01, 0x00,              // 1 channel.
+      0x40, 0x1F, 0x00, 0x00,  // 8000 Hz sample rate.
+      0x40, 0x1F, 0x00, 0x00,  // byte rate (8000 * 1 * 1 = 8000).
+      0x01, 0x00,              // block align (1 channel * 1 byte).
+      0x08, 0x00,              // 8 bits per sample.
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x80, 0x90, 0xA0, 0xB0   // 8-bit samples (4 samples).
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(k8BitPcmWav));
+  ASSERT_TRUE(handler);
+  EXPECT_EQ(8, handler->bits_per_sample_for_testing());
+
+  auto bus = AudioBus::Create(1, 4);
+  size_t frames_written = 0;
+  EXPECT_TRUE(handler->CopyTo(bus.get(), &frames_written));
+  EXPECT_EQ(4u, frames_written);
+
+  // Test 32-bit PCM.
+  // clang-format off
+  // Use WAVE_FORMAT_EXTENSIBLE with padding chunk to ensure data is 8-byte aligned.
+  // Structure: 12 (RIFF) + 48 (fmt) + 12 (pad with 4 bytes data) + 8 (data header) = 80
+  // Data starts at offset 80, which is 8-byte aligned (80 % 8 == 0).
+  alignas(8) constexpr auto k32BitPcmWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x50, 0x00, 0x00, 0x00,  // chunk size (80 bytes = 4 + 48 + 12 + 8 + 8).
+      'W', 'A', 'V', 'E',
+      // fmt chunk with WAVE_FORMAT_EXTENSIBLE (40 bytes data).
+      'f', 'm', 't', ' ',
+      0x28, 0x00, 0x00, 0x00,  // chunk size (40 bytes for extensible format).
+      0xFE, 0xFF,              // WAVE_FORMAT_EXTENSIBLE.
+      0x01, 0x00,              // 1 channel.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x10, 0xB1, 0x02, 0x00,  // byte rate (44100 * 1 * 4 = 176400).
+      0x04, 0x00,              // block align (1 channel * 4 bytes).
+      0x20, 0x00,              // 32 bits per sample.
+      0x16, 0x00,              // extension size (22 bytes).
+      0x20, 0x00,              // valid bits per sample (32).
+      0x04, 0x00, 0x00, 0x00,  // channel mask (4 = front center).
+      // Subformat GUID for PCM: 00000001-0000-0010-8000-00aa00389b71.
+      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+      0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71,
+      // Padding chunk to align data section (12 bytes total: 4 ID + 4 size + 4 data).
+      'P', 'A', 'D', ' ',
+      0x04, 0x00, 0x00, 0x00,  // chunk size (4 bytes).
+      0x00, 0x00, 0x00, 0x00,  // padding data (4 bytes).
+      // data chunk (now starts at offset 72, and data at 80, which is 8-byte aligned).
+      'd', 'a', 't', 'a',
+      0x08, 0x00, 0x00, 0x00,  // data size (8 bytes).
+      // Sample data (starts at offset 80, which is 8-byte aligned).
+      0x00, 0x00, 0x01, 0x00,  // 32-bit sample 1 (little-endian: 65536).
+      0x00, 0x00, 0x02, 0x00   // 32-bit sample 2 (little-endian: 131072).
+  });
+  // clang-format on
+
+  auto handler2 = WavAudioHandler::Create(base::span(k32BitPcmWav));
+  ASSERT_TRUE(handler2);
+  EXPECT_EQ(32, handler2->bits_per_sample_for_testing());
+
+  auto bus2 = AudioBus::Create(1, 2);
+  size_t frames_written2 = 0;
+  EXPECT_TRUE(handler2->CopyTo(bus2.get(), &frames_written2));
+  EXPECT_EQ(2u, frames_written2);
+}
+
+// Test AtEnd() boundary condition and CopyTo at end of data.
+TEST(WavAudioHandlerTest, AtEndBoundaryCondition) {
+  // clang-format off
+  constexpr auto kSmallWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x24, 0x00, 0x00, 0x00,  // chunk size (36 bytes = 4 + 24 + 8).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x01, 0x00,              // 1 channel.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0xAC, 0x44, 0x00, 0x00,  // byte rate (44100 * 1 * 1 = 44100).
+      0x01, 0x00,              // block align (1 channel * 1 byte).
+      0x08, 0x00,              // 8 bits per sample.
+      // data chunk with zero length.
+      'd', 'a', 't', 'a',
+      0x00, 0x00, 0x00, 0x00   // data size (0 bytes).
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kSmallWav));
+  ASSERT_TRUE(handler);
+
+  // Initially should not be at end since we haven't read any data.
+  EXPECT_TRUE(handler->AtEnd());
+
+  auto bus = AudioBus::Create(1, 4);
+  auto channel_data = bus->channel_span(0);
+  for (int i = 0; i < bus->frames(); ++i) {
+    channel_data[i] = 1.0f;
+  }
+
+  size_t frames_written = 0;
+  EXPECT_TRUE(handler->CopyTo(bus.get(), &frames_written));
+  EXPECT_EQ(0u, frames_written);
+
+  // Verify bus was zeroed.
+  for (int i = 0; i < bus->frames(); ++i) {
+    EXPECT_EQ(0.0f, channel_data[i]);
+  }
+}
+
+// Test skipping unknown chunks to cover DVLOG path.
+TEST(WavAudioHandlerTest, SkipUnknownChunks) {
+  // clang-format off
+  constexpr auto kWavWithUnknownChunk = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x34, 0x00, 0x00, 0x00,  // chunk size (52 bytes = 4 + 24 + 12 + 12).
+      'W', 'A', 'V', 'E',
+      // fmt chunk.
+      'f', 'm', 't', ' ',
+      0x10, 0x00, 0x00, 0x00,  // chunk size (16 bytes).
+      0x01, 0x00,              // PCM format.
+      0x01, 0x00,              // 1 channel.
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0xAC, 0x44, 0x00, 0x00,  // byte rate (44100 * 1 * 1 = 44100).
+      0x01, 0x00,              // block align (1 channel * 1 byte).
+      0x08, 0x00,              // 8 bits per sample.
+      // Unknown chunk "LIST".
+      'L', 'I', 'S', 'T',
+      0x04, 0x00, 0x00, 0x00,  // chunk size (4 bytes).
+      0x00, 0x00, 0x00, 0x00,  // dummy data.
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x80, 0x90, 0xA0, 0xB0   // sample data.
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kWavWithUnknownChunk));
+  ASSERT_TRUE(handler);
+  EXPECT_EQ(1, handler->GetNumChannels());
+  EXPECT_EQ(8, handler->bits_per_sample_for_testing());
+  EXPECT_EQ(4u, handler->data().size());
+}
+
+// Test to specifically trigger the DVLOG path that calls
+// valid_bits_per_sample() and is_extensible() accessor methods.
+TEST(WavAudioHandlerTest, TriggerAccessorMethodsInDVLOG) {
+  // clang-format off
+  constexpr auto kInvalidExtensibleWav = std::to_array<uint8_t>({
+      // RIFF header.
+      'R', 'I', 'F', 'F',
+      0x40, 0x00, 0x00, 0x00,  // chunk size (64 bytes = 4 + 48 + 12).
+      'W', 'A', 'V', 'E',
+      // fmt chunk - extensible format.
+      'f', 'm', 't', ' ',
+      0x28, 0x00, 0x00, 0x00,  // chunk size (40 bytes for extensible).
+      0xFE, 0xFF,              // WAVE_FORMAT_EXTENSIBLE.
+      0x00, 0x00,              // 0 channels (invalid - will trigger DVLOG).
+      0x44, 0xAC, 0x00, 0x00,  // 44100 Hz sample rate.
+      0x00, 0x00, 0x00, 0x00,  // byte rate (0 due to invalid channels).
+      0x00, 0x00,              // block align (0 due to invalid channels).
+      0x10, 0x00,              // 16 bits per sample.
+      0x16, 0x00,              // extension size (22 bytes).
+      0x10, 0x00,              // valid bits per sample.
+      0x04, 0x00, 0x00, 0x00,  // channel mask.
+      // Subformat GUID for PCM.
+      0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
+      0x80, 0x00, 0x00, 0xAA, 0x00, 0x38, 0x9B, 0x71,
+      // data chunk.
+      'd', 'a', 't', 'a',
+      0x04, 0x00, 0x00, 0x00,  // data size (4 bytes).
+      0x00, 0x00, 0x00, 0x00   // sample data.
+  });
+  // clang-format on
+
+  auto handler = WavAudioHandler::Create(base::span(kInvalidExtensibleWav));
+  EXPECT_FALSE(handler);
+}
+
 }  // namespace media
diff --git a/media/base/supported_types_unittest.cc b/media/base/supported_types_unittest.cc
index 6dc84db..431cee8 100644
--- a/media/base/supported_types_unittest.cc
+++ b/media/base/supported_types_unittest.cc
@@ -32,8 +32,9 @@
   // Expect support for baseline configuration of known codecs.
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP8, VP8PROFILE_ANY, kUnspecifiedLevel, kColorSpace}));
-  EXPECT_TRUE(IsDecoderSupportedVideoType(
-      {VideoCodec::kVP9, VP9PROFILE_PROFILE0, kUnspecifiedLevel, kColorSpace}));
+  EXPECT_EQ(IsDecoderSupportedVideoType({VideoCodec::kVP9, VP9PROFILE_PROFILE0,
+                                         kUnspecifiedLevel, kColorSpace}),
+            BUILDFLAG(ENABLE_LIBVPX));
   EXPECT_FALSE(IsDecoderSupportedVideoType({VideoCodec::kTheora,
                                             VIDEO_CODEC_PROFILE_UNKNOWN,
                                             kUnspecifiedLevel, kColorSpace}));
@@ -69,6 +70,7 @@
 #endif
 }
 
+#if defined(ENABLE_LIBVPX)
 TEST(SupportedTypesTest, IsDecoderSupportedVideoType_VP9TransferFunctions) {
   size_t num_found = 0;
   // TODO(hubbe): Verify support for HDR codecs when color management enabled.
@@ -190,6 +192,7 @@
       {VideoCodec::kVP9, VP9PROFILE_PROFILE2, kUnspecifiedLevel, kColorSpace}));
 #endif
 }
+#endif  // defined(ENABLE_LIBVPX)
 
 TEST(SupportedTypesTest,
      IsDecoderSupportedAudioTypeWithSpatialRenderingBasics) {
@@ -284,8 +287,10 @@
   // Expect support for baseline configuration of known codecs.
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP8, VP8PROFILE_ANY, kUnspecifiedLevel, color_space}));
+#if defined(ENABLE_LIBVPX)
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP9, VP9PROFILE_PROFILE0, kUnspecifiedLevel, color_space}));
+#endif
   EXPECT_FALSE(IsDecoderSupportedVideoType({VideoCodec::kTheora,
                                             VIDEO_CODEC_PROFILE_UNKNOWN,
                                             kUnspecifiedLevel, color_space}));
@@ -301,8 +306,10 @@
   color_space.transfer = VideoColorSpace::TransferID::SMPTEST2084;
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP8, VP8PROFILE_ANY, kUnspecifiedLevel, color_space}));
+#if defined(ENABLE_LIBVPX)
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP9, VP9PROFILE_PROFILE0, kUnspecifiedLevel, color_space}));
+#endif
   EXPECT_FALSE(IsDecoderSupportedVideoType({VideoCodec::kTheora,
                                             VIDEO_CODEC_PROFILE_UNKNOWN,
                                             kUnspecifiedLevel, color_space}));
@@ -314,8 +321,10 @@
   color_space.transfer = VideoColorSpace::TransferID::ARIB_STD_B67;
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP8, VP8PROFILE_ANY, kUnspecifiedLevel, color_space}));
+#if defined(ENABLE_LIBVPX)
   EXPECT_TRUE(IsDecoderSupportedVideoType(
       {VideoCodec::kVP9, VP9PROFILE_PROFILE0, kUnspecifiedLevel, color_space}));
+#endif
   EXPECT_FALSE(IsDecoderSupportedVideoType({VideoCodec::kTheora,
                                             VIDEO_CODEC_PROFILE_UNKNOWN,
                                             kUnspecifiedLevel, color_space}));
diff --git a/media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.cc b/media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.cc
index 73eb1fe..e0050297 100644
--- a/media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.cc
+++ b/media/cdm/library_cdm/clear_key_cdm/cdm_video_decoder.cc
@@ -31,6 +31,8 @@
 #include "media/base/decoder_status.h"
 #include "media/base/media_switches.h"
 #include "media/base/media_util.h"
+#include "media/base/video_decoder.h"
+#include "media/base/video_frame.h"
 #include "media/cdm/cdm_type_conversion.h"
 #include "media/cdm/library_cdm/cdm_host_proxy.h"
 #include "media/media_buildflags.h"
diff --git a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
index 99a6274..5b078f00 100644
--- a/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
+++ b/media/fuchsia/video/fuchsia_video_decoder_unittest.cc
@@ -91,10 +91,6 @@
   gpu::ContextSupport* ContextSupport() override {
     return &gpu_context_support_;
   }
-  class GrDirectContext* GrContext() override {
-    ADD_FAILURE();
-    return nullptr;
-  }
   gpu::SharedImageInterface* SharedImageInterface() override {
     return shared_image_interface_.get();
   }
diff --git a/media/gpu/test/video_encoder/video_encoder.h b/media/gpu/test/video_encoder/video_encoder.h
index 2cdade0..52def0c6 100644
--- a/media/gpu/test/video_encoder/video_encoder.h
+++ b/media/gpu/test/video_encoder/video_encoder.h
@@ -20,13 +20,13 @@
 #include "base/synchronization/lock.h"
 #include "base/thread_annotations.h"
 #include "base/time/time.h"
+#include "media/gpu/test/bitstream_helpers.h"
 
 namespace media {
 class VideoBitrateAllocation;
 
 namespace test {
 
-class BitstreamProcessor;
 class RawVideo;
 class VideoEncoderClient;
 struct VideoEncoderClientConfig;
diff --git a/media/mojo/clients/mojo_gpu_video_accelerator_factories_unittest.cc b/media/mojo/clients/mojo_gpu_video_accelerator_factories_unittest.cc
index 11d6a7d..a829529 100644
--- a/media/mojo/clients/mojo_gpu_video_accelerator_factories_unittest.cc
+++ b/media/mojo/clients/mojo_gpu_video_accelerator_factories_unittest.cc
@@ -159,7 +159,6 @@
   MOCK_METHOD(gpu::gles2::GLES2Interface*, ContextGL, (), (override));
   MOCK_METHOD(gpu::raster::RasterInterface*, RasterInterface, (), (override));
   MOCK_METHOD(gpu::ContextSupport*, ContextSupport, (), (override));
-  MOCK_METHOD(class GrDirectContext*, GrContext, (), (override));
   MOCK_METHOD(gpu::SharedImageInterface*, SharedImageInterface, (), (override));
   MOCK_METHOD(viz::ContextCacheController*, CacheController, (), (override));
   MOCK_METHOD(base::Lock*, GetLock, (), (override));
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
index 575b5c8..2e03259 100644
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
@@ -1728,12 +1728,10 @@
 
 class NoSyncImpl : public mojom::NoSync {
  public:
-  explicit NoSyncImpl(PendingReceiver<mojom::NoSync> receiver)
-      : receiver_(this, std::move(receiver)) {}
+  explicit NoSyncImpl(PendingReceiver<mojom::NoSync> receiver);
 
   explicit NoSyncImpl(
-      PendingAssociatedReceiver<mojom::NoSync> associated_receiver)
-      : associated_receiver_(this, std::move(associated_receiver)) {}
+      PendingAssociatedReceiver<mojom::NoSync> associated_receiver);
 
   // mojom::NoSync implementation:
   void Method(MethodCallback callback) override;
@@ -1771,6 +1769,13 @@
   std::unique_ptr<OneSyncImpl> associated_one_sync_;
 };
 
+NoSyncImpl::NoSyncImpl(PendingReceiver<mojom::NoSync> receiver)
+    : receiver_(this, std::move(receiver)) {}
+
+NoSyncImpl::NoSyncImpl(
+    PendingAssociatedReceiver<mojom::NoSync> associated_receiver)
+    : associated_receiver_(this, std::move(associated_receiver)) {}
+
 void NoSyncImpl::Method(MethodCallback callback) {
   EXPECT_TRUE(false);
   std::move(callback).Run();
diff --git a/net/disk_cache/sql/cache_entry_key.cc b/net/disk_cache/sql/cache_entry_key.cc
index def33777..398f3ff 100644
--- a/net/disk_cache/sql/cache_entry_key.cc
+++ b/net/disk_cache/sql/cache_entry_key.cc
@@ -5,13 +5,13 @@
 #include "net/disk_cache/sql/cache_entry_key.h"
 
 #include "base/check.h"
-#include "net/disk_cache/simple/simple_util.h"
+#include "base/hash/hash.h"
 
 namespace disk_cache {
 
 CacheEntryKey::CacheEntryKey(std::string str)
     : data_(base::MakeRefCounted<base::RefCountedString>(std::move(str))),
-      hash_(static_cast<int64_t>(simple_util::GetEntryHashKey(string()))) {}
+      hash_(static_cast<int32_t>(base::PersistentHash(string()))) {}
 
 CacheEntryKey::~CacheEntryKey() = default;
 
@@ -25,7 +25,8 @@
 }
 
 bool CacheEntryKey::operator==(const CacheEntryKey& other) const {
-  return data_ == other.data_ || string() == other.string();
+  return data_ == other.data_ ||
+         (hash() == other.hash() && string() == other.string());
 }
 
 const std::string& CacheEntryKey::string() const {
diff --git a/net/disk_cache/sql/cache_entry_key.h b/net/disk_cache/sql/cache_entry_key.h
index 35ad60a7..d895ea9 100644
--- a/net/disk_cache/sql/cache_entry_key.h
+++ b/net/disk_cache/sql/cache_entry_key.h
@@ -37,7 +37,7 @@
 // the main cache key string.
 class NET_EXPORT_PRIVATE CacheEntryKey {
  public:
-  using Hash = base::StrongAlias<class HashTag, int64_t>;
+  using Hash = base::StrongAlias<class HashTag, int32_t>;
 
   explicit CacheEntryKey(std::string str = "");
   ~CacheEntryKey();
diff --git a/net/disk_cache/sql/sql_backend_constants.h b/net/disk_cache/sql/sql_backend_constants.h
index 2644e4a0..e455e44 100644
--- a/net/disk_cache/sql/sql_backend_constants.h
+++ b/net/disk_cache/sql/sql_backend_constants.h
@@ -58,21 +58,24 @@
 //            cleaned up. Instead of a delayed task, cleanup is now triggered
 //            during browser idle periods. Also, the index on `res_id` for
 //            doomed entries was removed as it's no longer needed.
+// Version 6: https://crrev.com/c/7006231 changed the hash function for cache
+//            keys to base::PersistentHash, which uses a 32-bit hash. This is a
+//            breaking change as the previous version used a 64-bit hash.
 // ----------------------------------------------------------------------------
 
 // The oldest database schema version that the current code can read.
 // A database with a version older than this will be razed as it's considered
 // obsolete and the code no longer supports migrating from it.
-inline constexpr int kSqlBackendLowestSupportedDatabaseVersion = 5;
+inline constexpr int kSqlBackendLowestSupportedDatabaseVersion = 6;
 
 // The current version of the database schema. This should be incremented for
 // any schema change.
-inline constexpr int kSqlBackendCurrentDatabaseVersion = 5;
+inline constexpr int kSqlBackendCurrentDatabaseVersion = 6;
 
 // The oldest application version that can use a database with the current
 // schema. If a schema change is not backward-compatible, this must be set to
 // the same value as `kSqlBackendCurrentDatabaseVersion`.
-inline constexpr int kSqlBackendCompatibleDatabaseVersion = 5;
+inline constexpr int kSqlBackendCompatibleDatabaseVersion = 6;
 
 // Estimated static size overhead for a resource entry in the database,
 // excluding the key and any blob data. This is a conservative estimate based on
diff --git a/net/disk_cache/sql/sql_persistent_store.cc b/net/disk_cache/sql/sql_persistent_store.cc
index 44fb843b..b4979437 100644
--- a/net/disk_cache/sql/sql_persistent_store.cc
+++ b/net/disk_cache/sql/sql_persistent_store.cc
@@ -666,7 +666,7 @@
             Query::kGetCacheKeyHashes_SelectCacheKeyHashFromLiveResources)));
     while (statement.Step()) {
       const auto res_id = ResId(statement.ColumnInt64(0));
-      const auto key_hash = CacheEntryKey::Hash(statement.ColumnInt64(1));
+      const auto key_hash = CacheEntryKey::Hash(statement.ColumnInt(1));
       const bool doomed = statement.ColumnBool(2);
       if (doomed) {
         doomed_entry_res_ids.emplace_back(res_id);
@@ -796,7 +796,7 @@
 
   sql::Statement statement(db_.GetCachedStatement(
       SQL_FROM_HERE, GetQuery(Query::kOpenEntry_SelectLiveResources)));
-  statement.BindInt64(0, key.hash().value());
+  statement.BindInt(0, key.hash().value());
   statement.BindString(1, key.string());
   if (!statement.Step()) {
     // `Step()` returned false, which means either the query completed with no
@@ -890,7 +890,7 @@
     statement.BindTime(0, entry_info.last_used);
     statement.BindInt64(1, entry_info.body_end);
     statement.BindInt64(2, bytes_usage);
-    statement.BindInt64(3, key.hash().value());
+    statement.BindInt(3, key.hash().value());
     statement.BindString(4, key.string());
     if (!statement.Step()) {
       return base::unexpected(Error::kFailedToExecute);
@@ -1150,7 +1150,7 @@
   {
     sql::Statement statement(db_.GetCachedStatement(
         SQL_FROM_HERE, GetQuery(Query::kDeleteLiveEntry_DeleteFromResources)));
-    statement.BindInt64(0, key.hash().value());
+    statement.BindInt(0, key.hash().value());
     statement.BindString(1, key.string());
     while (statement.Step()) {
       const auto res_id = ResId(statement.ColumnInt64(0));
@@ -1394,7 +1394,7 @@
         SQL_FROM_HERE,
         GetQuery(Query::kUpdateEntryLastUsedByKey_UpdateResourceLastUsed)));
     statement.BindTime(0, last_used);
-    statement.BindInt64(1, key.hash().value());
+    statement.BindInt(1, key.hash().value());
     statement.BindString(2, key.string());
     if (!statement.Run()) {
       return Error::kFailedToExecute;
diff --git a/services/network/cookie_access_delegate_impl_unittest.cc b/services/network/cookie_access_delegate_impl_unittest.cc
index b139f69..ccfc7c1 100644
--- a/services/network/cookie_access_delegate_impl_unittest.cc
+++ b/services/network/cookie_access_delegate_impl_unittest.cc
@@ -55,7 +55,7 @@
           base::BindOnce(
               [](net::FirstPartySetMetadata,
                  net::FirstPartySetsCacheFilter::MatchInfo) { FAIL(); })),
-      Optional(std::make_pair(std::ref(expected_metadata),
+      Optional(std::make_pair(std::cref(expected_metadata),
                               net::FirstPartySetsCacheFilter::MatchInfo())));
 
   EXPECT_THAT(
diff --git a/services/network/shared_dictionary/shared_dictionary_manager.cc b/services/network/shared_dictionary/shared_dictionary_manager.cc
index e7507ba..a8625c8 100644
--- a/services/network/shared_dictionary/shared_dictionary_manager.cc
+++ b/services/network/shared_dictionary/shared_dictionary_manager.cc
@@ -158,6 +158,8 @@
     cached_storages_.Clear();
     preloaded_dictionaries_set_.clear();
   }
+
+  HandleMemoryPressure(level);
 }
 
 size_t SharedDictionaryManager::GetStorageCountForTesting() {
diff --git a/services/network/shared_dictionary/shared_dictionary_manager.h b/services/network/shared_dictionary/shared_dictionary_manager.h
index 5efc3ed..57f6c9634a 100644
--- a/services/network/shared_dictionary/shared_dictionary_manager.h
+++ b/services/network/shared_dictionary/shared_dictionary_manager.h
@@ -97,6 +97,8 @@
       base::Time start_time,
       base::Time end_time,
       base::OnceCallback<void(const std::vector<url::Origin>&)> callback) = 0;
+  virtual void HandleMemoryPressure(
+      base::MemoryPressureLevel memory_pressure_level) = 0;
 
   net::SharedDictionaryGetter MaybeCreateSharedDictionaryGetter(
       int request_load_flags,
diff --git a/services/network/shared_dictionary/shared_dictionary_manager_in_memory.h b/services/network/shared_dictionary/shared_dictionary_manager_in_memory.h
index 88dbabf1..1de039b5 100644
--- a/services/network/shared_dictionary/shared_dictionary_manager_in_memory.h
+++ b/services/network/shared_dictionary/shared_dictionary_manager_in_memory.h
@@ -52,6 +52,8 @@
       base::Time end_time,
       base::OnceCallback<void(const std::vector<url::Origin>&)> callback)
       override;
+  void HandleMemoryPressure(
+      base::MemoryPressureLevel memory_pressure_level) override {}
 
   void MaybeRunCacheEvictionPerSite(const net::SchemefulSite& top_frame_site);
   void MaybeRunCacheEviction();
diff --git a/services/network/shared_dictionary/shared_dictionary_manager_on_disk.cc b/services/network/shared_dictionary/shared_dictionary_manager_on_disk.cc
index b0388af..1b90b7c 100644
--- a/services/network/shared_dictionary/shared_dictionary_manager_on_disk.cc
+++ b/services/network/shared_dictionary/shared_dictionary_manager_on_disk.cc
@@ -493,12 +493,6 @@
           base::CommandLine::ForCurrentProcess()->HasSwitch(
               switches::kDisableSharedDictionaryStorageCleanupForTesting)) {
   dictionary_cache_ = base::MakeRefCounted<SharedDictionaryCache>();
-  memory_pressure_listener_registration_ =
-      std::make_unique<base::AsyncMemoryPressureListenerRegistration>(
-          FROM_HERE,
-          base::MemoryPressureListenerTag::kSharedDictionaryManagerOnDisk,
-          base::BindRepeating(&SharedDictionaryManagerOnDisk::OnMemoryPressure,
-                              weak_factory_.GetWeakPtr()));
   disk_cache_.Initialize(cache_directory_path,
 #if BUILDFLAG(IS_ANDROID)
                          app_status_listener_getter,
@@ -593,6 +587,13 @@
           std::move(callback)));
 }
 
+void SharedDictionaryManagerOnDisk::HandleMemoryPressure(
+    base::MemoryPressureLevel level) {
+  if (level != base::MEMORY_PRESSURE_LEVEL_NONE) {
+    dictionary_cache_->Clear();
+  }
+}
+
 scoped_refptr<SharedDictionaryWriter>
 SharedDictionaryManagerOnDisk::CreateWriter(
     const net::SharedDictionaryIsolationKey& isolation_key,
@@ -833,11 +834,4 @@
           weak_factory_.GetWeakPtr())));
 }
 
-void SharedDictionaryManagerOnDisk::OnMemoryPressure(
-    base::MemoryPressureLevel level) {
-  if (level != base::MEMORY_PRESSURE_LEVEL_NONE) {
-    dictionary_cache_->Clear();
-  }
-}
-
 }  // namespace network
diff --git a/services/network/shared_dictionary/shared_dictionary_manager_on_disk.h b/services/network/shared_dictionary/shared_dictionary_manager_on_disk.h
index 1b71861b5..cb92d2d 100644
--- a/services/network/shared_dictionary/shared_dictionary_manager_on_disk.h
+++ b/services/network/shared_dictionary/shared_dictionary_manager_on_disk.h
@@ -83,6 +83,8 @@
       base::Time end_time,
       base::OnceCallback<void(const std::vector<url::Origin>&)> callback)
       override;
+  void HandleMemoryPressure(
+      base::MemoryPressureLevel memory_pressure_level) override;
 
   SharedDictionaryDiskCache& disk_cache() { return disk_cache_; }
   net::SQLitePersistentSharedDictionaryStore& metadata_store() {
@@ -174,8 +176,6 @@
     return writing_disk_cache_key_tokens_;
   }
 
-  void OnMemoryPressure(base::MemoryPressureLevel level);
-
   uint64_t cache_max_size() const { return cache_max_size_; }
   uint64_t cache_max_count() const { return cache_max_count_; }
 
@@ -195,8 +195,6 @@
   bool expired_entry_deletion_task_queued_ = false;
 
   bool cleanup_task_disabled_for_testing_ = false;
-  std::unique_ptr<base::AsyncMemoryPressureListenerRegistration>
-      memory_pressure_listener_registration_;
 
   base::WeakPtrFactory<SharedDictionaryManagerOnDisk> weak_factory_{this};
 };
diff --git a/services/network/slop_bucket.cc b/services/network/slop_bucket.cc
index 981cfe2..1c927b4 100644
--- a/services/network/slop_bucket.cc
+++ b/services/network/slop_bucket.cc
@@ -116,6 +116,10 @@
                                      base::MEMORY_PRESSURE_LEVEL_MODERATE,
                                      &kMemoryPressureLevelOptions);
 
+// "enabled_for_cache_response" parameter.
+constexpr base::FeatureParam<bool>
+    kEnabledForCacheresponse(&kSlopBucket, "enabled_for_cache_response", true);
+
 }  // namespace
 
 // This class encapsulates the runtime configuration of SlopBucket. When
@@ -135,6 +139,9 @@
   base::MemoryPressureLevel memory_pressure_disable_level() const {
     return memory_pressure_disable_level_;
   }
+  bool enabled_for_cache_response() const {
+    return enabled_for_cache_response_;
+  }
 
  private:
   friend std::ostream& operator<<(std::ostream& os,
@@ -187,6 +194,8 @@
           "max_chunks_total is less than max_chunks_per_request");
     }
     memory_pressure_disable_level_ = kMemoryPressureDisableLevelParam.Get();
+
+    enabled_for_cache_response_ = kEnabledForCacheresponse.Get();
   }
 
   void DisableWithWarning(const char* warning) {
@@ -209,6 +218,8 @@
 
   base::MemoryPressureLevel memory_pressure_disable_level_ =
       kDefaultMemoryPressureDisableLevel;
+
+  bool enabled_for_cache_response_ = true;
 };
 
 // SlopBucketManager tracks global state for SlopBuckets. It is thread-hostile.
@@ -268,6 +279,10 @@
   size_t chunk_size() const { return configuration_.chunk_size(); }
   size_t min_buffer_size() const { return configuration_.min_buffer_size(); }
 
+  bool enabled_for_cache_response() const {
+    return configuration_.enabled_for_cache_response();
+  }
+
   scoped_refptr<ChunkIOBuffer> RequestChunk(size_t existing_chunks) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     if (disabled()) {
@@ -514,6 +529,16 @@
     return nullptr;
   }
 
+  using CacheEntryStatus = net::HttpResponseInfo::CacheEntryStatus;
+  const CacheEntryStatus& cache_entry_status =
+      for_request->response_info().cache_entry_status;
+  const bool is_response_from_cache =
+      cache_entry_status == CacheEntryStatus::ENTRY_USED ||
+      cache_entry_status == CacheEntryStatus::ENTRY_VALIDATED;
+  if (is_response_from_cache && !manager.enabled_for_cache_response()) {
+    return nullptr;
+  }
+
   return std::make_unique<SlopBucket>(PassKey(), for_request);
 }
 
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index 7834c23..622190e 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -1533,6 +1533,7 @@
         bool should_wait = true;
         if (base::FeatureList::IsEnabled(kSlopBucket) && !slop_bucket_) {
           slop_bucket_ = SlopBucket::RequestSlopBucket(url_request_.get());
+          was_slop_bucket_enabled_ = true;
         }
         if (slop_bucket_ && !slop_bucket_->read_in_progress() &&
             !slop_bucket_->IsComplete()) {
@@ -1948,10 +1949,25 @@
                                    total_received, 50, 10 * 1000 * 1000, 50);
     mojo_begin_write_count_for_uma_ =
         std::max(mojo_begin_write_count_for_uma_, 1);
+    const int proportion = mojo_blocked_write_count_for_uma_ * 100 /
+                           mojo_begin_write_count_for_uma_;
     base::UmaHistogramPercentage(
-        "Net.URLLoader.ProportionOfWritesBlockedByMojo",
-        mojo_blocked_write_count_for_uma_ * 100 /
-            mojo_begin_write_count_for_uma_);
+        "Net.URLLoader.ProportionOfWritesBlockedByMojo", proportion);
+    if (was_slop_bucket_enabled_) {
+      base::UmaHistogramPercentage(
+          "Net.URLLoader.SlopBucket.ProportionOfWritesBlockedByMojo.All",
+          proportion);
+
+      using CacheEntryStatus = net::HttpResponseInfo::CacheEntryStatus;
+      const CacheEntryStatus& cache_entry_status =
+          url_request_->response_info().cache_entry_status;
+      if (cache_entry_status != CacheEntryStatus::ENTRY_USED &&
+          cache_entry_status != CacheEntryStatus::ENTRY_VALIDATED) {
+        base::UmaHistogramPercentage(
+            "Net.URLLoader.SlopBucket.ProportionOfWritesBlockedByMojo.NoCache",
+            proportion);
+      }
+    }
   }
 
   if (total_sent > 0) {
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 21dc5e84807..09c035a 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -762,6 +762,7 @@
   // Internal counters to record UMA for SlopBucket.
   int mojo_begin_write_count_for_uma_ = 0;
   int mojo_blocked_write_count_for_uma_ = 0;
+  bool was_slop_bucket_enabled_ = false;
 
   // For decoding a small part of the response body to check its type (for ORB
   // and MIME sniffing) when the response might be compressed and client-side
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
index cb104393b..747e05d8 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -47,7 +47,6 @@
 #include "services/viz/public/cpp/gpu/command_buffer_metrics.h"
 #include "skia/buildflags.h"
 #include "third_party/skia/include/core/SkTraceMemoryDump.h"
-#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 #include "ui/gl/trace_util.h"
 
 class SkDiscardableMemory;
@@ -472,12 +471,6 @@
   return impl_;
 }
 
-class GrDirectContext* ContextProviderCommandBuffer::GrContext() {
-  DCHECK(bind_tried_);
-  DCHECK_EQ(bind_result_, gpu::ContextResult::kSuccess);
-  return nullptr;
-}
-
 gpu::SharedImageInterface*
 ContextProviderCommandBuffer::SharedImageInterface() {
   return shared_image_interface_.get();
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index 41c575a..2dbecfb 100644
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -126,7 +126,6 @@
   gpu::gles2::GLES2Interface* ContextGL() override;
   gpu::raster::RasterInterface* RasterInterface() override;
   gpu::ContextSupport* ContextSupport() override;
-  class GrDirectContext* GrContext() override;
   gpu::SharedImageInterface* SharedImageInterface() override;
   ContextCacheController* CacheController() override;
   base::Lock* GetLock() override;
diff --git a/services/webnn/ort/context_impl_ort.cc b/services/webnn/ort/context_impl_ort.cc
index d5150c2..054ab05c 100644
--- a/services/webnn/ort/context_impl_ort.cc
+++ b/services/webnn/ort/context_impl_ort.cc
@@ -252,7 +252,7 @@
        {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)},
        /*matmul_input=*/{DataTypeConstraint::kFloat16To32Ints32To64, kMaxRank},
        /*pad_input=*/
-       {DataTypeConstraint::kAllDataTypesAtLeast8bits, kMaxNonScalarRank},
+       {DataTypeConstraint::kAllDataTypesAtLeast8bits, kMaxRank},
        /*average_pool2d_input=*/{DataTypeConstraint::kFloat16To32, {3, 8}},
        /*l2_pool2d_input=*/{DataTypeConstraint::kFloat16To32, {3, 8}},
        /*max_pool2d_input=*/{kInts8Float16To32, {3, 8}},
@@ -303,7 +303,7 @@
        /*sigmoid_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank},
        /*slice_input=*/
        {DataTypeConstraint::kAllDataTypesAtLeast8bits, kMaxRank},
-       /*softmax_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank},
+       /*softmax_input=*/{DataTypeConstraint::kFloat16To32, kMaxNonScalarRank},
        /*softplus_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank},
        /*softsign_input=*/{DataTypeConstraint::kFloat16To32, kMaxRank},
        /*split_input=*/
diff --git a/services/webnn/tflite/graph_builder_tflite.cc b/services/webnn/tflite/graph_builder_tflite.cc
index 889d951..7e72d6b 100644
--- a/services/webnn/tflite/graph_builder_tflite.cc
+++ b/services/webnn/tflite/graph_builder_tflite.cc
@@ -502,9 +502,12 @@
        /*arg_min_max_output=*/
        {DataTypeConstraint::kInt32To64, SupportedRanks::UpTo(8)},
        // BatchNormalization is emulated by sub, mul, add and div ops that only
-       // support max rank up to 5.
+       // support max rank up to 5. Because `SerializeBatchNormalization()`
+       // emulation code accesses input size along axis, input cannot be a
+       // scalar:
+       // https://source.chromium.org/chromium/chromium/src/+/main:services/webnn/tflite/graph_builder_tflite.cc;l=3556;drc=7b1dd7749fbb05ea8469492fe5c03c27fef75e38
        /*batch_normalization_input=*/
-       {DataTypeConstraint::kFloat16To32, SupportedRanks::UpTo(5)},
+       {DataTypeConstraint::kFloat16To32, SupportedRanks::NonScalarUpTo(5)},
        /*batch_normalization_mean=*/
        {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)},
        /*cast_input=*/
@@ -512,7 +515,10 @@
        // Polyfilled using MIN and MAX.
        /*clamp_input=*/
        {DataTypeConstraint::kFloat16To32, SupportedRanks::UpTo(5)},
-       /*concat_inputs=*/{kAllDataTypesExceptUint4, SupportedRanks::UpTo(8)},
+       // Scalar is not supported:
+       // https://source.chromium.org/chromium/chromium/src/+/main:third_party/tflite/src/tensorflow/lite/kernels/internal/reference/concatenation.h;l=38;drc=31b46e86a93151ca1192009863818d4eaf5df831
+       /*concat_inputs=*/
+       {kAllDataTypesExceptUint4, SupportedRanks::NonScalarUpTo(8)},
        // https://source.chromium.org/chromium/chromium/src/+/main:third_party/tflite/src/tensorflow/lite/kernels/conv.cc
        /*conv2d_input=*/
        {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)},
@@ -620,8 +626,10 @@
        /*elu_input=*/{kFloat16To32AndInt8, SupportedRanks::UpTo(5)},
        /*expand_input=*/
        {kFloat16To32AndInts8To32AndInt64, SupportedRanks::UpTo(8)},
+       // Scalar is not supported:
+       // https://source.chromium.org/chromium/chromium/src/+/main:third_party/tflite/src/tensorflow/lite/kernels/internal/reference/gather.h;l=43;drc=49db932a0bdfca060c3e8b0d063a7e8c9f5d2fa5
        /*gather_input=*/
-       {kFloat16To32AndInt8To64AndUint8, SupportedRanks::UpTo(8)},
+       {kFloat16To32AndInt8To64AndUint8, SupportedRanks::NonScalarUpTo(8)},
        /*gather_indices=*/
        {DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes,
         SupportedRanks::UpTo(8)},
diff --git a/services/webnn/webnn_context_impl.cc b/services/webnn/webnn_context_impl.cc
index 1f5d8f5..dad6d57 100644
--- a/services/webnn/webnn_context_impl.cc
+++ b/services/webnn/webnn_context_impl.cc
@@ -392,23 +392,41 @@
   // A specific maximum rank is still under discussion, but 8 is the highest
   // supported by any backend.
   constexpr SupportedRanks kNonScalarMaxRank = SupportedRanks::NonScalarUpTo(8);
+  constexpr SupportedRanks kAtLeast2D{2, 8};
 
   // Only intersects for ones that have limits defined in the specification.
   // For ones that has no limit, no need to intersect with
   // `SupportedDataTypes::All()`.
+  backend_context_properties.data_type_limits.arg_min_max_input.ranks
+      .IntersectWith(kNonScalarMaxRank);
+  backend_context_properties.data_type_limits.arg_min_max_output.data_types
+      .RetainAll(DataTypeConstraint::kInt32To64);
   backend_context_properties.data_type_limits.batch_normalization_input
-      .data_types.RetainAll(DataTypeConstraint::kFloat16To32);
+      .IntersectWith({DataTypeConstraint::kFloat16To32, kNonScalarMaxRank});
   backend_context_properties.data_type_limits.batch_normalization_mean
       .IntersectWith(
           {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)});
-  backend_context_properties.data_type_limits.conv2d_input.ranks.IntersectWith(
-      SupportedRanks::Exactly(4));
-  backend_context_properties.data_type_limits.conv2d_bias.ranks.IntersectWith(
-      SupportedRanks::Exactly(1));
-  backend_context_properties.data_type_limits.conv_transpose2d_input.ranks
-      .IntersectWith(SupportedRanks::Exactly(4));
-  backend_context_properties.data_type_limits.conv_transpose2d_bias.ranks
-      .IntersectWith(SupportedRanks::Exactly(1));
+  backend_context_properties.data_type_limits.concat_inputs.ranks.IntersectWith(
+      kNonScalarMaxRank);
+  backend_context_properties.data_type_limits.conv2d_input.IntersectWith(
+      {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)});
+  backend_context_properties.data_type_limits.conv2d_bias.IntersectWith(
+      {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)});
+  backend_context_properties.data_type_limits.conv_transpose2d_input
+      .IntersectWith(
+          {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)});
+  backend_context_properties.data_type_limits.conv_transpose2d_bias
+      .IntersectWith(
+          {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)});
+  backend_context_properties.data_type_limits.cumulative_sum_input
+      .IntersectWith(
+          {DataTypeConstraint::kFloat16To32Ints32To64, kNonScalarMaxRank});
+  backend_context_properties.data_type_limits.dequantize_linear_input.data_types
+      .RetainAll(DataTypeConstraint::kInts4Ints8Ints32);
+  backend_context_properties.data_type_limits.dequantize_linear_scale.data_types
+      .RetainAll(DataTypeConstraint::kFloat16To32);
+  backend_context_properties.data_type_limits.dequantize_linear_zero_point
+      .data_types.RetainAll(DataTypeConstraint::kInts4Ints8Ints32);
   backend_context_properties.data_type_limits.logical_and_input.data_types
       .RetainAll(DataTypeConstraint::kUint8);
   backend_context_properties.data_type_limits.logical_or_input.data_types
@@ -429,15 +447,6 @@
       DataTypeConstraint::kFloat16To32);
   backend_context_properties.data_type_limits.cos_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32);
-  backend_context_properties.data_type_limits.cumulative_sum_input
-      .IntersectWith(
-          {DataTypeConstraint::kFloat16To32Ints32To64, kNonScalarMaxRank});
-  backend_context_properties.data_type_limits.dequantize_linear_input.data_types
-      .RetainAll(DataTypeConstraint::kInts4Ints8Ints32);
-  backend_context_properties.data_type_limits.dequantize_linear_scale.data_types
-      .RetainAll(DataTypeConstraint::kFloat16To32);
-  backend_context_properties.data_type_limits.dequantize_linear_zero_point
-      .data_types.RetainAll(DataTypeConstraint::kInts4Ints8Ints32);
   backend_context_properties.data_type_limits.erf_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32);
   backend_context_properties.data_type_limits.exp_input.data_types.RetainAll(
@@ -463,20 +472,20 @@
   backend_context_properties.data_type_limits.elu_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32);
   backend_context_properties.data_type_limits.gather_input.ranks.IntersectWith(
-      SupportedRanks::NonScalarUpTo(8));
+      kNonScalarMaxRank);
   backend_context_properties.data_type_limits.gather_indices.data_types
       .RetainAll(DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes);
   backend_context_properties.data_type_limits.gather_elements_input.ranks
-      .IntersectWith(SupportedRanks::NonScalarUpTo(8));
+      .IntersectWith(kNonScalarMaxRank);
   backend_context_properties.data_type_limits.gather_elements_indices
       .IntersectWith(
           {DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes,
-           SupportedRanks::NonScalarUpTo(8)});
+           kNonScalarMaxRank});
   backend_context_properties.data_type_limits.gather_nd_input.ranks
-      .IntersectWith(SupportedRanks::NonScalarUpTo(8));
+      .IntersectWith(kNonScalarMaxRank);
   backend_context_properties.data_type_limits.gather_nd_indices.IntersectWith(
       {DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes,
-       SupportedRanks::NonScalarUpTo(8)});
+       kNonScalarMaxRank});
   backend_context_properties.data_type_limits.gelu_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32);
   backend_context_properties.data_type_limits.gemm_a.IntersectWith(
@@ -521,16 +530,14 @@
   backend_context_properties.data_type_limits.lstm_cell_bias.IntersectWith(
       {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(1)});
   backend_context_properties.data_type_limits.matmul_input.IntersectWith(
-      {DataTypeConstraint::kFloat16To32, {2, 8}});
-  backend_context_properties.data_type_limits.pad_input.IntersectWith(
-      {SupportedDataTypes::All(), kNonScalarMaxRank});
+      {DataTypeConstraint::kFloat16To32, kAtLeast2D});
   backend_context_properties.data_type_limits.average_pool2d_input
       .IntersectWith(
           {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)});
   backend_context_properties.data_type_limits.l2_pool2d_input.IntersectWith(
       {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)});
-  backend_context_properties.data_type_limits.max_pool2d_input.IntersectWith(
-      {SupportedDataTypes::All(), SupportedRanks::Exactly(4)});
+  backend_context_properties.data_type_limits.max_pool2d_input.ranks
+      .IntersectWith(SupportedRanks::Exactly(4));
   backend_context_properties.data_type_limits.prelu_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32Int8To64);
   backend_context_properties.data_type_limits.quantize_linear_input.data_types
@@ -558,29 +565,29 @@
   backend_context_properties.data_type_limits.resample2d_input.IntersectWith(
       {DataTypeConstraint::kFloat16To32, SupportedRanks::Exactly(4)});
   backend_context_properties.data_type_limits.scatter_elements_input.ranks
-      .IntersectWith(SupportedRanks::NonScalarUpTo(8));
+      .IntersectWith(kNonScalarMaxRank);
   backend_context_properties.data_type_limits.scatter_elements_indices
       .data_types.RetainAll(
           DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes);
   backend_context_properties.data_type_limits.scatter_nd_input.ranks
-      .IntersectWith(SupportedRanks::NonScalarUpTo(8));
+      .IntersectWith(kNonScalarMaxRank);
   backend_context_properties.data_type_limits.scatter_nd_indices.IntersectWith(
       {DataTypeConstraint::kGatherScatterIndicesSupportedDataTypes,
-       SupportedRanks::NonScalarUpTo(8)});
+       kNonScalarMaxRank});
   backend_context_properties.data_type_limits.sigmoid_input.data_types
       .RetainAll(DataTypeConstraint::kFloat16To32);
-  backend_context_properties.data_type_limits.slice_input.IntersectWith(
-      {SupportedDataTypes::All(), kNonScalarMaxRank});
-  backend_context_properties.data_type_limits.softmax_input.data_types
-      .RetainAll(DataTypeConstraint::kFloat16To32);
+  backend_context_properties.data_type_limits.softmax_input.IntersectWith(
+      {DataTypeConstraint::kFloat16To32, kNonScalarMaxRank});
   backend_context_properties.data_type_limits.softplus_input.data_types
       .RetainAll(DataTypeConstraint::kFloat16To32);
   backend_context_properties.data_type_limits.softsign_input.data_types
       .RetainAll(DataTypeConstraint::kFloat16To32);
+  backend_context_properties.data_type_limits.split_input.ranks.IntersectWith(
+      kNonScalarMaxRank);
   backend_context_properties.data_type_limits.tanh_input.data_types.RetainAll(
       DataTypeConstraint::kFloat16To32);
-  backend_context_properties.data_type_limits.triangular_input.IntersectWith(
-      {SupportedDataTypes::All(), {2, 8}});
+  backend_context_properties.data_type_limits.triangular_input.ranks
+      .IntersectWith(kAtLeast2D);
   backend_context_properties.data_type_limits.where_condition.data_types
       .RetainAll(DataTypeConstraint::kUint8);
   return backend_context_properties;
diff --git a/testing/perf/cbb_ref_info/edge/dev/windows.json b/testing/perf/cbb_ref_info/edge/dev/windows.json
index 00bb32bf..deb6d4aa 100644
--- a/testing/perf/cbb_ref_info/edge/dev/windows.json
+++ b/testing/perf/cbb_ref_info/edge/dev/windows.json
@@ -2,5 +2,5 @@
   "browser": "edge",
   "channel": "dev",
   "platform": "windows",
-  "version": "142.0.3581.0"
+  "version": "142.0.3595.7"
 }
\ No newline at end of file
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 05e4ba7..8e8bb34 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -12799,6 +12799,28 @@
                     ]
                 }
             ]
+        },
+        {
+            "platforms": [
+                "chromeos",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled_NVS_HttpCache_Only_WithNewAreEquivalent_DevCanary_1008_Desktop",
+                    "enable_features": [
+                        "HttpCacheNoVarySearch",
+                        "HttpNoVarySearchDataUseNewAreEquivalent"
+                    ],
+                    "disable_features": [
+                        "DsePreload2",
+                        "PrefetchPrerenderIntegration",
+                        "SearchPrefetchWithNoVarySearchDiskCache"
+                    ]
+                }
+            ]
         }
     ],
     "HttpDiskCachePrewarming": [
@@ -23983,6 +24005,15 @@
             "experiments": [
                 {
                     "name": "Enabled",
+                    "params": {
+                        "chunk_size": "524288",
+                        "enabled_for_cache_response": "true",
+                        "max_chunks_per_request": "8",
+                        "max_chunks_total": "32",
+                        "memory_pressure_disable_level": "MODERATE",
+                        "min_buffer_size": "32768",
+                        "require_priority": "MEDIUM"
+                    },
                     "enable_features": [
                         "SlopBucket"
                     ]
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index 5c676d1..25b940f 100644
--- a/third_party/androidx/build.gradle
+++ b/third_party/androidx/build.gradle
@@ -314,7 +314,7 @@
     google()
     maven {
         // This URL is generated by the fetch_all_androidx.py script.
-        url 'https://androidx.dev/snapshots/builds/14233173/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/14236064/artifacts/repository'
     }
     mavenCentral()
 }
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
index b498c3a..968532e 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity
 Short Name: activity
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/activity/activity/1.12.0-SNAPSHOT/activity-1.12.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/activity/activity/1.12.0-SNAPSHOT/activity-1.12.0-20251008.211458-1.aar
 Version: 1.12.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
index 79e202a3..50dcf94 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity_compose/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity Compose
 Short Name: activity-compose
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/activity/activity-compose/1.12.0-SNAPSHOT/activity-compose-1.12.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/activity/activity-compose/1.12.0-SNAPSHOT/activity-compose-1.12.0-20251008.211458-1.aar
 Version: 1.12.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
index 27fcb1ce..d02bda0cc 100644
--- a/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_activity_activity_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Activity Kotlin Extensions
 Short Name: activity-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/activity/activity-ktx/1.12.0-SNAPSHOT/activity-ktx-1.12.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/activity/activity-ktx/1.12.0-SNAPSHOT/activity-ktx-1.12.0-20251008.211458-1.aar
 Version: 1.12.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium b/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
index 21c9f7d0..9f74009f 100644
--- a/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_annotation_annotation_experimental/README.chromium
@@ -1,6 +1,6 @@
 Name: Experimental annotation
 Short Name: annotation-experimental
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20251008.211458-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
index dc055a1..69c636d 100644
--- a/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_annotation_annotation_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: Annotation
 Short Name: annotation-jvm
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20251008.211458-1.jar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium b/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
index d9b02f0..26d2f81 100644
--- a/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appcompat_appcompat/README.chromium
@@ -1,6 +1,6 @@
 Name: AppCompat
 Short Name: appcompat
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20251008.211458-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium b/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
index b2ca89e2c..18a5617 100644
--- a/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appcompat_appcompat_resources/README.chromium
@@ -1,6 +1,6 @@
 Name: AppCompat Resources
 Short Name: appcompat-resources
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20251008.211458-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
index f5b2144f..bdaba6d 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch
 Short Name: appsearch
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
index 2496ce9f..ba1a9128 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_builtin_types/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch Builtin Types
 Short Name: appsearch-builtin-types
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
index 77fb61e..f8c87bd 100644
--- a/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_appsearch_appsearch_platform_storage/README.chromium
@@ -1,6 +1,6 @@
 Name: AppSearch Platform Storage
 Short Name: appsearch-platform-storage
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium b/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
index 12dec2be..44a3b8eb 100644
--- a/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_arch_core_core_common/README.chromium
@@ -1,6 +1,6 @@
 Name: Arch-Common
 Short Name: core-common
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20251008.211458-1.jar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium b/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
index d5fc6b4..2431d22e 100644
--- a/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_arch_core_core_runtime/README.chromium
@@ -1,6 +1,6 @@
 Name: Arch-Runtime
 Short Name: core-runtime
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20251008.211458-1.aar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium b/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
index 2046b975..47819673 100644
--- a/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_autofill_autofill/README.chromium
@@ -1,6 +1,6 @@
 Name: Autofill
 Short Name: autofill
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20251008.211458-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
index 9a78b1f..fad3193 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_common/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Common
 Short Name: benchmark-common
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
index 7949d37e..dc91cac 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_junit4/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - JUnit4
 Short Name: benchmark-junit4
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
index 70c17da..00b73d82 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Macrobenchmark
 Short Name: benchmark-macro
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
index 805aaf4f..4c5a352 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_macro_junit4/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark - Macrobenchmark JUnit4
 Short Name: benchmark-macro-junit4
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
index d4288a6..9432d8a 100644
--- a/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_benchmark_benchmark_traceprocessor_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Benchmark TraceProcessor
 Short Name: benchmark-traceprocessor-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium b/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
index 3d848c6..d4af0f76 100644
--- a/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_biometric_biometric/README.chromium
@@ -1,6 +1,6 @@
 Name: Biometric
 Short Name: biometric
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20251008.211458-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium b/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
index 12e0204..ad748f4 100644
--- a/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_browser_browser/README.chromium
@@ -1,6 +1,6 @@
 Name: Browser
 Short Name: browser
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium b/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
index df88f6d..22ac539 100644
--- a/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_cardview_cardview/README.chromium
@@ -1,6 +1,6 @@
 Name: CardView
 Short Name: cardview
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
index 59fb5a6..5d69450 100644
--- a/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_collection_collection_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: collections
 Short Name: collection-jvm
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/collection/collection-jvm/1.6.0-SNAPSHOT/collection-jvm-1.6.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/collection/collection-jvm/1.6.0-SNAPSHOT/collection-jvm-1.6.0-20251008.211458-1.jar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
index 8443ee3..4bf1614 100644
--- a/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_collection_collection_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Collections Kotlin Extensions
 Short Name: collection-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/collection/collection-ktx/1.6.0-SNAPSHOT/collection-ktx-1.6.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/collection/collection-ktx/1.6.0-SNAPSHOT/collection-ktx-1.6.0-20251008.211458-1.jar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
index 5f330696..d8e5aad 100644
--- a/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_animation_animation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Animation
 Short Name: animation-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/animation/animation-android/1.10.0-SNAPSHOT/animation-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/animation/animation-android/1.10.0-SNAPSHOT/animation-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
index 0e50be01..7565c04 100644
--- a/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_animation_animation_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Animation Core
 Short Name: animation-core-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/animation/animation-core-android/1.10.0-SNAPSHOT/animation-core-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/animation/animation-core-android/1.10.0-SNAPSHOT/animation-core-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
index 124fc967..9c2f629dc 100644
--- a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Foundation
 Short Name: foundation-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/foundation/foundation-android/1.10.0-SNAPSHOT/foundation-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/foundation/foundation-android/1.10.0-SNAPSHOT/foundation-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
index e4d66bf..5a6d2ef 100644
--- a/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_foundation_foundation_layout_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Layouts
 Short Name: foundation-layout-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.10.0-SNAPSHOT/foundation-layout-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.10.0-SNAPSHOT/foundation-layout-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
index c585fa2..a334ff3 100644
--- a/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_material3_material3_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Material3 Components
 Short Name: material3-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
index ee6a3f9..c427a40 100644
--- a/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_material_material_ripple_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Material Ripple
 Short Name: material-ripple-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/material/material-ripple-android/1.10.0-SNAPSHOT/material-ripple-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/material/material-ripple-android/1.10.0-SNAPSHOT/material-ripple-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
index cf1f734..efbc5e8 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime
 Short Name: runtime-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/runtime/runtime-android/1.10.0-SNAPSHOT/runtime-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/runtime/runtime-android/1.10.0-SNAPSHOT/runtime-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
index dd4a549d..e36aeec 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_annotation_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime Annotation
 Short Name: runtime-annotation-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.10.0-SNAPSHOT/runtime-annotation-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.10.0-SNAPSHOT/runtime-annotation-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
index aa34576..cf6d633b 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_retain_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Runtime Retain
 Short Name: runtime-retain-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.10.0-SNAPSHOT/runtime-retain-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.10.0-SNAPSHOT/runtime-retain-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
index e2a3f35..472670f 100644
--- a/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_runtime_runtime_saveable_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Saveable
 Short Name: runtime-saveable-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.10.0-SNAPSHOT/runtime-saveable-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.10.0-SNAPSHOT/runtime-saveable-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
index 6c5114fb..793357d 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose UI
 Short Name: ui-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-android/1.10.0-SNAPSHOT/ui-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-android/1.10.0-SNAPSHOT/ui-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
index f345649..408840bb 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_geometry_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Geometry
 Short Name: ui-geometry-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.10.0-SNAPSHOT/ui-geometry-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.10.0-SNAPSHOT/ui-geometry-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
index 7b78771..7fe42711 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_graphics_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Graphics
 Short Name: ui-graphics-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.10.0-SNAPSHOT/ui-graphics-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.10.0-SNAPSHOT/ui-graphics-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
index e5adac2..28174fbd 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing
 Short Name: ui-test-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-test-android/1.10.0-SNAPSHOT/ui-test-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-test-android/1.10.0-SNAPSHOT/ui-test-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
index 297d247..0cd65c9 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_junit4_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing for JUnit4
 Short Name: ui-test-junit4-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.10.0-SNAPSHOT/ui-test-junit4-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.10.0-SNAPSHOT/ui-test-junit4-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
index eab6256..76565ed 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_test_manifest/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Testing manifest dependency
 Short Name: ui-test-manifest
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.10.0-SNAPSHOT/ui-test-manifest-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.10.0-SNAPSHOT/ui-test-manifest-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
index 0eef630..9bee968c 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose UI Text
 Short Name: ui-text-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-text-android/1.10.0-SNAPSHOT/ui-text-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-text-android/1.10.0-SNAPSHOT/ui-text-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
index 7f36433..830dd20 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_text_google_fonts/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Google Fonts integration
 Short Name: ui-text-google-fonts
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.10.0-SNAPSHOT/ui-text-google-fonts-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.10.0-SNAPSHOT/ui-text-google-fonts-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
index 7680cc5..d4d496f 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_unit_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Unit
 Short Name: ui-unit-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-unit-android/1.10.0-SNAPSHOT/ui-unit-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-unit-android/1.10.0-SNAPSHOT/ui-unit-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium b/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
index 04a5cf1..9f21cfb 100644
--- a/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_compose_ui_ui_util_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Util
 Short Name: ui-util-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/compose/ui/ui-util-android/1.10.0-SNAPSHOT/ui-util-android-1.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/compose/ui/ui-util-android/1.10.0-SNAPSHOT/ui-util-android-1.10.0-20251008.211458-1.aar
 Version: 1.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
index d9167312..72c2fb5 100644
--- a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout/README.chromium
@@ -1,6 +1,6 @@
 Name: ConstraintLayout
 Short Name: constraintlayout
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20251008.211458-1.aar
 Version: 2.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
index c38dace..c74aebb 100644
--- a/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_constraintlayout_constraintlayout_core/README.chromium
@@ -1,6 +1,6 @@
 Name: ConstraintLayout Core
 Short Name: constraintlayout-core
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20251008.211458-1.jar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core/README.chromium b/third_party/androidx/committed/libs/androidx_core_core/README.chromium
index 0039a393..99a8907 100644
--- a/third_party/androidx/committed/libs/androidx_core_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core/README.chromium
@@ -1,6 +1,6 @@
 Name: Core
 Short Name: core
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20251008.211458-1.aar
 Version: 1.18.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
index d222d2b..91d6eb71 100644
--- a/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Core Kotlin Extensions
 Short Name: core-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20251008.211458-1.aar
 Version: 1.18.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium b/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
index 9631802..a255ae38 100644
--- a/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_core_core_viewtree/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.core:core-viewtree
 Short Name: core-viewtree
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
index 2a67cda..0ac7878b 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_credentials/README.chromium
@@ -1,6 +1,6 @@
 Name: Credentials
 Short Name: credentials
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20251008.211458-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
index 2f3069e..b865d47 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_credentials_play_services_auth/README.chromium
@@ -1,6 +1,6 @@
 Name: Credentials Play Services Auth
 Short Name: credentials-play-services-auth
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20251008.211458-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
index a0ab7a1..2eb575a1 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.credentials.registry:registry-provider
 Short Name: registry-provider
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
index cd6466d..530c381 100644
--- a/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_credentials_registry_registry_provider_play_services/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.credentials.registry:registry-provider-play-services
 Short Name: registry-provider-play-services
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium b/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
index 6eedf43..3f16e35 100644
--- a/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_cursoradapter_cursoradapter/README.chromium
@@ -1,6 +1,6 @@
 Name: Cursor Adapter
 Short Name: cursoradapter
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
index b980b38..1fe4863 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_android/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore
 Short Name: datastore-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-android/1.2.0-SNAPSHOT/datastore-android-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-android/1.2.0-SNAPSHOT/datastore-android-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
index 113e571..696fb15 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore Core
 Short Name: datastore-core-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-core-android/1.2.0-SNAPSHOT/datastore-core-android-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-core-android/1.2.0-SNAPSHOT/datastore-core-android-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
index ebb3e556..442512a5 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_core_okio_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: DataStore Core Okio
 Short Name: datastore-core-okio-jvm
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.2.0-SNAPSHOT/datastore-core-okio-jvm-1.2.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.2.0-SNAPSHOT/datastore-core-okio-jvm-1.2.0-20251008.211458-1.jar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
index 8ddb5a14..000cc743 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore
 Short Name: datastore-preferences-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-preferences-android/1.2.0-SNAPSHOT/datastore-preferences-android-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-preferences-android/1.2.0-SNAPSHOT/datastore-preferences-android-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
index 1cb6369..8ef8b4bd 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore Core
 Short Name: datastore-preferences-core-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.2.0-SNAPSHOT/datastore-preferences-core-android-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.2.0-SNAPSHOT/datastore-preferences-core-android-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
index bccbce8..eaf4dbbc 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_external_protobuf/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences External Protobuf
 Short Name: datastore-preferences-external-protobuf
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.2.0-SNAPSHOT/datastore-preferences-external-protobuf-1.2.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.2.0-SNAPSHOT/datastore-preferences-external-protobuf-1.2.0-20251008.211458-1.jar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: BSD-3-Clause
diff --git a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
index 779aa3f..79158c1 100644
--- a/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_datastore_datastore_preferences_proto/README.chromium
@@ -1,6 +1,6 @@
 Name: Preferences DataStore Proto
 Short Name: datastore-preferences-proto
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.2.0-SNAPSHOT/datastore-preferences-proto-1.2.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.2.0-SNAPSHOT/datastore-preferences-proto-1.2.0-20251008.211458-1.jar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium b/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
index 8c35e63..2c643479 100644
--- a/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_drawerlayout_drawerlayout/README.chromium
@@ -1,6 +1,6 @@
 Name: Drawer Layout
 Short Name: drawerlayout
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20251008.211458-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_emoji_emoji/README.chromium b/third_party/androidx/committed/libs/androidx_emoji_emoji/README.chromium
index bdd49597..ac55d6d 100644
--- a/third_party/androidx/committed/libs/androidx_emoji_emoji/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_emoji_emoji/README.chromium
@@ -1,6 +1,6 @@
 Name: Emoji
 Short Name: emoji
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/emoji/emoji/1.2.0-SNAPSHOT/emoji-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/emoji/emoji/1.2.0-SNAPSHOT/emoji-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0, SIL Open Font License, Version 1.1, Unicode, Inc. License
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
index a2c8072..e68978d 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment/README.chromium
@@ -1,6 +1,6 @@
 Name: fragment
 Short Name: fragment
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20251008.211458-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
index eeb64e4..83e1270 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_compose/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Compose
 Short Name: fragment-compose
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20251008.211458-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
index 080dfd8..eef422e 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Kotlin Extensions
 Short Name: fragment-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20251008.211458-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
index 09843027..270f065 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Testing Extensions
 Short Name: fragment-testing
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20251008.211458-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
index 53403331..f5377e3d 100644
--- a/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_fragment_fragment_testing_manifest/README.chromium
@@ -1,6 +1,6 @@
 Name: Fragment Testing Manifest dependency
 Short Name: fragment-testing-manifest
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20251008.211458-1.aar
 Version: 1.9.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium b/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
index 5c4dc5a7..d9aa95a 100644
--- a/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_graphics_graphics_path/README.chromium
@@ -1,6 +1,6 @@
 Name: Android Graphics Path
 Short Name: graphics-path
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_graphics_graphics_shapes_android/README.chromium b/third_party/androidx/committed/libs/androidx_graphics_graphics_shapes_android/README.chromium
index 4e0a0a5..aff0597c 100644
--- a/third_party/androidx/committed/libs/androidx_graphics_graphics_shapes_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_graphics_graphics_shapes_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Graphics Shapes
 Short Name: graphics-shapes-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/graphics/graphics-shapes-android/1.1.0-SNAPSHOT/graphics-shapes-android-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/graphics/graphics-shapes-android/1.1.0-SNAPSHOT/graphics-shapes-android-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium b/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
index 84cb1d8..9d8fa83 100644
--- a/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_interpolator_interpolator/README.chromium
@@ -1,6 +1,6 @@
 Name: Interpolators
 Short Name: interpolator
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
index a56b2d9..c48744e2 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_java8/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle-Common for Java 8
 Short Name: lifecycle-common-java8
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.10.0-SNAPSHOT/lifecycle-common-java8-2.10.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.10.0-SNAPSHOT/lifecycle-common-java8-2.10.0-20251008.211458-1.jar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
index de87ad40..c77fcfda 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_common_jvm/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle-Common
 Short Name: lifecycle-common-jvm
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.10.0-SNAPSHOT/lifecycle-common-jvm-2.10.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.10.0-SNAPSHOT/lifecycle-common-jvm-2.10.0-20251008.211458-1.jar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
index 444d678..0a351ed 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle LiveData
 Short Name: lifecycle-livedata
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.10.0-SNAPSHOT/lifecycle-livedata-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.10.0-SNAPSHOT/lifecycle-livedata-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
index eef16ef..fc5291c 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle LiveData Core
 Short Name: lifecycle-livedata-core
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.10.0-SNAPSHOT/lifecycle-livedata-core-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.10.0-SNAPSHOT/lifecycle-livedata-core-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
index 26a4ee8d..7282701 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_core_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: LiveData Core Kotlin Extensions
 Short Name: lifecycle-livedata-core-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
index bd3b37ad..54664b89 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_livedata_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: LiveData Kotlin Extensions
 Short Name: lifecycle-livedata-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-ktx-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-ktx-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
index b0f65672..3e2a98ef 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_process/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Process
 Short Name: lifecycle-process
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-process/2.10.0-SNAPSHOT/lifecycle-process-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-process/2.10.0-SNAPSHOT/lifecycle-process-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
index 70b2657..0027be6a 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Runtime
 Short Name: lifecycle-runtime-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.10.0-SNAPSHOT/lifecycle-runtime-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.10.0-SNAPSHOT/lifecycle-runtime-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
index 15e5bdc..6e9131a 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Runtime Compose
 Short Name: lifecycle-runtime-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.10.0-SNAPSHOT/lifecycle-runtime-compose-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.10.0-SNAPSHOT/lifecycle-runtime-compose-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
index 09afe7ba..2bd9ebd7 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_runtime_ktx_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Kotlin Extensions
 Short Name: lifecycle-runtime-ktx-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.10.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.10.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
index 1cdae34c..b455b3e 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_service/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle Service
 Short Name: lifecycle-service
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-service/2.10.0-SNAPSHOT/lifecycle-service-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-service/2.10.0-SNAPSHOT/lifecycle-service-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
index 0bb56fb1..6d778f57 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel
 Short Name: lifecycle-viewmodel-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
index 2d6c49d9..d43f9b1 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel Compose
 Short Name: lifecycle-viewmodel-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
index 849b8812..846894c8 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel Kotlin Extensions
 Short Name: lifecycle-viewmodel-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.10.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.10.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
index 60c619a..9a6cc99d 100644
--- a/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_lifecycle_lifecycle_viewmodel_savedstate_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Lifecycle ViewModel with SavedState
 Short Name: lifecycle-viewmodel-savedstate-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium b/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
index 7d0f1db6..2cc9dafd 100644
--- a/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_loader_loader/README.chromium
@@ -1,6 +1,6 @@
 Name: loader
 Short Name: loader
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_media_media/README.chromium b/third_party/androidx/committed/libs/androidx_media_media/README.chromium
index 1c6ce43..acfe350 100644
--- a/third_party/androidx/committed/libs/androidx_media_media/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_media_media/README.chromium
@@ -1,6 +1,6 @@
 Name: Media
 Short Name: media
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20251008.211458-1.aar
 Version: 1.8.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
index e987524..f7699eae 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_common_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Common
 Short Name: navigation-common-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
index 148d2fd..07ad84d 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Compose Navigation
 Short Name: navigation-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
index aadf2d6..50dd40d 100644
--- a/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigation_navigation_runtime_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Runtime
 Short Name: navigation-runtime-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20251008.211458-1.aar
 Version: 2.10.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
index 16d7575..98f572e 100644
--- a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Navigation Event
 Short Name: navigationevent-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/navigationevent/navigationevent-android/1.0.0-SNAPSHOT/navigationevent-android-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/navigationevent/navigationevent-android/1.0.0-SNAPSHOT/navigationevent-android-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
index e0a522e..e7fbdccb 100644
--- a/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_navigationevent_navigationevent_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: NavigationEvent Compose
 Short Name: navigationevent-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.0.0-SNAPSHOT/navigationevent-compose-android-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.0.0-SNAPSHOT/navigationevent-compose-android-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
index 2680f04e..cd7d1c1 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_common_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Common
 Short Name: paging-common-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/paging/paging-common-android/3.4.0-SNAPSHOT/paging-common-android-3.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/paging/paging-common-android/3.4.0-SNAPSHOT/paging-common-android-3.4.0-20251008.211458-1.aar
 Version: 3.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
index afa9dd26..d1ed6ca 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_common_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Common Kotlin Extensions
 Short Name: paging-common-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/paging/paging-common-ktx/3.4.0-SNAPSHOT/paging-common-ktx-3.4.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/paging/paging-common-ktx/3.4.0-SNAPSHOT/paging-common-ktx-3.4.0-20251008.211458-1.jar
 Version: 3.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
index 72f6f0e..fea8e7ba 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Compose
 Short Name: paging-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/paging/paging-compose-android/3.4.0-SNAPSHOT/paging-compose-android-3.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/paging/paging-compose-android/3.4.0-SNAPSHOT/paging-compose-android-3.4.0-20251008.211458-1.aar
 Version: 3.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium b/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
index a79487f..ff418f76a 100644
--- a/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_paging_paging_runtime/README.chromium
@@ -1,6 +1,6 @@
 Name: Paging-Runtime
 Short Name: paging-runtime
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/paging/paging-runtime/3.4.0-SNAPSHOT/paging-runtime-3.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/paging/paging-runtime/3.4.0-SNAPSHOT/paging-runtime-3.4.0-20251008.211458-1.aar
 Version: 3.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium b/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
index 4bf39410..f3d64fc 100644
--- a/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_palette_palette/README.chromium
@@ -1,6 +1,6 @@
 Name: Palette
 Short Name: palette
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20251008.211458-1.aar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
index dc0d0e6..cb4fea3f 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_document_service/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-document-service
 Short Name: pdf-document-service
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
index 56dbee32..815d102 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-viewer
 Short Name: pdf-viewer
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
index 86926de..566ed23b 100644
--- a/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_pdf_pdf_viewer_fragment/README.chromium
@@ -1,6 +1,6 @@
 Name: androidx.pdf:pdf-viewer-fragment
 Short Name: pdf-viewer-fragment
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium b/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
index f1c0a526..9ad6ce36 100644
--- a/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_preference_preference/README.chromium
@@ -1,6 +1,6 @@
 Name: Preference
 Short Name: preference
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20251008.211458-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium b/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
index 44685668..87a33df 100644
--- a/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_profileinstaller_profileinstaller/README.chromium
@@ -1,6 +1,6 @@
 Name: Profile Installer
 Short Name: profileinstaller
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium b/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
index 18dd623..f22f975 100644
--- a/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_recyclerview_recyclerview/README.chromium
@@ -1,6 +1,6 @@
 Name: RecyclerView
 Short Name: recyclerview
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20251008.211458-1.aar
 Version: 1.5.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium b/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
index 3bd95fa..250a229 100644
--- a/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_resourceinspection_resourceinspection_annotation/README.chromium
@@ -1,6 +1,6 @@
 Name: Resource Inspection - Annotations
 Short Name: resourceinspection-annotation
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20251008.132034-1.jar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20251008.211458-1.jar
 Version: 1.1.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
index 9c98b961..6849319 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Saved State
 Short Name: savedstate-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/savedstate/savedstate-android/1.4.0-SNAPSHOT/savedstate-android-1.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/savedstate/savedstate-android/1.4.0-SNAPSHOT/savedstate-android-1.4.0-20251008.211458-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
index 97019c8e..e6a8b46 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_compose_android/README.chromium
@@ -1,6 +1,6 @@
 Name: Saved State Compose
 Short Name: savedstate-compose-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.4.0-SNAPSHOT/savedstate-compose-android-1.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.4.0-SNAPSHOT/savedstate-compose-android-1.4.0-20251008.211458-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
index 56b821f..b62779b 100644
--- a/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_savedstate_savedstate_ktx/README.chromium
@@ -1,6 +1,6 @@
 Name: SavedState Kotlin Extensions
 Short Name: savedstate-ktx
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/savedstate/savedstate-ktx/1.4.0-SNAPSHOT/savedstate-ktx-1.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/savedstate/savedstate-ktx/1.4.0-SNAPSHOT/savedstate-ktx-1.4.0-20251008.211458-1.aar
 Version: 1.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium b/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
index af5800c..07d3fcf 100644
--- a/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_slidingpanelayout_slidingpanelayout/README.chromium
@@ -1,6 +1,6 @@
 Name: Sliding Pane Layout
 Short Name: slidingpanelayout
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20251008.211458-1.aar
 Version: 1.3.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_swiperefreshlayout_swiperefreshlayout/README.chromium b/third_party/androidx/committed/libs/androidx_swiperefreshlayout_swiperefreshlayout/README.chromium
index d5a545a..0a4ac0f 100644
--- a/third_party/androidx/committed/libs/androidx_swiperefreshlayout_swiperefreshlayout/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_swiperefreshlayout_swiperefreshlayout/README.chromium
@@ -1,6 +1,6 @@
 Name: Swipe Refresh Layout
 Short Name: swiperefreshlayout
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/swiperefreshlayout/swiperefreshlayout/1.2.0-SNAPSHOT/swiperefreshlayout-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/swiperefreshlayout/swiperefreshlayout/1.2.0-SNAPSHOT/swiperefreshlayout-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
index e9ff841..8f2add0 100644
--- a/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_test_uiautomator_uiautomator/README.chromium
@@ -1,6 +1,6 @@
 Name: UIAutomator
 Short Name: uiautomator
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20251008.211458-1.aar
 Version: 2.4.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_transition_transition/README.chromium b/third_party/androidx/committed/libs/androidx_transition_transition/README.chromium
index c6bbe96f..a263ce90 100644
--- a/third_party/androidx/committed/libs/androidx_transition_transition/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_transition_transition/README.chromium
@@ -1,6 +1,6 @@
 Name: Transition
 Short Name: transition
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/transition/transition/1.7.0-SNAPSHOT/transition-1.7.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/transition/transition/1.7.0-SNAPSHOT/transition-1.7.0-20251008.211458-1.aar
 Version: 1.7.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium b/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
index 7576b72..d9dd4af 100644
--- a/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_viewpager2_viewpager2/README.chromium
@@ -1,6 +1,6 @@
 Name: ViewPager2
 Short Name: viewpager2
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20251008.211458-1.aar
 Version: 1.2.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium b/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
index 65b5cd5f..168423f 100644
--- a/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_webkit_webkit/README.chromium
@@ -1,6 +1,6 @@
 Name: Webkit
 Short Name: webkit
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/webkit/webkit/1.15.0-SNAPSHOT/webkit-1.15.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/webkit/webkit/1.15.0-SNAPSHOT/webkit-1.15.0-20251008.211458-1.aar
 Version: 1.15.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium b/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
index 5d1cee4c..324dc47a 100644
--- a/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_sidecar_sidecar/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager Sidecar
 Short Name: sidecar
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20251008.211458-1.aar
 Version: 1.0.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_window/README.chromium b/third_party/androidx/committed/libs/androidx_window_window/README.chromium
index ed59070..2b610e69 100644
--- a/third_party/androidx/committed/libs/androidx_window_window/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_window/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager
 Short Name: window
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20251008.211458-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium b/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
index f5da02e7..ca4f6810 100644
--- a/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
+++ b/third_party/androidx/committed/libs/androidx_window_window_core_android/README.chromium
@@ -1,6 +1,6 @@
 Name: WindowManager Core
 Short Name: window-core-android
-URL: https://androidx.dev/snapshots/builds/14233173/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20251008.132034-1.aar
+URL: https://androidx.dev/snapshots/builds/14236064/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20251008.211458-1.aar
 Version: 1.6.0-SNAPSHOT
 Update Mechanism: Autoroll
 License: Apache-2.0
diff --git a/third_party/angle b/third_party/angle
index f9685fd..17977bb 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit f9685fdb79805ace8376705bafb024a1bd64c05a
+Subproject commit 17977bb088acae8e114bae7f1ae92326b5fe8d1d
diff --git a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
index 4b582288..ec9d788 100644
--- a/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/longhands/longhands_custom.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/memory/values_equivalent.h"
 #include "base/numerics/clamped_math.h"
 #include "third_party/blink/public/strings/grit/blink_strings.h"
 #include "third_party/blink/renderer/core/css/basic_shape_functions.h"
@@ -64,6 +65,7 @@
 #include "third_party/blink/renderer/core/layout/layout_box.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/style/computed_style.h"
+#include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/core/style/coord_box_offset_path_operation.h"
 #include "third_party/blink/renderer/core/style/geometry_box_clip_path_operation.h"
 #include "third_party/blink/renderer/core/style/grid_area.h"
@@ -1966,6 +1968,24 @@
   return ZoomAdjustedPixelValue(width, style);
 }
 
+namespace {
+
+const CSSValue* ConsumeBasicShapeAndCoordBox(CSSParserTokenStream& stream,
+                                             const CSSParserContext& context) {
+  CSSValue* shape = css_parsing_utils::ConsumeBasicShape(stream, context);
+  if (!shape) {
+    return nullptr;
+  }
+  CSSValue* coord_box = css_parsing_utils::ConsumeCoordBox(stream);
+  if (coord_box) {
+    return MakeGarbageCollected<CSSValuePair>(
+        shape, coord_box, CSSValuePair::kKeepIdenticalValues);
+  }
+  return shape;
+}
+
+}  // namespace
+
 const CSSValue* BorderShape::ParseSingleValue(
     CSSParserTokenStream& stream,
     const CSSParserContext& context,
@@ -1975,17 +1995,20 @@
     return css_parsing_utils::ConsumeIdent(stream);
   }
 
-  // TODO(nrosenthal) parse the <<geometry-box>>.
-  CSSValue* outer_shape = css_parsing_utils::ConsumeBasicShape(stream, context);
-  if (!outer_shape) {
+  const CSSValue* outer = ConsumeBasicShapeAndCoordBox(stream, context);
+  if (!outer) {
     return nullptr;
   }
 
-  CSSValue* inner_shape = css_parsing_utils::ConsumeBasicShape(stream, context);
-  return inner_shape
-             ? MakeGarbageCollected<CSSValuePair>(
-                   outer_shape, inner_shape, CSSValuePair::kDropIdenticalValues)
-             : outer_shape;
+  const CSSValue* inner = ConsumeBasicShapeAndCoordBox(stream, context);
+  if (!inner || base::ValuesEquivalent(inner, outer)) {
+    return outer;
+  }
+
+  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
+  list->Append(*outer);
+  list->Append(*inner);
+  return list;
 }
 
 const CSSValue* BorderShape::CSSValueFromComputedStyleInternal(
@@ -1997,15 +2020,25 @@
     return CSSIdentifierValue::Create(CSSValueID::kNone);
   }
   const StyleBorderShape& border_shape = *style.BorderShape();
+  CSSValueList* list = CSSValueList::CreateSpaceSeparated();
   const CSSValue* outer_shape =
       ValueForBasicShape(style, &border_shape.OuterShape());
-  if (!border_shape.HasSeparateInnerShape()) {
-    return outer_shape;
+  list->Append(*outer_shape);
+  CoordBox coord_box = border_shape.OuterCoordBox();
+  if (coord_box != CoordBox::kBorderBox) {
+    list->Append(*CSSIdentifierValue::Create(coord_box));
   }
-
-  return MakeGarbageCollected<CSSValuePair>(
-      outer_shape, ValueForBasicShape(style, &border_shape.InnerShape()),
-      CSSValuePair::kDropIdenticalValues);
+  if (!border_shape.HasSeparateInnerShape()) {
+    return list;
+  }
+  const CSSValue* inner_shape =
+      ValueForBasicShape(style, &border_shape.InnerShape());
+  list->Append(*inner_shape);
+  coord_box = border_shape.InnerCoordBox();
+  if (coord_box != CoordBox::kBorderBox) {
+    list->Append(*CSSIdentifierValue::Create(coord_box));
+  }
+  return list;
 }
 
 const CSSValue* Bottom::ParseSingleValue(
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
index aaf3b23..18195a2 100644
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
@@ -275,22 +275,58 @@
       url_value.ValueForSerialization());
 }
 
+namespace {
+
+struct BasicShapeAndCoordBox {
+  STACK_ALLOCATED();
+
+ public:
+  BasicShape* shape;
+  CoordBox coord_box;
+};
+
+BasicShapeAndCoordBox BasicShapeAndCoordBoxForValue(StyleResolverState& state,
+                                                    const CSSValue& value) {
+  BasicShape* shape = nullptr;
+  CoordBox coord_box = CoordBox::kBorderBox;
+  if (const auto* pair = DynamicTo<CSSValuePair>(value)) {
+    shape = BasicShapeForValue(state, pair->First());
+    coord_box = To<CSSIdentifierValue>(pair->Second()).ConvertTo<CoordBox>();
+  } else {
+    shape = BasicShapeForValue(state, value);
+  }
+  return {shape, coord_box};
+}
+
+}  // namespace
+
 StyleBorderShape* StyleBuilderConverter::ConvertBorderShape(
     StyleResolverState& state,
     const CSSValue& value) {
+  // Either:
+  // - none;
+  // - a single shape (meaning default coord box is border-box);
+  // - a pair of shape + coord_box;
+  // - list of either: two pairs of shape + coord_box or two shapes.
   if (value.IsIdentifierValue()) {
     CHECK_EQ(To<CSSIdentifierValue>(value).GetValueID(), CSSValueID::kNone);
     return nullptr;
   }
 
-  if (const auto* pair = DynamicTo<CSSValuePair>(value)) {
+  if (const auto* list = DynamicTo<CSSValueList>(value)) {
+    DCHECK_EQ(list->length(), 2u);
+    auto [outer_shape, outer_coord_box] =
+        BasicShapeAndCoordBoxForValue(state, list->First());
+    auto [inner_shape, inner_coord_box] =
+        BasicShapeAndCoordBoxForValue(state, list->Last());
     return MakeGarbageCollected<StyleBorderShape>(
-        *BasicShapeForValue(state, pair->First()),
-        BasicShapeForValue(state, pair->Second()));
+        *outer_shape, inner_shape, outer_coord_box, inner_coord_box);
   }
 
+  auto [outer_shape, outer_coord_box] =
+      BasicShapeAndCoordBoxForValue(state, value);
   return MakeGarbageCollected<StyleBorderShape>(
-      *BasicShapeForValue(state, value));
+      *outer_shape, outer_shape, outer_coord_box, outer_coord_box);
 }
 
 LengthBox StyleBuilderConverter::ConvertClip(StyleResolverState& state,
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 79daed3..80d39d5 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -3676,6 +3676,10 @@
   documentElement()->SetNeedsStyleRecalc(
       kLocalStyleChange,
       StyleChangeReasonForTracing::Create(style_change_reason::kFrame));
+  if (GetLayoutView() && GetFrame()->Owner() &&
+      !GetFrame()->Owner()->IsDisplayNone()) {
+    GetLayoutView()->CacheScrollDimensions();
+  }
 }
 
 bool Document::WillPrintSoon() {
diff --git a/third_party/blink/renderer/core/html/forms/html_select_element.cc b/third_party/blink/renderer/core/html/forms/html_select_element.cc
index 61c41eae..255582b 100644
--- a/third_party/blink/renderer/core/html/forms/html_select_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_select_element.cc
@@ -234,7 +234,7 @@
       uses_menu_list_ =
           FastHasAttribute(html_names::kSizeAttr) ? size_ == 1 : false;
     } else {
-      uses_menu_list_ = size_ == 1;
+      uses_menu_list_ = size_ <= 1;
     }
     return;
   }
@@ -1604,6 +1604,7 @@
   if (UsesMenuList() != old_uses_menu_list) {
     select_type_->WillBeDestroyed();
     select_type_ = SelectType::Create(*this);
+    PseudoStateChanged(CSSSelector::kPseudoListBox);
   }
   if (!InActiveDocument())
     return;
diff --git a/third_party/blink/renderer/core/html/media/html_media_test_helper.h b/third_party/blink/renderer/core/html/media/html_media_test_helper.h
index ee8086a6..74f1658 100644
--- a/third_party/blink/renderer/core/html/media/html_media_test_helper.h
+++ b/third_party/blink/renderer/core/html/media/html_media_test_helper.h
@@ -5,6 +5,7 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_HTML_MEDIA_TEST_HELPER_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_HTML_MEDIA_TEST_HELPER_H_
 
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "third_party/blink/renderer/core/loader/empty_clients.h"
 
 namespace blink {
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
index 5a2e15c5..5c0cdb3 100644
--- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -154,7 +154,6 @@
 #include "third_party/blink/renderer/platform/fonts/font.h"
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/fonts/font_custom_platform_data.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
 #include "third_party/blink/renderer/platform/geometry/layout_unit.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/clear_collection_scope.h"
diff --git a/third_party/blink/renderer/core/layout/layout_view.cc b/third_party/blink/renderer/core/layout/layout_view.cc
index 18786d2..7931113 100644
--- a/third_party/blink/renderer/core/layout/layout_view.cc
+++ b/third_party/blink/renderer/core/layout/layout_view.cc
@@ -918,6 +918,34 @@
     SetHasBoxDecorationBackground(true);
 }
 
+void LayoutView::UpdateAfterLayout() {
+  NOT_DESTROYED();
+  LayoutBlockFlow::UpdateAfterLayout();
+  if (cached_scroll_dimensions_.has_value() && GetFrame()->Owner() &&
+      !GetFrame()->Owner()->IsDisplayNone() && !GetDocument().Printing()) {
+    auto* scrollable_area = GetScrollableArea();
+    CHECK(scrollable_area);
+    // Only restore scroll offset if the scroll dimensions match
+    if (scrollable_area->ScrollWidth() == cached_scroll_dimensions_->width &&
+        scrollable_area->ScrollHeight() == cached_scroll_dimensions_->height &&
+        scrollable_area->ScrollOrigin() == cached_scroll_dimensions_->origin) {
+      scrollable_area->SetScrollOffset(cached_scroll_dimensions_->offset,
+                                       mojom::blink::ScrollType::kProgrammatic,
+                                       cc::ScrollSourceType::kAbsoluteScroll);
+    }
+    cached_scroll_dimensions_.reset();
+  }
+}
+
+void LayoutView::CacheScrollDimensions() {
+  NOT_DESTROYED();
+  auto* scrollable_area = GetScrollableArea();
+  CHECK(scrollable_area);
+  cached_scroll_dimensions_.emplace(CachedScrollDimensions{
+      scrollable_area->ScrollWidth(), scrollable_area->ScrollHeight(),
+      scrollable_area->ScrollOrigin(), scrollable_area->GetScrollOffset()});
+}
+
 void LayoutView::StyleDidChange(
     StyleDifference diff,
     const ComputedStyle* old_style,
diff --git a/third_party/blink/renderer/core/layout/layout_view.h b/third_party/blink/renderer/core/layout/layout_view.h
index 711dac9..cc8971f 100644
--- a/third_party/blink/renderer/core/layout/layout_view.h
+++ b/third_party/blink/renderer/core/layout/layout_view.h
@@ -27,6 +27,7 @@
 #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h"
 #include "third_party/blink/renderer/core/core_export.h"
 #include "third_party/blink/renderer/core/layout/layout_block_flow.h"
+#include "third_party/blink/renderer/core/scroll/scroll_types.h"
 #include "third_party/blink/renderer/core/scroll/scrollable_area.h"
 #include "third_party/blink/renderer/platform/graphics/overlay_scrollbar_clip_behavior.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
@@ -336,6 +337,8 @@
 
   LayoutViewTransitionRoot* GetViewTransitionRoot() const;
 
+  void CacheScrollDimensions();
+
  private:
   void StyleDidChange(StyleDifference,
                       const ComputedStyle* old_style,
@@ -356,6 +359,7 @@
 
   bool CanHaveChildren() const override;
   void UpdateFromStyle() override;
+  void UpdateAfterLayout() override;
 
   // The CompositeBackgroundAttachmentFixed optimization doesn't apply to
   // LayoutView which paints background specially.
@@ -403,6 +407,17 @@
   mojom::blink::ScrollbarMode autosize_h_scrollbar_mode_;
   mojom::blink::ScrollbarMode autosize_v_scrollbar_mode_;
 
+  struct CachedScrollDimensions {
+    LayoutUnit width;
+    LayoutUnit height;
+    gfx::Point origin;
+    ScrollOffset offset;
+  };
+
+  // This is set when a frame becomes display:none and reset in the first layout
+  // after exiting that state.
+  std::optional<CachedScrollDimensions> cached_scroll_dimensions_;
+
   mutable PhysicalRect previous_background_rect_;
 };
 
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc
index f22f9db..292c0fa 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -57,9 +57,8 @@
     const PhysicalRect& rect,
     const BoxBackgroundPaintContext& bg_paint_context,
     BackgroundBleedAvoidance bleed) {
-  FillLayerOcclusionOutputList reversed_paint_list;
-  bool should_draw_background_in_separate_buffer =
-      CalculateFillLayerOcclusionCulling(reversed_paint_list, fill_layer);
+  auto [should_draw_background_in_separate_buffer, last_layer] =
+      AnalyzeFillLayersForPainting(fill_layer);
 
   // TODO(trchen): We can optimize out isolation group if we have a
   // non-transparent background color and the bottom layer encloses all other
@@ -68,9 +67,12 @@
   if (should_draw_background_in_separate_buffer)
     context.BeginLayer();
 
-  for (auto* const paint : base::Reversed(reversed_paint_list)) {
-    PaintFillLayer(paint_info, c, *paint, rect, bleed, bg_paint_context);
-  }
+  FillLayer::IterateFillLayersInReverseOrder(
+      &fill_layer, last_layer,
+      [this, paint_info, c, rect, bleed,
+       bg_paint_context](const FillLayer& paint) {
+        PaintFillLayer(paint_info, c, paint, rect, bleed, bg_paint_context);
+      });
 
   if (should_draw_background_in_separate_buffer)
     context.EndLayer();
@@ -459,13 +461,11 @@
           !document.GetSettings()->GetShouldPrintBackgrounds());
 }
 
-bool BoxPainterBase::CalculateFillLayerOcclusionCulling(
-    FillLayerOcclusionOutputList& reversed_paint_list,
+std::pair<bool, const FillLayer*> BoxPainterBase::AnalyzeFillLayersForPainting(
     const FillLayer& fill_layer) {
   bool is_non_associative = false;
-  for (auto* current_layer = &fill_layer; current_layer;
-       current_layer = current_layer->Next()) {
-    reversed_paint_list.push_back(current_layer);
+  const FillLayer* current_layer = &fill_layer;
+  for (; current_layer; current_layer = current_layer->Next()) {
     // Stop traversal when an opaque layer is encountered.
     // FIXME : It would be possible for the following occlusion culling test to
     // be more aggressive on layers with no repeat by testing whether the image
@@ -488,7 +488,7 @@
       break;
     }
   }
-  return is_non_associative;
+  return {is_non_associative, current_layer};
 }
 
 BoxPainterBase::FillLayerInfo::FillLayerInfo(
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.h b/third_party/blink/renderer/core/paint/box_painter_base.h
index 9bd2debb..eddac0d6 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.h
+++ b/third_party/blink/renderer/core/paint/box_painter_base.h
@@ -100,13 +100,14 @@
   static bool ShouldForceWhiteBackgroundForPrintEconomy(const Document&,
                                                         const ComputedStyle&);
 
-  typedef Vector<const FillLayer*, 8> FillLayerOcclusionOutputList;
-  // Returns true if the result fill layers have non-associative blending or
-  // compositing mode.  (i.e. The rendering will be different without creating
-  // isolation group by context.saveLayer().) Note that the output list will be
-  // in top-bottom order.
-  bool CalculateFillLayerOcclusionCulling(
-      FillLayerOcclusionOutputList& reversed_paint_list,
+  // Analyzes the fill layers to determine painting requirements.
+  // Returns a pair containing:
+  //  - bool: True if the layers require an isolation group (a separate buffer)
+  //    due to non-associative blending modes.
+  //  - const FillLayer*: The last layer to be painted. Subsequent layers are
+  //    occluded and can be culled. This will be the last layer in the list
+  //    if no occlusion occurs.
+  std::pair<bool, const FillLayer*> AnalyzeFillLayersForPainting(
       const FillLayer&);
 
   static bool ShouldSkipPaintUnderInvalidationChecking(const LayoutBox&);
diff --git a/third_party/blink/renderer/core/paint/view_painter.cc b/third_party/blink/renderer/core/paint/view_painter.cc
index 1d33ec8..2ae24c8 100644
--- a/third_party/blink/renderer/core/paint/view_painter.cc
+++ b/third_party/blink/renderer/core/paint/view_painter.cc
@@ -374,13 +374,10 @@
 
   recorder.UniteVisualRect(paint_rect);
 
-  GC_PLUGIN_IGNORE("crbug.com/446536462")
-  BoxPainterBase::FillLayerOcclusionOutputList reversed_paint_list;
-  bool should_draw_background_in_separate_buffer =
+  const FillLayer& background_layers = style.BackgroundLayers();
+  auto [should_draw_background_in_separate_buffer, last_background_layer] =
       BoxModelObjectPainter(layout_view)
-          .CalculateFillLayerOcclusionCulling(reversed_paint_list,
-                                              style.BackgroundLayers());
-  DCHECK(reversed_paint_list.size());
+          .AnalyzeFillLayersForPainting(background_layers);
 
   if (painted_separate_effect) {
     should_draw_background_in_separate_buffer = true;
@@ -434,11 +431,14 @@
   BoxBackgroundPaintContext bg_paint_context(layout_view, &box_fragment_,
                                              background_image_offset);
   BoxModelObjectPainter box_model_painter(layout_view);
-  for (const auto* fill_layer : base::Reversed(reversed_paint_list)) {
-    box_model_painter.PaintFillLayer(paint_info, Color(), *fill_layer,
-                                     PhysicalRect(paint_rect),
-                                     kBackgroundBleedNone, bg_paint_context);
-  }
+  FillLayer::IterateFillLayersInReverseOrder(
+      &background_layers, last_background_layer,
+      [&box_model_painter, paint_info, paint_rect,
+       bg_paint_context](const FillLayer& fill_layer) {
+        box_model_painter.PaintFillLayer(
+            paint_info, Color(), fill_layer, PhysicalRect(paint_rect),
+            kBackgroundBleedNone, bg_paint_context);
+      });
 
   if (should_draw_background_in_separate_buffer && !painted_separate_effect)
     context.EndLayer();
diff --git a/third_party/blink/renderer/core/script/pending_import_map.cc b/third_party/blink/renderer/core/script/pending_import_map.cc
index 35ce13c0..a29b2e6d 100644
--- a/third_party/blink/renderer/core/script/pending_import_map.cc
+++ b/third_party/blink/renderer/core/script/pending_import_map.cc
@@ -41,12 +41,7 @@
 // href="https://html.spec.whatwg.org/C#register-an-import-map"> This is
 // parallel to PendingScript::ExecuteScriptBlock().
 void PendingImportMap::RegisterImportMap() {
-  // TODO(crbug.com/364917757): I don't think this ever happens, so we can
-  // replace this with a CHECK.
-  if (!import_map_) {
-    element_->DispatchErrorEvent();
-    return;
-  }
+  CHECK(import_map_);
 
   // TODO(crbug.com/364917757): This step is no longer in the spec, and it's not
   // clear when this can actually happen.
diff --git a/third_party/blink/renderer/core/style/fill_layer.h b/third_party/blink/renderer/core/style/fill_layer.h
index 8d0917ea..ea1a6dd 100644
--- a/third_party/blink/renderer/core/style/fill_layer.h
+++ b/third_party/blink/renderer/core/style/fill_layer.h
@@ -300,6 +300,18 @@
   }
   static StyleImage* InitialFillImage(EFillLayerType) { return nullptr; }
 
+  template <typename Callback>
+  static void IterateFillLayersInReverseOrder(const FillLayer* start,
+                                              const FillLayer* end,
+                                              Callback callback) {
+    if (start != end) {
+      IterateFillLayersInReverseOrder(start->Next(), end, callback);
+    }
+    if (start) {
+      callback(*start);
+    }
+  }
+
  private:
   friend class ComputedStyle;
 
diff --git a/third_party/blink/renderer/core/style/style_border_shape.h b/third_party/blink/renderer/core/style/style_border_shape.h
index 8934875..fc0f595 100644
--- a/third_party/blink/renderer/core/style/style_border_shape.h
+++ b/third_party/blink/renderer/core/style/style_border_shape.h
@@ -7,6 +7,7 @@
 
 #include "base/memory/values_equivalent.h"
 #include "third_party/blink/renderer/core/style/basic_shapes.h"
+#include "third_party/blink/renderer/core/style/computed_style_constants.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/heap/member.h"
 
@@ -17,8 +18,14 @@
  public:
   // A border shape always has an inner and outer shape, though in case they are
   // identical certain operations such as filling between them can be skipped.
-  explicit StyleBorderShape(BasicShape& outer, BasicShape* inner = nullptr)
-      : outer_(&outer), inner_(inner ? inner : &outer) {}
+  explicit StyleBorderShape(BasicShape& outer,
+                            BasicShape* inner = nullptr,
+                            CoordBox outer_coord_box = CoordBox::kBorderBox,
+                            CoordBox inner_coord_box = CoordBox::kBorderBox)
+      : outer_(&outer),
+        inner_(inner ? inner : &outer),
+        outer_coord_box_(outer_coord_box),
+        inner_coord_box_(inner_coord_box) {}
 
   void Trace(Visitor* visitor) const {
     visitor->Trace(outer_);
@@ -32,14 +39,21 @@
   const BasicShape& OuterShape() const { return *outer_; }
   const BasicShape& InnerShape() const { return *inner_; }
 
+  CoordBox OuterCoordBox() const { return outer_coord_box_; }
+  CoordBox InnerCoordBox() const { return inner_coord_box_; }
+
   bool operator==(const StyleBorderShape& o) const {
     return base::ValuesEquivalent(outer_, o.outer_) &&
-           base::ValuesEquivalent(inner_, o.inner_);
+           base::ValuesEquivalent(inner_, o.inner_) &&
+           outer_coord_box_ == o.outer_coord_box_ &&
+           inner_coord_box_ == o.inner_coord_box_;
   }
 
  private:
   Member<BasicShape> outer_;
   Member<BasicShape> inner_;
+  CoordBox outer_coord_box_;
+  CoordBox inner_coord_box_;
 };
 }  // namespace blink
 
diff --git a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
index 9074eb83..9dcceb3f 100644
--- a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
+++ b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent.cc
@@ -1623,6 +1623,31 @@
   HitTestResult result(request, location);
   document.GetLayoutView()->HitTest(location, result);
 
+  // TODO(averge): At this point, hit_nodes may contain duplicates due to
+  // multiple passes over the same node while hit testing. These need to
+  // be filtered out. The most correct approach is probably to keep the first
+  // occurrence of each node, because it's more likely it was added in a later
+  // paint phase, which is more representative of what the page actually looks
+  // like to the user (or actor).
+  //
+  // result.ListBasedTestResult() already returns a NodeSet with predictable
+  // iteration order based on order of insertion, which is a fancy way of saying
+  // it already handles duplicates in exactly the way we need. We should eval
+  // using the NodeSet result directly, and if we see improvement, remove
+  // hit_nodes and the associated callback entirely.
+  if (base::FeatureList::IsEnabled(
+          blink::features::kAIPageContentZOrderEarlyFiltering)) {
+    std::vector<DOMNodeId> nodes_from_result;
+    for (auto& gc_member : result.ListBasedTestResult()) {
+      Node& node = *gc_member;
+      if (node.GetLayoutObject()) {
+        nodes_from_result.push_back(DOMNodeIds::IdForNode(&node));
+      }
+    }
+
+    hit_nodes = nodes_from_result;
+  }
+
   int32_t next_z_order = 1;
   std::for_each(hit_nodes.rbegin(), hit_nodes.rend(), [&](auto node_id) {
     if (dom_node_to_z_order_.contains(node_id)) {
diff --git a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
index 6ee27953..3d17e98 100644
--- a/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
+++ b/third_party/blink/renderer/modules/content_extraction/ai_page_content_agent_unittest.cc
@@ -7,6 +7,7 @@
 #include <cstddef>
 
 #include "base/strings/stringprintf.h"
+#include "base/test/with_feature_override.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/common/frame/frame_ad_evidence.h"
@@ -3285,262 +3286,6 @@
                    mojom::blink::AIPageContentAnnotatedRole::kPaidContent));
 }
 
-TEST_F(AIPageContentAgentTest, AnchorInInlineWithFloatingSiblingHitTesting) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <span>"
-      "  <a href='https://www.google.com'>"
-      "    <div style='position: relative; float: left;'>text in div</div>"
-      "    <span>text</span>"
-      "  </a>"
-      "  </span>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  const auto& root = ContentRootNode();
-  const auto& span = *root.children_nodes.at(0);
-  const auto& anchor = *span.children_nodes.at(0);
-
-  CheckAnchorNode(anchor, blink::KURL("https://www.google.com/"), {});
-  ASSERT_TRUE(anchor.content_attributes->node_interaction_info);
-  EXPECT_TRUE(anchor.content_attributes->node_interaction_info
-                  ->document_scoped_z_order);
-}
-
-TEST_F(AIPageContentAgentTest, HitTestElementsBasic) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <p style='background:red'>Text 1</p>"
-      "  <p>Text 2</p>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  // The tree should look as follows, with the given z order.
-  // root - 1
-  // |_html - 2
-  //    |_body - 3
-  //      |_p - 4
-  //      | |_Text1 - 6
-  //      |_p - 5
-  //        |_Text2 - 7
-  const auto& root = *Content()->root_node;
-
-  ASSERT_TRUE(root.content_attributes->node_interaction_info);
-  EXPECT_EQ(
-      root.content_attributes->node_interaction_info->document_scoped_z_order,
-      1);
-
-  ASSERT_EQ(root.children_nodes.size(), 1u);
-  const auto& html = *root.children_nodes.at(0);
-  EXPECT_EQ(
-      html.content_attributes->node_interaction_info->document_scoped_z_order,
-      2);
-
-  ASSERT_EQ(html.children_nodes.size(), 1u);
-  const auto& body = *html.children_nodes.at(0);
-  EXPECT_EQ(
-      body.content_attributes->node_interaction_info->document_scoped_z_order,
-      3);
-
-  ASSERT_EQ(body.children_nodes.size(), 2u);
-  const auto& p1 = *body.children_nodes.at(0);
-  EXPECT_EQ(
-      p1.content_attributes->node_interaction_info->document_scoped_z_order, 4);
-
-  const auto& p2 = *body.children_nodes.at(1);
-  EXPECT_EQ(
-      p2.content_attributes->node_interaction_info->document_scoped_z_order, 5);
-
-  ASSERT_EQ(p1.children_nodes.size(), 1u);
-  const auto& text1 = *p1.children_nodes.at(0);
-  CheckTextNode(text1, "Text 1");
-  EXPECT_EQ(
-      text1.content_attributes->node_interaction_info->document_scoped_z_order,
-      6);
-
-  ASSERT_EQ(p2.children_nodes.size(), 1u);
-  const auto& text2 = *p2.children_nodes.at(0);
-  CheckTextNode(text2, "Text 2");
-  EXPECT_EQ(
-      text2.content_attributes->node_interaction_info->document_scoped_z_order,
-      7);
-}
-
-TEST_F(AIPageContentAgentTest, HitTestElementsFixedPos) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <p style='position: fixed; top: 10px;'>Text 1</p>"
-      "  <p>Text 2</p>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  const auto& root = ContentRootNode();
-  ASSERT_EQ(root.children_nodes.size(), 2u);
-
-  // The first node is now on top.
-  const auto& p1 = *root.children_nodes.at(0);
-  ASSERT_TRUE(p1.content_attributes->node_interaction_info);
-  ASSERT_TRUE(
-      p1.content_attributes->node_interaction_info->document_scoped_z_order);
-  EXPECT_EQ(
-      p1.content_attributes->node_interaction_info->document_scoped_z_order, 6);
-
-  const auto& p2 = *root.children_nodes.at(1);
-  ASSERT_TRUE(p2.content_attributes->node_interaction_info);
-  ASSERT_TRUE(
-      p2.content_attributes->node_interaction_info->document_scoped_z_order);
-  EXPECT_EQ(
-      p2.content_attributes->node_interaction_info->document_scoped_z_order, 4);
-}
-
-TEST_F(AIPageContentAgentTest, HitTestElementsPointerNone) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <p style='pointer-events:none'>Text 1</p>"
-      "  <p>Text 2</p>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-  const auto& root = ContentRootNode();
-  ASSERT_EQ(root.children_nodes.size(), 2u);
-
-  // The first node is not actionable anymore.
-  const auto& p1 = *root.children_nodes.at(0);
-  EXPECT_FALSE(p1.content_attributes->node_interaction_info);
-
-  const auto& p2 = *root.children_nodes.at(1);
-  ASSERT_TRUE(p2.content_attributes->node_interaction_info);
-  ASSERT_TRUE(
-      p2.content_attributes->node_interaction_info->document_scoped_z_order);
-}
-
-TEST_F(AIPageContentAgentTest, HitTestElementsOffscreen) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <p style='cursor:pointer; position:fixed; top:110vh;'>Text 1</p>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-  const auto& root = ContentRootNode();
-  ASSERT_EQ(root.children_nodes.size(), 1u);
-
-  // The first node is actionable but not in viewport
-  const auto& p1 = *root.children_nodes.at(0);
-  ASSERT_TRUE(p1.content_attributes->node_interaction_info);
-  const auto& interaction_info = *p1.content_attributes->node_interaction_info;
-  EXPECT_FALSE(interaction_info.clickability_reasons.empty());
-  EXPECT_FALSE(interaction_info.document_scoped_z_order);
-}
-
-TEST_F(AIPageContentAgentTest, HitTestElementsIframe) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      R"HTML(
-      <body>
-        <iframe srcdoc='<p>Text 1</p>'></iframe>
-        <p>Text 2</p>
-      </body>
-      )HTML",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  // The iframe and outer p have z order relative to each other.
-  GetAIPageContentWithActionableElements();
-
-  const auto& root = ContentRootNode();
-  ASSERT_EQ(root.children_nodes.size(), 2u);
-
-  const auto& iframe = *root.children_nodes.at(0);
-  ASSERT_TRUE(iframe.content_attributes->node_interaction_info);
-  ASSERT_TRUE(iframe.content_attributes->node_interaction_info
-                  ->document_scoped_z_order);
-
-  const auto& p = *root.children_nodes.at(1);
-  ASSERT_TRUE(p.content_attributes->node_interaction_info);
-  ASSERT_TRUE(
-      p.content_attributes->node_interaction_info->document_scoped_z_order);
-
-  EXPECT_GT(
-      *iframe.content_attributes->node_interaction_info
-           ->document_scoped_z_order,
-      *p.content_attributes->node_interaction_info->document_scoped_z_order);
-
-  ASSERT_EQ(iframe.children_nodes.size(), 1u);
-  const auto& doc_inside_iframe = *iframe.children_nodes.at(0);
-  ASSERT_TRUE(doc_inside_iframe.content_attributes->node_interaction_info);
-  ASSERT_TRUE(doc_inside_iframe.content_attributes->node_interaction_info
-                  ->document_scoped_z_order);
-  EXPECT_EQ(*doc_inside_iframe.content_attributes->node_interaction_info
-                 ->document_scoped_z_order,
-            1);
-}
-
-TEST_F(AIPageContentAgentTest, OverflowHiddenGeometry) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <div style='width: 100px; height: 100px; overflow-y: hidden;'>"
-      "     <article style='width: 50px; height: 300px;'></article>"
-      "   </div>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  const auto& outer = ContentRootNode().children_nodes[0];
-  const auto& article = outer->children_nodes[0];
-  CheckAnnotatedRole(*article,
-                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
-
-  EXPECT_GT(*article->content_attributes->node_interaction_info
-                 ->document_scoped_z_order,
-            *outer->content_attributes->node_interaction_info
-                 ->document_scoped_z_order);
-
-  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
-  CheckGeometry(*article, gfx::Rect(8, 8, 50, 300), gfx::Rect(8, 8, 50, 100));
-}
-
-TEST_F(AIPageContentAgentTest, OverflowVisibleGeometry) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <section style='width: 100px; height: 100px; overflow-y: visible;'>"
-      "    <article style='width: 50px; height: 300px;'></article>"
-      "  </section>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  const auto& outer = ContentRootNode().children_nodes[0];
-  const auto& article = outer->children_nodes[0];
-  CheckAnnotatedRole(*article,
-                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
-
-  EXPECT_GT(*article->content_attributes->node_interaction_info
-                 ->document_scoped_z_order,
-            *outer->content_attributes->node_interaction_info
-                 ->document_scoped_z_order);
-
-  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
-  CheckGeometry(*article, gfx::Rect(8, 8, 50, 300), gfx::Rect(8, 8, 50, 300));
-}
-
 TEST_F(AIPageContentAgentTest, BlurGeometry) {
   frame_test_helpers::LoadHTMLString(
       helper_.LocalMainFrame(),
@@ -3579,35 +3324,6 @@
                 gfx::Rect(200, 200, 100, 100));
 }
 
-TEST_F(AIPageContentAgentTest, HitTestElementsRelativePos) {
-  frame_test_helpers::LoadHTMLString(
-      helper_.LocalMainFrame(),
-      "<body>"
-      "  <section style='width: 100px; height: 100px; position: relative; "
-      "overflow: clip;'>"
-      "    <article style='width: 50px; height: 50px; position: absolute; "
-      "left: "
-      "150px; top:0px;'></article>"
-      "  </section>"
-      "</body>",
-      url_test_helpers::ToKURL("http://foobar.com"));
-
-  GetAIPageContentWithActionableElements();
-
-  const auto& outer = ContentRootNode().children_nodes[0];
-  const auto& article = outer->children_nodes[0];
-  CheckAnnotatedRole(*article,
-                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
-
-  EXPECT_GT(*article->content_attributes->node_interaction_info
-                 ->document_scoped_z_order,
-            *outer->content_attributes->node_interaction_info
-                 ->document_scoped_z_order);
-
-  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
-  CheckGeometry(*article, gfx::Rect(158, 8, 50, 50), gfx::Rect());
-}
-
 TEST_F(AIPageContentAgentTest, GeometryTransform) {
   frame_test_helpers::LoadHTMLString(
       helper_.LocalMainFrame(),
@@ -4589,5 +4305,488 @@
   CheckGeometry(div_node, gfx::Rect(), gfx::Rect());
 }
 
+// Tests hit-testing and z-order computations for AIPageContentAgent.
+class AIPageContentAgentTestZOrder : public base::test::WithFeatureOverride,
+                                     public AIPageContentAgentTest {
+ public:
+  AIPageContentAgentTestZOrder()
+      : base::test::WithFeatureOverride(
+            blink::features::kAIPageContentZOrderEarlyFiltering) {}
+  ~AIPageContentAgentTestZOrder() override = default;
+};
+
+TEST_P(AIPageContentAgentTestZOrder,
+       AnchorInInlineWithFloatingSiblingHitTesting) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <span>"
+      "  <a href='https://www.google.com'>"
+      "    <div style='position: relative; float: left;'>text in div</div>"
+      "    <span>text</span>"
+      "  </a>"
+      "  </span>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& root = ContentRootNode();
+  const auto& span = *root.children_nodes.at(0);
+  const auto& anchor = *span.children_nodes.at(0);
+
+  CheckAnchorNode(anchor, blink::KURL("https://www.google.com/"), {});
+  ASSERT_TRUE(anchor.content_attributes->node_interaction_info);
+  EXPECT_TRUE(anchor.content_attributes->node_interaction_info
+                  ->document_scoped_z_order);
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsBasic) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <p style='background:red'>Text 1</p>"
+      "  <p>Text 2</p>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& root = *Content()->root_node;
+
+  ASSERT_TRUE(root.content_attributes->node_interaction_info);
+  EXPECT_EQ(
+      root.content_attributes->node_interaction_info->document_scoped_z_order,
+      1);
+
+  ASSERT_EQ(root.children_nodes.size(), 1u);
+  const auto& html = *root.children_nodes.at(0);
+  EXPECT_EQ(
+      html.content_attributes->node_interaction_info->document_scoped_z_order,
+      2);
+
+  ASSERT_EQ(html.children_nodes.size(), 1u);
+  const auto& body = *html.children_nodes.at(0);
+  EXPECT_EQ(
+      body.content_attributes->node_interaction_info->document_scoped_z_order,
+      3);
+
+  if (IsParamFeatureEnabled()) {
+    // When relying directly on the hit test result for z order, the tree should
+    // look as follows, with the given z order. This is consistent with "tree
+    // order" depth-first traversal as defined in the CSS spec:
+    // https://www.w3.org/TR/CSS2/zindex.html
+    // root - 1
+    // |_html - 2
+    //    |_body - 3
+    //      |_p - 4
+    //      | |_Text1 - 5
+    //      |_p - 6
+    //        |_Text2 - 7
+    ASSERT_EQ(body.children_nodes.size(), 2u);
+    const auto& p1 = *body.children_nodes.at(0);
+    EXPECT_EQ(
+        p1.content_attributes->node_interaction_info->document_scoped_z_order,
+        4);
+
+    ASSERT_EQ(p1.children_nodes.size(), 1u);
+    const auto& text1 = *p1.children_nodes.at(0);
+    CheckTextNode(text1, "Text 1");
+    EXPECT_EQ(text1.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              5);
+
+    const auto& p2 = *body.children_nodes.at(1);
+    EXPECT_EQ(
+        p2.content_attributes->node_interaction_info->document_scoped_z_order,
+        6);
+
+    ASSERT_EQ(p2.children_nodes.size(), 1u);
+    const auto& text2 = *p2.children_nodes.at(0);
+    CheckTextNode(text2, "Text 2");
+    EXPECT_EQ(text2.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              7);
+  } else {
+    // The tree should look as follows, with the given z order.
+    // root - 1
+    // |_html - 2
+    //    |_body - 3
+    //      |_p - 4
+    //      | |_Text1 - 6
+    //      |_p - 5
+    //        |_Text2 - 7
+    ASSERT_EQ(body.children_nodes.size(), 2u);
+    const auto& p1 = *body.children_nodes.at(0);
+    EXPECT_EQ(
+        p1.content_attributes->node_interaction_info->document_scoped_z_order,
+        4);
+
+    const auto& p2 = *body.children_nodes.at(1);
+    EXPECT_EQ(
+        p2.content_attributes->node_interaction_info->document_scoped_z_order,
+        5);
+
+    ASSERT_EQ(p1.children_nodes.size(), 1u);
+    const auto& text1 = *p1.children_nodes.at(0);
+    CheckTextNode(text1, "Text 1");
+    EXPECT_EQ(text1.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              6);
+
+    ASSERT_EQ(p2.children_nodes.size(), 1u);
+    const auto& text2 = *p2.children_nodes.at(0);
+    CheckTextNode(text2, "Text 2");
+    EXPECT_EQ(text2.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              7);
+  }
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsFixedPos) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <p style='position: fixed; top: 10px;'>Text 1</p>"
+      "  <p>Text 2</p>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& root = ContentRootNode();
+  ASSERT_EQ(root.children_nodes.size(), 2u);
+
+  // The first node is now on top.
+  const auto& p1 = *root.children_nodes.at(0);
+  ASSERT_TRUE(p1.content_attributes->node_interaction_info);
+  ASSERT_TRUE(
+      p1.content_attributes->node_interaction_info->document_scoped_z_order);
+  EXPECT_EQ(
+      p1.content_attributes->node_interaction_info->document_scoped_z_order, 6);
+
+  const auto& p2 = *root.children_nodes.at(1);
+  ASSERT_TRUE(p2.content_attributes->node_interaction_info);
+  ASSERT_TRUE(
+      p2.content_attributes->node_interaction_info->document_scoped_z_order);
+  EXPECT_EQ(
+      p2.content_attributes->node_interaction_info->document_scoped_z_order, 4);
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsPointerNone) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <p style='pointer-events:none'>Text 1</p>"
+      "  <p>Text 2</p>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+  const auto& root = ContentRootNode();
+  ASSERT_EQ(root.children_nodes.size(), 2u);
+
+  // The first node is not actionable anymore.
+  const auto& p1 = *root.children_nodes.at(0);
+  EXPECT_FALSE(p1.content_attributes->node_interaction_info);
+
+  const auto& p2 = *root.children_nodes.at(1);
+  ASSERT_TRUE(p2.content_attributes->node_interaction_info);
+  ASSERT_TRUE(
+      p2.content_attributes->node_interaction_info->document_scoped_z_order);
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsOffscreen) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <p style='cursor:pointer; position:fixed; top:110vh;'>Text 1</p>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+  const auto& root = ContentRootNode();
+  ASSERT_EQ(root.children_nodes.size(), 1u);
+
+  // The first node is actionable but not in viewport
+  const auto& p1 = *root.children_nodes.at(0);
+  ASSERT_TRUE(p1.content_attributes->node_interaction_info);
+  const auto& interaction_info = *p1.content_attributes->node_interaction_info;
+  EXPECT_FALSE(interaction_info.clickability_reasons.empty());
+  EXPECT_FALSE(interaction_info.document_scoped_z_order);
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsIframe) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      R"HTML(
+      <body>
+        <iframe srcdoc='<p>Text 1</p>'></iframe>
+        <p>Text 2</p>
+      </body>
+      )HTML",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  // The iframe and outer p have z order relative to each other.
+  GetAIPageContentWithActionableElements();
+
+  const auto& root = ContentRootNode();
+  ASSERT_EQ(root.children_nodes.size(), 2u);
+
+  const auto& iframe = *root.children_nodes.at(0);
+  ASSERT_TRUE(iframe.content_attributes->node_interaction_info);
+  ASSERT_TRUE(iframe.content_attributes->node_interaction_info
+                  ->document_scoped_z_order);
+
+  const auto& p = *root.children_nodes.at(1);
+  ASSERT_TRUE(p.content_attributes->node_interaction_info);
+  ASSERT_TRUE(
+      p.content_attributes->node_interaction_info->document_scoped_z_order);
+
+  if (IsParamFeatureEnabled()) {
+    // If we're respecting tree-order traversal when computing z-order, the
+    // iframe will have a lower z-order because it is the first child.
+    EXPECT_LT(
+        *iframe.content_attributes->node_interaction_info
+             ->document_scoped_z_order,
+        *p.content_attributes->node_interaction_info->document_scoped_z_order);
+  } else {
+    EXPECT_GT(
+        *iframe.content_attributes->node_interaction_info
+             ->document_scoped_z_order,
+        *p.content_attributes->node_interaction_info->document_scoped_z_order);
+  }
+
+  ASSERT_EQ(iframe.children_nodes.size(), 1u);
+  const auto& doc_inside_iframe = *iframe.children_nodes.at(0);
+  ASSERT_TRUE(doc_inside_iframe.content_attributes->node_interaction_info);
+  ASSERT_TRUE(doc_inside_iframe.content_attributes->node_interaction_info
+                  ->document_scoped_z_order);
+  EXPECT_EQ(*doc_inside_iframe.content_attributes->node_interaction_info
+                 ->document_scoped_z_order,
+            1);
+}
+
+TEST_P(AIPageContentAgentTestZOrder, OverflowHiddenGeometry) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <div style='width: 100px; height: 100px; overflow-y: hidden;'>"
+      "     <article style='width: 50px; height: 300px;'></article>"
+      "   </div>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& outer = ContentRootNode().children_nodes[0];
+  const auto& article = outer->children_nodes[0];
+  CheckAnnotatedRole(*article,
+                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
+
+  EXPECT_GT(*article->content_attributes->node_interaction_info
+                 ->document_scoped_z_order,
+            *outer->content_attributes->node_interaction_info
+                 ->document_scoped_z_order);
+
+  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
+  CheckGeometry(*article, gfx::Rect(8, 8, 50, 300), gfx::Rect(8, 8, 50, 100));
+}
+
+TEST_P(AIPageContentAgentTestZOrder, OverflowVisibleGeometry) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <section style='width: 100px; height: 100px; overflow-y: visible;'>"
+      "    <article style='width: 50px; height: 300px;'></article>"
+      "  </section>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& outer = ContentRootNode().children_nodes[0];
+  const auto& article = outer->children_nodes[0];
+  CheckAnnotatedRole(*article,
+                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
+
+  EXPECT_GT(*article->content_attributes->node_interaction_info
+                 ->document_scoped_z_order,
+            *outer->content_attributes->node_interaction_info
+                 ->document_scoped_z_order);
+
+  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
+  CheckGeometry(*article, gfx::Rect(8, 8, 50, 300), gfx::Rect(8, 8, 50, 300));
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsRelativePos) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      "<body>"
+      "  <section style='width: 100px; height: 100px; position: relative; "
+      "overflow: clip;'>"
+      "    <article style='width: 50px; height: 50px; position: absolute; "
+      "left: "
+      "150px; top:0px;'></article>"
+      "  </section>"
+      "</body>",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& outer = ContentRootNode().children_nodes[0];
+  const auto& article = outer->children_nodes[0];
+  CheckAnnotatedRole(*article,
+                     mojom::blink::AIPageContentAnnotatedRole::kArticle);
+
+  EXPECT_GT(*article->content_attributes->node_interaction_info
+                 ->document_scoped_z_order,
+            *outer->content_attributes->node_interaction_info
+                 ->document_scoped_z_order);
+
+  CheckGeometry(*outer, gfx::Rect(8, 8, 100, 100), gfx::Rect(8, 8, 100, 100));
+  CheckGeometry(*article, gfx::Rect(158, 8, 50, 50), gfx::Rect());
+}
+
+TEST_P(AIPageContentAgentTestZOrder, HitTestElementsAnchorWithSpanParent) {
+  frame_test_helpers::LoadHTMLString(
+      helper_.LocalMainFrame(),
+      R"HTML(
+      <body>
+        <span id="target-span">
+          <a id="link" href="https://example.com">
+            <span id="inner-span">
+              This is the inner span.
+             </span>
+            <div id="inner-div">
+              This is the inner div.
+            </div>
+          </a>
+        </span>
+      </body>
+      )HTML",
+      url_test_helpers::ToKURL("http://foobar.com"));
+
+  GetAIPageContentWithActionableElements();
+
+  const auto& root = *Content()->root_node;
+  EXPECT_EQ(
+      root.content_attributes->node_interaction_info->document_scoped_z_order,
+      1);
+  ASSERT_EQ(root.children_nodes.size(), 1u);
+
+  const auto& html = *root.children_nodes.at(0);
+  EXPECT_EQ(
+      html.content_attributes->node_interaction_info->document_scoped_z_order,
+      2);
+  ASSERT_EQ(html.children_nodes.size(), 1u);
+
+  const auto& body = *html.children_nodes.at(0);
+  EXPECT_EQ(
+      body.content_attributes->node_interaction_info->document_scoped_z_order,
+      3);
+  ASSERT_EQ(body.children_nodes.size(), 1u);
+
+  if (IsParamFeatureEnabled()) {
+    // When filtering for duplicate hit test nodes early, the resulting z-order
+    // will follow "tree order", which is depth-first. The resulting tree with
+    // corresponding z-order will be:
+    // root - 1
+    // |_html - 2
+    //    |_body - 3
+    //      |_span - 4
+    //        |_a - 5
+    //          |_span - 6
+    //          | |_text - 7
+    //          |_div - 8
+    //            |_text - 9
+
+    const auto& target_span = *body.children_nodes.at(0);
+    EXPECT_EQ(target_span.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              4);
+    ASSERT_EQ(target_span.children_nodes.size(), 1u);
+
+    const auto& anchor = *target_span.children_nodes.at(0);
+    EXPECT_EQ(anchor.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              5);
+    ASSERT_EQ(anchor.children_nodes.size(), 2u);
+
+    const auto& inner_span = *anchor.children_nodes.at(0);
+    EXPECT_EQ(inner_span.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              6);
+    ASSERT_EQ(inner_span.children_nodes.size(), 1u);
+
+    const auto& span_text = *inner_span.children_nodes.at(0);
+    EXPECT_EQ(span_text.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              7);
+
+    const auto& inner_div = *anchor.children_nodes.at(1);
+    EXPECT_EQ(inner_div.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              8);
+    ASSERT_EQ(inner_div.children_nodes.size(), 1u);
+
+    const auto& div_text = *inner_div.children_nodes.at(0);
+    EXPECT_EQ(div_text.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              9);
+  } else {
+    // When we don't filter for duplicate hit test nodes early, the span
+    // containers will be included multiple times, causing tree order to be
+    // violated. The resulting tree with corresponding z-order will be:
+    // root - 1
+    // |_html - 2
+    //    |_body - 3
+    //      |_span - 6
+    //        |_a - 4
+    //          |_span - 7
+    //          | |_text - 8
+    //          |_div - 5
+    //            |_text - 9
+
+    const auto& target_span = *body.children_nodes.at(0);
+    EXPECT_EQ(target_span.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              6);
+    ASSERT_EQ(target_span.children_nodes.size(), 1u);
+
+    const auto& anchor = *target_span.children_nodes.at(0);
+    EXPECT_EQ(anchor.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              4);
+    ASSERT_EQ(anchor.children_nodes.size(), 2u);
+
+    const auto& inner_span = *anchor.children_nodes.at(0);
+    EXPECT_EQ(inner_span.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              7);
+    ASSERT_EQ(inner_span.children_nodes.size(), 1u);
+
+    const auto& span_text = *inner_span.children_nodes.at(0);
+    EXPECT_EQ(span_text.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              8);
+
+    const auto& inner_div = *anchor.children_nodes.at(1);
+    EXPECT_EQ(inner_div.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              5);
+    ASSERT_EQ(inner_div.children_nodes.size(), 1u);
+
+    const auto& div_text = *inner_div.children_nodes.at(0);
+    EXPECT_EQ(div_text.content_attributes->node_interaction_info
+                  ->document_scoped_z_order,
+              9);
+  }
+}
+
+INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(AIPageContentAgentTestZOrder);
+
 }  // namespace
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.cc b/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.cc
index 6a62f3eb2..ebba9d6 100644
--- a/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.cc
+++ b/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.cc
@@ -61,21 +61,6 @@
   }
 }
 
-void ObserveDocument(WeakMember<Node>& observing,
-                     MutationObserver* observer,
-                     Element* document_element) {
-  if (observing.Get() == document_element) {
-    return;
-  }
-  observer->disconnect();
-  MutationObserverInit* init = MutationObserverInit::Create();
-  init->setChildList(true);
-  DummyExceptionStateForTesting exception_state;
-  observer->observe(document_element, init, exception_state);
-  DCHECK(!exception_state.HadException());
-  observing = document_element;
-}
-
 template <typename ObserverSet, typename MutationObserver>
 bool UpdateObserver(Document* document,
                     ObserverSet& observer_set,
@@ -107,69 +92,7 @@
   Member<FrameMetadataObserverRegistry> registry_;
 };
 
-class FrameMetadataObserverRegistry::PaidContentMutationObserver final
-    : public MutationObserver::Delegate {
- public:
-  explicit PaidContentMutationObserver(FrameMetadataObserverRegistry* registry);
 
-  void ObserveHead(HTMLHeadElement* head);
-  void ObserveDocument(Element* document_element);
-
-  void Disconnect() {
-    observer_->disconnect();
-    observing_ = nullptr;
-    registry_->DisconnectAllPaidContentAttributeObservers();
-  }
-
-  ExecutionContext* GetExecutionContext() const override {
-    return registry_->GetSupplementable()->GetExecutionContext();
-  }
-
-  void Deliver(const HeapVector<Member<MutationRecord>>& records,
-               MutationObserver&) override {
-    bool needs_update = false;
-    for (const auto& record : records) {
-      if (record->type() == "childList") {
-        for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
-          if (IsA<HTMLHeadElement>(record->addedNodes()->item(i))) {
-            registry_->OnPaidContentMetadataChanged();
-            return;
-          }
-        }
-        for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
-          if (auto* script =
-                  DynamicTo<HTMLScriptElement>(record->addedNodes()->item(i))) {
-            registry_->ObservePaidContentScriptAttributes(script);
-            needs_update = true;
-          }
-        }
-        for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
-          if (auto* script = DynamicTo<HTMLScriptElement>(
-                  record->removedNodes()->item(i))) {
-            registry_->StopObservingPaidContentScriptAttributes(script);
-            needs_update = true;
-          }
-        }
-      }
-    }
-
-    if (needs_update) {
-      registry_->OnPaidContentMetadataChanged();
-    }
-  }
-
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(registry_);
-    visitor->Trace(observer_);
-    visitor->Trace(observing_);
-    MutationObserver::Delegate::Trace(visitor);
-  }
-
- private:
-  Member<FrameMetadataObserverRegistry> registry_;
-  Member<MutationObserver> observer_;
-  WeakMember<Node> observing_;
-};
 
 class FrameMetadataObserverRegistry::MetaTagAttributeObserver final
     : public MutationObserver::Delegate {
@@ -193,157 +116,14 @@
  private:
   Member<FrameMetadataObserverRegistry> registry_;
 };
-
-// TODO(gklassen): Use templated class to avoid duplication between this and
-// PaidContentMutationObserver.
-class FrameMetadataObserverRegistry::MetaTagsMutationObserver final
-    : public MutationObserver::Delegate {
- public:
-  explicit MetaTagsMutationObserver(FrameMetadataObserverRegistry* registry);
-
-  void ObserveHead(HTMLHeadElement* head);
-  void ObserveDocument(Element* document_element);
-
-  void Disconnect() {
-    observer_->disconnect();
-    observing_ = nullptr;
-    registry_->DisconnectAllAttributeObservers();
-  }
-
-  ExecutionContext* GetExecutionContext() const override {
-    return registry_->GetSupplementable()->GetExecutionContext();
-  }
-
-  void Deliver(const HeapVector<Member<MutationRecord>>& records,
-               MutationObserver&) override {
-    bool needs_update = false;
-    for (const auto& record : records) {
-      if (record->type() == "childList") {
-        // This handles the case where the <head> element itself is added to the
-        // doc.
-        for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
-          if (IsA<HTMLHeadElement>(record->addedNodes()->item(i))) {
-            registry_->OnMetaTagsChanged();
-            return;
-          }
-        }
-
-        // This handles meta tags added/removed inside the head.
-        for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
-          if (auto* meta =
-                  DynamicTo<HTMLMetaElement>(record->addedNodes()->item(i))) {
-            registry_->ObserveMetaTagAttributes(meta);
-            needs_update = true;
-          }
-        }
-        for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
-          if (auto* meta =
-                  DynamicTo<HTMLMetaElement>(record->removedNodes()->item(i))) {
-            registry_->StopObservingMetaTagAttributes(meta);
-            needs_update = true;
-          }
-        }
-      }
-    }
-
-    if (needs_update) {
-      registry_->OnMetaTagsChanged();
-    }
-  }
-
-  void Trace(Visitor* visitor) const override {
-    visitor->Trace(registry_);
-    visitor->Trace(observer_);
-    visitor->Trace(observing_);
-    MutationObserver::Delegate::Trace(visitor);
-  }
-
- private:
-  Member<FrameMetadataObserverRegistry> registry_;
-  Member<MutationObserver> observer_;
-  WeakMember<Node> observing_;
-};
-
 FrameMetadataObserverRegistry::PaidContentAttributeObserver::
     PaidContentAttributeObserver(FrameMetadataObserverRegistry* registry)
     : registry_(registry) {}
 
-FrameMetadataObserverRegistry::PaidContentMutationObserver::
-    PaidContentMutationObserver(FrameMetadataObserverRegistry* registry)
-    : registry_(registry), observer_(MutationObserver::Create(this)) {}
-
-void FrameMetadataObserverRegistry::PaidContentMutationObserver::ObserveHead(
-    HTMLHeadElement* head) {
-  if (observing_.Get() == head) {
-    return;
-  }
-  Disconnect();
-
-  observing_ = head;
-  if (!head) {
-    return;
-  }
-
-  // Start observing childList changes in the head.
-  MutationObserverInit* init = MutationObserverInit::Create();
-  init->setChildList(true);
-  init->setSubtree(true);
-  DummyExceptionStateForTesting exception_state;
-  observer_->observe(head, init, exception_state);
-  DCHECK(!exception_state.HadException());
-
-  // For all existing script tags, set up attribute observers.
-  for (HTMLScriptElement& script :
-       Traversal<HTMLScriptElement>::ChildrenOf(*head)) {
-    registry_->ObservePaidContentScriptAttributes(&script);
-  }
-}
-
-void FrameMetadataObserverRegistry::PaidContentMutationObserver::
-    ObserveDocument(Element* document_element) {
-  ::blink::ObserveDocument(observing_, observer_.Get(), document_element);
-}
-
-FrameMetadataObserverRegistry::MetaTagsMutationObserver::
-    MetaTagsMutationObserver(FrameMetadataObserverRegistry* registry)
-    : registry_(registry),
-      observer_(MutationObserver::Create(this)) {}  // NO LINT
-
 FrameMetadataObserverRegistry::MetaTagAttributeObserver::
     MetaTagAttributeObserver(FrameMetadataObserverRegistry* registry)
     : registry_(registry) {}
 
-void FrameMetadataObserverRegistry::MetaTagsMutationObserver::ObserveHead(
-    HTMLHeadElement* head) {
-  if (observing_.Get() == head) {
-    return;
-  }
-  Disconnect();
-
-  observing_ = head;
-  if (!head) {
-    return;
-  }
-
-  // Start observing childList changes in the head.
-  MutationObserverInit* init = MutationObserverInit::Create();
-  init->setChildList(true);
-  init->setSubtree(true);
-  DummyExceptionStateForTesting exception_state;
-  observer_->observe(head, init, exception_state);
-  DCHECK(!exception_state.HadException());
-
-  // For all existing meta tags, set up attribute observers.
-  for (HTMLMetaElement& meta : Traversal<HTMLMetaElement>::ChildrenOf(*head)) {
-    registry_->ObserveMetaTagAttributes(&meta);
-  }
-}
-
-void FrameMetadataObserverRegistry::MetaTagsMutationObserver::ObserveDocument(
-    Element* document_element) {
-  ::blink::ObserveDocument(observing_, observer_.Get(), document_element);
-}
-
 // static
 const char FrameMetadataObserverRegistry::kSupplementName[] =
     "FrameMetadataObserverRegistry";
@@ -379,9 +159,12 @@
       paid_content_metadata_observers_(frame.DomWindow()),
       metatags_observers_(frame.DomWindow()),
       meta_tags_mutation_observer_(
-          MakeGarbageCollected<MetaTagsMutationObserver>(this)),
+          MakeGarbageCollected<FrameMetadataMutationObserver<
+              FrameMetadataObserverRegistry::MetaTagsObserverTraits>>(this)),
       paid_content_mutation_observer_(
-          MakeGarbageCollected<PaidContentMutationObserver>(this)) {
+          MakeGarbageCollected<FrameMetadataMutationObserver<
+              FrameMetadataObserverRegistry::PaidContentObserverTraits>>(
+              this)) {
   // Observer endpoints are explicitly closed when the other side is no
   // longer interested, so clean up the meta tags requested by that
   // observer at disconnect time.
diff --git a/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.h b/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.h
index 683dc1d..e6e169e5 100644
--- a/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.h
+++ b/third_party/blink/renderer/modules/content_extraction/frame_metadata_observer_registry.h
@@ -18,14 +18,19 @@
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver_set.h"
 #include "third_party/blink/renderer/platform/mojo/heap_mojo_remote_set.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_mutation_observer_init.h"
+#include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/core/dom/mutation_observer.h"
+#include "third_party/blink/renderer/core/dom/mutation_record.h"
+#include "third_party/blink/renderer/core/html/html_head_element.h"
+#include "third_party/blink/renderer/core/html/html_meta_element.h"
+#include "third_party/blink/renderer/core/html/html_script_element.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "third_party/blink/renderer/platform/supplementable.h"
 
 namespace blink {
 
-class HTMLMetaElement;
-class HTMLScriptElement;
 class LocalFrame;
-class MutationObserver;
 
 // Registry used to Add Observers for when frame metadata changes.
 class MODULES_EXPORT FrameMetadataObserverRegistry final
@@ -59,13 +64,161 @@
       mojo::PendingRemote<mojom::blink::MetaTagsObserver> observer) override;
 
  private:
+  struct MetaTagsObserverTraits;
+  struct PaidContentObserverTraits;
+  template <typename Traits>
+  class FrameMetadataMutationObserver;
+
   class DomContentLoadedListener;
   class MetaTagAttributeObserver;
-  class MetaTagsMutationObserver;
   class PaidContentAttributeObserver;
-  class PaidContentMutationObserver;
   friend class DomContentLoadedListener;
 
+  struct MetaTagsObserverTraits {
+    using ElementType = HTMLMetaElement;
+    static void OnChanged(FrameMetadataObserverRegistry* registry) {
+      registry->OnMetaTagsChanged();
+    }
+    static void ObserveAttributes(FrameMetadataObserverRegistry* registry,
+                                  ElementType* element) {
+      registry->ObserveMetaTagAttributes(element);
+    }
+    static void StopObservingAttributes(FrameMetadataObserverRegistry* registry,
+                                        ElementType* element) {
+      registry->StopObservingMetaTagAttributes(element);
+    }
+    static void DisconnectAllAttributeObservers(
+        FrameMetadataObserverRegistry* registry) {
+      registry->DisconnectAllAttributeObservers();
+    }
+  };
+
+  struct PaidContentObserverTraits {
+    using ElementType = HTMLScriptElement;
+    static void OnChanged(FrameMetadataObserverRegistry* registry) {
+      registry->OnPaidContentMetadataChanged();
+    }
+    static void ObserveAttributes(FrameMetadataObserverRegistry* registry,
+                                  ElementType* element) {
+      registry->ObservePaidContentScriptAttributes(element);
+    }
+    static void StopObservingAttributes(FrameMetadataObserverRegistry* registry,
+                                        ElementType* element) {
+      registry->StopObservingPaidContentScriptAttributes(element);
+    }
+    static void DisconnectAllAttributeObservers(
+        FrameMetadataObserverRegistry* registry) {
+      registry->DisconnectAllPaidContentAttributeObservers();
+    }
+  };
+
+  template <typename Traits>
+  class FrameMetadataMutationObserver final
+      : public MutationObserver::Delegate {
+   public:
+    explicit FrameMetadataMutationObserver(
+        FrameMetadataObserverRegistry* registry)
+        : registry_(registry), observer_(MutationObserver::Create(this)) {}
+
+    void ObserveHead(HTMLHeadElement* head) {
+      if (observing_.Get() == head) {
+        return;
+      }
+      Disconnect();
+
+      observing_ = head;
+      if (!head) {
+        return;
+      }
+
+      // Start observing childList changes in the head.
+      MutationObserverInit* init = MutationObserverInit::Create();
+      init->setChildList(true);
+      init->setSubtree(true);
+      DummyExceptionStateForTesting exception_state;
+      observer_->observe(head, init, exception_state);
+      DCHECK(!exception_state.HadException());
+
+      // For all existing elements, set up attribute observers.
+      for (typename Traits::ElementType& element :
+           Traversal<typename Traits::ElementType>::ChildrenOf(*head)) {
+        Traits::ObserveAttributes(registry_, &element);
+      }
+    }
+
+    void ObserveDocument(Element* document_element) {
+      if (observing_.Get() == document_element) {
+        return;
+      }
+      observer_->disconnect();
+      MutationObserverInit* init = MutationObserverInit::Create();
+      init->setChildList(true);
+      DummyExceptionStateForTesting exception_state;
+      observer_->observe(document_element, init, exception_state);
+      DCHECK(!exception_state.HadException());
+      observing_ = document_element;
+    }
+
+    void Disconnect() {
+      observer_->disconnect();
+      observing_ = nullptr;
+      Traits::DisconnectAllAttributeObservers(registry_);
+    }
+
+    ExecutionContext* GetExecutionContext() const override {
+      return registry_->GetSupplementable()->GetExecutionContext();
+    }
+
+    void Deliver(const HeapVector<Member<MutationRecord>>& records,
+                 MutationObserver&) override {
+      bool needs_update = false;
+      for (const auto& record : records) {
+        if (record->type() == "childList") {
+          // This handles the case where the <head> element itself is added to
+          // the doc.
+          for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
+            if (IsA<HTMLHeadElement>(record->addedNodes()->item(i))) {
+              Traits::OnChanged(registry_);
+              return;
+            }
+          }
+
+          // This handles meta tags added/removed inside the head.
+          for (unsigned i = 0; i < record->addedNodes()->length(); ++i) {
+            if (auto* element = DynamicTo<typename Traits::ElementType>(
+                    record->addedNodes()->item(i))) {
+              Traits::ObserveAttributes(registry_, element);
+              needs_update = true;
+            }
+          }
+          for (unsigned i = 0; i < record->removedNodes()->length(); ++i) {
+            if (auto* element = DynamicTo<typename Traits::ElementType>(
+                    record->removedNodes()->item(i))) {
+              Traits::StopObservingAttributes(registry_, element);
+              needs_update = true;
+            }
+          }
+        }
+      }
+
+      if (needs_update) {
+        Traits::OnChanged(registry_);
+      }
+    }
+
+    void Trace(Visitor* visitor) const override {
+      visitor->Trace(registry_);
+      visitor->Trace(observer_);
+      visitor->Trace(observing_);
+      MutationObserver::Delegate::Trace(visitor);
+    }
+
+   private:
+    Member<FrameMetadataObserverRegistry> registry_;
+    Member<MutationObserver> observer_;
+    WeakMember<Node> observing_;
+  };
+
   void Bind(mojo::PendingReceiver<mojom::blink::FrameMetadataObserverRegistry>
                 receiver);
 
@@ -115,8 +268,10 @@
 
   Member<DomContentLoadedListener> dom_content_loaded_observer_;
 
-  Member<MetaTagsMutationObserver> meta_tags_mutation_observer_;
-  Member<PaidContentMutationObserver> paid_content_mutation_observer_;
+  Member<FrameMetadataMutationObserver<MetaTagsObserverTraits>>
+      meta_tags_mutation_observer_;
+  Member<FrameMetadataMutationObserver<PaidContentObserverTraits>>
+      paid_content_mutation_observer_;
 
   HeapHashMap<WeakMember<HTMLMetaElement>, Member<MutationObserver>>
       meta_tag_attribute_observers_;
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
index c0a30d4..b01f6985 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_builder.cc
@@ -2792,6 +2792,15 @@
           ending_padding, BlinkPaddingModeToComponent(options->mode().AsEnum()),
           label));
 
+  // Pad becomes a no-op if input is a scalar and the paddings are all empty.
+  if (input->Rank() == 0) {
+    return BuildElementWiseUnaryOperator(
+        ml_context_->GetProperties(), this, exception_state,
+        blink_mojom::ElementWiseUnary::Kind::kIdentity,
+        ml_context_->GetProperties().data_type_limits.identity_input, input,
+        options);
+  }
+
   base::expected<webnn::MLNumber, String> pad_value =
       ToMLNumberAsType(*options->value(), input->DataType());
   if (!pad_value.has_value()) {
@@ -3152,6 +3161,16 @@
       webnn::ValidateSliceAndInferOutput(ml_context_->GetProperties(),
                                          input->Descriptor(), attributes));
 
+  // Slice becomes a no-op if the input is a scalar and starts, sizes, strides
+  // are all empty.
+  if (input->Rank() == 0) {
+    return BuildElementWiseUnaryOperator(
+        ml_context_->GetProperties(), this, exception_state,
+        blink_mojom::ElementWiseUnary::Kind::kIdentity,
+        ml_context_->GetProperties().data_type_limits.identity_input, input,
+        options);
+  }
+
   auto* slice = MakeGarbageCollected<MLSliceOperator>(this, starts, sizes,
                                                       strides, options);
   MLOperand* output =
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
index 5ff9371..c2b1f87b 100644
--- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
+++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
@@ -354,20 +354,14 @@
 
 class WebNNContextHelper {
  public:
-  WebNNContextHelper() = default;
-  ~WebNNContextHelper() = default;
+  WebNNContextHelper();
+  ~WebNNContextHelper();
 
   void ConnectWebNNTensorImpl(const blink::WebNNTensorToken& handle,
-                              std::unique_ptr<FakeWebNNTensor> tensor) {
-    const auto it = tensor_impls_.find(handle);
-    ASSERT_TRUE(it == tensor_impls_.end());
-    tensor_impls_.try_emplace(handle, std::move(tensor));
-  }
+                              std::unique_ptr<FakeWebNNTensor> tensor);
 
   void DisconnectAndDestroyWebNNTensorImpl(
-      const blink::WebNNTensorToken& handle) {
-    tensor_impls_.erase(handle);
-  }
+      const blink::WebNNTensorToken& handle);
 
  private:
   std::map<blink::WebNNTensorToken, std::unique_ptr<FakeWebNNTensor>>
@@ -450,6 +444,22 @@
   mojo_base::BigBuffer buffer_;
 };
 
+WebNNContextHelper::WebNNContextHelper() = default;
+WebNNContextHelper::~WebNNContextHelper() = default;
+
+void WebNNContextHelper::ConnectWebNNTensorImpl(
+    const blink::WebNNTensorToken& handle,
+    std::unique_ptr<FakeWebNNTensor> tensor) {
+  const auto it = tensor_impls_.find(handle);
+  ASSERT_TRUE(it == tensor_impls_.end());
+  tensor_impls_.try_emplace(handle, std::move(tensor));
+}
+
+void WebNNContextHelper::DisconnectAndDestroyWebNNTensorImpl(
+    const blink::WebNNTensorToken& handle) {
+  tensor_impls_.erase(handle);
+}
+
 class FakeWebNNGraphBuilder : public blink_mojom::WebNNGraphBuilder {
  public:
   explicit FakeWebNNGraphBuilder(MLGraphTest& helper) : helper_(helper) {}
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 9efd4e34..bcdcce2 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -757,8 +757,6 @@
     "fonts/segmented_font_data.h",
     "fonts/shaping/caching_word_shape_iterator.cc",
     "fonts/shaping/caching_word_shape_iterator.h",
-    "fonts/shaping/caching_word_shaper.cc",
-    "fonts/shaping/caching_word_shaper.h",
     "fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc",
     "fonts/shaping/case_mapping_harfbuzz_buffer_filler.h",
     "fonts/shaping/font_features.cc",
diff --git a/third_party/blink/renderer/platform/fonts/font.cc b/third_party/blink/renderer/platform/fonts/font.cc
index 99e0db40..7341702 100644
--- a/third_party/blink/renderer/platform/fonts/font.cc
+++ b/third_party/blink/renderer/platform/fonts/font.cc
@@ -29,7 +29,7 @@
 #include "third_party/blink/renderer/platform/fonts/font_cache.h"
 #include "third_party/blink/renderer/platform/fonts/font_fallback_list.h"
 #include "third_party/blink/renderer/platform/fonts/font_fallback_map.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_spacing.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
@@ -264,7 +264,9 @@
   if (mark.empty())
     return GlyphData();
   if (!RuntimeEnabledFeatures::EmphasisMarkShapeCacheEnabled()) {
-    return CachingWordShaper(*this).EmphasisMarkGlyphData(TextRun(mark));
+    return CachingWordShapeIterator::ShapeWordWithoutSpacing(TextRun(mark),
+                                                             this)
+        ->EmphasisMarkGlyphData(font_description_);
   }
   return EnsureFontFallbackList()
       ->GetOrCreateEmphasisMarkShape(*this, mark)
diff --git a/third_party/blink/renderer/platform/fonts/plain_text_node.cc b/third_party/blink/renderer/platform/fonts/plain_text_node.cc
index 918b112..e8a24ed 100644
--- a/third_party/blink/renderer/platform/fonts/plain_text_node.cc
+++ b/third_party/blink/renderer/platform/fonts/plain_text_node.cc
@@ -6,7 +6,6 @@
 
 #include "third_party/blink/renderer/platform/fonts/character_range.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/frame_shape_cache.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
@@ -81,6 +80,76 @@
   return {text.ToString(), maybe_bidi};
 }
 
+template <bool split_by_zws>
+bool IsWordDelimiter(UChar ch) {
+  // As of 2025 March, Google Docs always wraps text with BiDi control
+  // characters, and they are replaced with ZWS for HarfBuzzShaper.
+  // Assuming ZWS as a word delimiter improves hit rate of a shape cache.
+  return ch == uchar::kSpace || ch == uchar::kTab ||
+         (split_by_zws && ch == uchar::kZeroWidthSpace);
+}
+
+unsigned NextWordEndIndex(StringView text, unsigned start_index) {
+  const unsigned length = text.length();
+  if (start_index >= length) {
+    return 0;
+  }
+
+  if (start_index + 1u == length || IsWordDelimiter<true>(text[start_index])) {
+    return start_index + 1;
+  }
+
+  // 8Bit words end at IsWordDelimiter().
+  if (text.Is8Bit()) {
+    for (unsigned i = start_index + 1;; ++i) {
+      if (i == length || IsWordDelimiter<false>(text[i])) {
+        return i;
+      }
+    }
+  }
+
+  // Non-CJK/Emoji words end at IsWordDelimiter() or CJK/Emoji characters.
+  unsigned end = start_index;
+  UChar32 ch = text.CodePointAtAndNext(end);
+  if (!Character::IsCJKIdeographOrSymbol(ch)) {
+    for (unsigned next_end = end; end < length; end = next_end) {
+      ch = text.CodePointAtAndNext(next_end);
+      if (IsWordDelimiter<true>(ch) ||
+          Character::IsCJKIdeographOrSymbolBase(ch)) {
+        return end;
+      }
+    }
+    return length;
+  }
+
+  // For CJK/Emoji words, delimit every character because these scripts do
+  // not delimit words by spaces, and delimiting only at IsWordDelimiter()
+  // worsen the cache efficiency.
+  bool has_any_script = !Character::IsCommonOrInheritedScript(ch);
+  for (unsigned next_end = end; end < length; end = next_end) {
+    ch = text.CodePointAtAndNext(next_end);
+    // Modifier check in order not to split Emoji sequences.
+    if (U_GET_GC_MASK(ch) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_SK_MASK) ||
+        ch == uchar::kZeroWidthJoiner || Character::IsEmojiComponent(ch) ||
+        Character::IsExtendedPictographic(ch)) {
+      continue;
+    }
+    // Avoid delimiting COMMON/INHERITED alone, which makes harder to
+    // identify the script.
+    if (Character::IsCJKIdeographOrSymbol(ch)) {
+      if (Character::IsCommonOrInheritedScript(ch)) {
+        continue;
+      }
+      if (!has_any_script) {
+        has_any_script = true;
+        continue;
+      }
+    }
+    return end;
+  }
+  return length;
+}
+
 }  // namespace
 
 void PlainTextItem::Trace(Visitor* visitor) const {
@@ -245,8 +314,7 @@
   const wtf_size_t insertion_index = item_list_.size();
   StringView text_content(text_content_, start_offset, run_length);
   for (wtf_size_t index = 0; index < run_length;) {
-    wtf_size_t new_index =
-        CachingWordShapeIterator::NextWordEndIndex<true>(text_content, index);
+    wtf_size_t new_index = NextWordEndIndex(text_content, index);
     PlainTextItem item(start_offset + index, new_index - index, direction,
                        text_content_);
     if (IsLtr(direction)) {
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
index fd3f2ab..e0e0b7d6 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
+++ b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h
@@ -28,9 +28,7 @@
 
 #include "base/check_op.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
-#include "third_party/blink/renderer/platform/fonts/simple_font_data.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
 
 namespace blink {
 
@@ -44,81 +42,6 @@
 
   static const ShapeResult* ShapeWordWithoutSpacing(const TextRun&,
                                                     const Font*);
-
- private:
-  template <bool split_by_zws>
-  static bool IsWordDelimiter(UChar ch) {
-    // As of 2025 March, Google Docs always wraps text with BiDi control
-    // characters, and they are replaced with ZWS for HarfBuzzShaper.
-    // Assuming ZWS as a word delimiter improves hit rate of a shape cache.
-    return ch == uchar::kSpace || ch == uchar::kTab ||
-           (split_by_zws && ch == uchar::kZeroWidthSpace);
-  }
-
-  // TODO(crbug.com/389726691): Move NextWordEndIndex() to a new file because
-  // CachingWordShapeIterator will be removed.
-  friend class PlainTextNode;
-  template <bool split_by_zws>
-  static unsigned NextWordEndIndex(StringView text, unsigned start_index) {
-    const unsigned length = text.length();
-    if (start_index >= length) {
-      return 0;
-    }
-
-    if (start_index + 1u == length ||
-        IsWordDelimiter<split_by_zws>(text[start_index])) {
-      return start_index + 1;
-    }
-
-    // 8Bit words end at IsWordDelimiter().
-    if (text.Is8Bit()) {
-      for (unsigned i = start_index + 1;; ++i) {
-        if (i == length || IsWordDelimiter<false>(text[i])) {
-          return i;
-        }
-      }
-    }
-
-    // Non-CJK/Emoji words end at IsWordDelimiter() or CJK/Emoji characters.
-    unsigned end = start_index;
-    UChar32 ch = text.CodePointAtAndNext(end);
-    if (!Character::IsCJKIdeographOrSymbol(ch)) {
-      for (unsigned next_end = end; end < length; end = next_end) {
-        ch = text.CodePointAtAndNext(next_end);
-        if (IsWordDelimiter<split_by_zws>(ch) ||
-            Character::IsCJKIdeographOrSymbolBase(ch)) {
-          return end;
-        }
-      }
-      return length;
-    }
-
-    // For CJK/Emoji words, delimit every character because these scripts do
-    // not delimit words by spaces, and delimiting only at isWordDelimiter()
-    // worsen the cache efficiency.
-    bool has_any_script = !Character::IsCommonOrInheritedScript(ch);
-    for (unsigned next_end = end; end < length; end = next_end) {
-      ch = text.CodePointAtAndNext(next_end);
-      // Modifier check in order not to split Emoji sequences.
-      if (U_GET_GC_MASK(ch) & (U_GC_M_MASK | U_GC_LM_MASK | U_GC_SK_MASK) ||
-          ch == uchar::kZeroWidthJoiner || Character::IsEmojiComponent(ch) ||
-          Character::IsExtendedPictographic(ch)) {
-        continue;
-      }
-      // Avoid delimiting COMMON/INHERITED alone, which makes harder to
-      // identify the script.
-      if (Character::IsCJKIdeographOrSymbol(ch)) {
-        if (Character::IsCommonOrInheritedScript(ch))
-          continue;
-        if (!has_any_script) {
-          has_any_script = true;
-          continue;
-        }
-      }
-      return end;
-    }
-    return length;
-  }
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
deleted file mode 100644
index 59b4908..0000000
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.cc
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (C) 2015 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``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 APPLE INC. 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.
- */
-
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
-
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shape_iterator.h"
-
-namespace blink {
-
-GlyphData CachingWordShaper::EmphasisMarkGlyphData(
-    const TextRun& emphasis_mark_run) const {
-  return CachingWordShapeIterator::ShapeWordWithoutSpacing(emphasis_mark_run,
-                                                           &font_)
-      ->EmphasisMarkGlyphData(font_.GetFontDescription());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h b/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
deleted file mode 100644
index a4a299d..0000000
--- a/third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Copyright (C) 2015 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:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. 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.
- *
- * THIS SOFTWARE IS PROVIDED BY GOOGLE INC. ``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 APPLE INC. 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.
- */
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CACHING_WORD_SHAPER_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CACHING_WORD_SHAPER_H_
-
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
-
-namespace blink {
-
-class Font;
-class TextRun;
-struct GlyphData;
-
-class PLATFORM_EXPORT CachingWordShaper final {
-  STACK_ALLOCATED();
-
- public:
-  explicit CachingWordShaper(const Font& font) : font_(font) {}
-  CachingWordShaper(const CachingWordShaper&) = delete;
-  CachingWordShaper& operator=(const CachingWordShaper&) = delete;
-  ~CachingWordShaper() = default;
-
-  GlyphData EmphasisMarkGlyphData(const TextRun&) const;
-
- private:
-  const Font& font_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_CACHING_WORD_SHAPER_H_
diff --git a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
index 1e911e54..042287b6 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/shape_result_bloberizer.cc
@@ -13,7 +13,6 @@
 #include "cc/paint/paint_canvas.h"
 #include "third_party/blink/renderer/platform/fonts/font.h"
 #include "third_party/blink/renderer/platform/fonts/plain_text_node.h"
-#include "third_party/blink/renderer/platform/fonts/shaping/caching_word_shaper.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_view.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 22be93b..ed3cf754f 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -329,6 +329,14 @@
       name: "AIPageContentPaidContentAnnotation",
       status: "stable"
     },
+    // In AIPageContentAgent::ComputeHitTestableNodesInViewport, the hit test
+    // may hit the same node multiple times, which causes issues with computing
+    // the final z-order of page elements. This flag will filter those
+    // duplicate results first before doing any further processing.
+    {
+      name: "AIPageContentZOrderEarlyFiltering",
+      status: "stable"
+    },
     {
       name: "AIPromptAPI",
       public: true,
@@ -2289,7 +2297,7 @@
       // See crbug.com/421690393.
       name: "FileSystemAccessRevokeReadOnRemove",
       depends_on: ["FileSystemAccessWriteMode"],
-      status: "test",
+      status: "stable",
     },
     {
       // Controls the internal write-only mode for various FileSystemAccess API.
@@ -2297,7 +2305,7 @@
       // user visible APIs.
       // This flag is part of crbug.com/421690393 and crbug.com/328458680.
       name: "FileSystemAccessWriteMode",
-      status: "test",
+      status: "stable",
     },
     {
       // The FileSystemObserver interface for the File System Access API.
diff --git a/third_party/blink/web_tests/VIRTUAL_OWNERS b/third_party/blink/web_tests/VIRTUAL_OWNERS
index a9a7d2e..99fe72e 100644
--- a/third_party/blink/web_tests/VIRTUAL_OWNERS
+++ b/third_party/blink/web_tests/VIRTUAL_OWNERS
@@ -42,6 +42,7 @@
 dom@chromium.org
 flackr@chromium.org
 ikilpatrick@chromium.org
+jonathanjlee@google.com
 kojii@chromium.org
 masonf@chromium.org
 pdr@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-computed.html b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-computed.html
index b86198b..d4d5808 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-computed.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-computed.html
@@ -15,5 +15,11 @@
 test_computed_value("border-shape", "shape(from 0px 0px, hline to 100px, vline to 100px, close)");
 test_computed_value("border-shape", "circle() circle()", "circle()");
 test_computed_value("border-shape", "circle() polygon(10px 10px, 100px 10px, 10px 100px)");
-
+test_computed_value("border-shape", "circle() content-box");
+test_computed_value("border-shape", "circle() border-box", "circle()");
+test_computed_value("border-shape", "circle() border-box polygon(10px 10px, 100px 10px, 10px 100px) border-box", "circle() polygon(10px 10px, 100px 10px, 10px 100px)");
+test_computed_value("border-shape", "circle() padding-box polygon(10px 10px, 100px 10px, 10px 100px) border-box", "circle() padding-box polygon(10px 10px, 100px 10px, 10px 100px)");
+test_computed_value("border-shape", "circle() padding-box polygon(10px 10px, 100px 10px, 10px 100px) padding-box", "circle() padding-box polygon(10px 10px, 100px 10px, 10px 100px) padding-box");
+test_computed_value("border-shape", "circle() polygon(10px 10px, 100px 10px, 10px 100px) border-box", "circle() polygon(10px 10px, 100px 10px, 10px 100px)");
+test_computed_value("border-shape", "circle() polygon(10px 10px, 100px 10px, 10px 100px) content-box", "circle() polygon(10px 10px, 100px 10px, 10px 100px) content-box");
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-invalid.html
index 8d2aee6..36b40b1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-invalid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-invalid.html
@@ -11,5 +11,11 @@
 test_invalid_value("border-shape", "shape()");
 test_invalid_value("border-shape", "nonsense");
 test_invalid_value("border-shape", "1px");
-
+test_invalid_value("border-shape", "circle() padding-box margin-box");
+test_invalid_value("border-shape", "padding-box margin-box");
+test_invalid_value("border-shape", "padding-box");
+test_invalid_value("border-shape", "padding-box circle()");
+test_invalid_value("border-shape", "circle() padding-box margin-box circle()");
+test_invalid_value("border-shape", "circle() padding-box circle() margin-box circle()");
+test_invalid_value("border-shape", "circle() padding-box circle() margin-box padding-box");
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-valid.html b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-valid.html
index 2f9d3a4b..4ebb68a 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-valid.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/parsing/border-shape-valid.html
@@ -12,5 +12,5 @@
 test_valid_value("border-shape", "shape(from 0px 0px, hline to 100px, vline to 100px, close)");
 test_valid_value("border-shape", "circle() circle()", "circle()");
 test_valid_value("border-shape", "circle() polygon(10px 10px, 100px 10px, 10px 100px)");
-
+test_valid_value("border-shape", "circle() border-box circle() content-box");
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html
new file mode 100644
index 0000000..c6e5b3da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.html
@@ -0,0 +1,85 @@
+<!doctype html>
+<meta charset="utf-8">
+<title>Ensure that the scroll position isn't lost when the iframe is set to display:none and shown again</title>
+<link rel="author" href="mailto:perryuwang@gmail.com">
+<link rel="help" href="https://issues.chromium.org/issues/41368291">
+<script src="scroll_support.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+
+<div>
+  <iframe id="frame"></iframe>
+</div>
+
+<script>
+const IFRAME_PATH = '/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html';
+
+function waitForFrameLoadAsync(frame) {
+  return new Promise(async (resolve) => {
+    frame.addEventListener('load', resolve, { once: true });
+  });
+}
+
+function waitForMessageAsync(expected_frame_id, expected_command) {
+  return new Promise((resolve) => {
+    window.addEventListener('message', (event) => {
+      assert_equals(event.data.command, expected_command);
+      assert_equals(event.data.frame_id, expected_frame_id);
+      resolve({scrollX: event.data.scrollX, scrollY: event.data.scrollY});
+    }, { once: true });
+  });
+}
+
+function iframeScrollTo(frame, x, y) {
+  return new Promise(async (resolve) => {
+    const scroll_ack_waiter = waitForMessageAsync(frame.id, 'scrollTo');
+    await frame.contentWindow.postMessage({
+      command: 'scrollTo',
+      frame_id: frame.id,
+      scrollX: x,
+      scrollY: y,
+    }, '*');
+    const ret = await scroll_ack_waiter;
+    resolve(ret);
+  });
+}
+
+function iframeGetScroll(frame) {
+  return new Promise(async (resolve) => {
+    const scroll_ack_waiter = waitForMessageAsync(frame.id, 'getScroll');
+    await frame.contentWindow.postMessage({
+      command: 'getScroll',
+      frame_id: frame.id,
+    }, '*');
+    const ret = await scroll_ack_waiter;
+    resolve(ret);
+  });
+}
+
+async function testIFrame(src) {
+  const frame = document.getElementById('frame');
+  frame.src = src;
+  await waitForFrameLoadAsync(frame);
+  let ret = await iframeScrollTo(frame, 1000, 2000);
+  assert_equals(ret.scrollX, 1000);
+  assert_equals(ret.scrollY, 2000);
+  frame.style.display = 'none';
+  await waitForCompositorCommit();
+  frame.style.display = '';
+  await waitForCompositorCommit();
+  ret = await iframeGetScroll(frame);
+  assert_equals(ret.scrollX, 1000);
+  assert_equals(ret.scrollY, 2000);
+}
+
+window.onload = async () => {
+  promise_test(async () => {
+    await testIFrame(IFRAME_PATH);
+  }, 'Ensure that the scroll position is not lost when the local iframe is set to display:none and shown again.');
+
+  promise_test(async () => {
+    await testIFrame(get_host_info().HTTP_NOTSAMESITE_ORIGIN + IFRAME_PATH);
+  }, 'Ensure that the scroll position is not lost when the remote iframe is set to display:none and shown again.');
+}
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html
new file mode 100644
index 0000000..f9c22d9
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/dom/events/scrolling/save-iframe-scroll-offset-when-display-none.sub.html
@@ -0,0 +1,34 @@
+<!DOCTYPE html>
+<div style="width: 10000px; height: 10000px">
+  <!-- Adding <input> is to reproduce scroll offset reset when display:none -->
+  <input type="text">
+</div>
+<script>
+function postReplyMessage(target, frame_id, command) {
+  target.postMessage({
+    command: command,
+    frame_id: frame_id,
+    scrollX: window.scrollX,
+    scrollY: window.scrollY
+  }, "*");
+}
+
+function handleMessage(event) {
+  switch (event.data.command) {
+    case 'scrollTo':
+      window.scrollTo(event.data.scrollX, event.data.scrollY);
+      break;
+    case 'getScroll':
+      // No-op, just reply with current scroll position.
+      break;
+    default:
+      throw Error(`Unknown command: ${event.data.command}`);
+      break;
+  }
+  requestAnimationFrame(() => {
+    postReplyMessage(event.source, event.data.frame_id, event.data.command);
+  });
+}
+
+window.addEventListener('message', handleMessage);
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple-ref.html
new file mode 100644
index 0000000..e3563c0b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple-ref.html
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<select>
+  <option>one</option>
+  <option>two</option>
+</select>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple.html
new file mode 100644
index 0000000..803af7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/the-select-element/select-toggle-multiple.html
@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html class=reftest-wait>
+<link rel=author href="mailto:jarhar@chromium.org">
+<link rel=help href="https://issues.chromium.org/issues/450045066">
+<link rel=match href="select-toggle-multiple-ref.html">
+
+<select>
+  <option>one</option>
+  <option>two</option>
+</select>
+
+<script>
+(async () => {
+  const select = document.querySelector('select');
+  await new Promise(requestAnimationFrame);
+  select.multiple = true;
+  await new Promise(requestAnimationFrame);
+  select.multiple = false;
+  await new Promise(requestAnimationFrame);
+  document.documentElement.classList.remove('reftest-wait');
+})();
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/pad.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/pad.https.any.js
index f1b9151..8be69ecb 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/pad.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/pad.https.any.js
@@ -29,6 +29,32 @@
 
 const padTests = [
   {
+    'name':
+        'padding float32 0D constant tensor with empty paddings should be no-op',
+    'graph': {
+      'inputs': {
+        'padInput': {
+          'data': [22.76361846923828],
+          'descriptor': {shape: [], dataType: 'float32'},
+          'constant': true
+        }
+      },
+      'operators': [{
+        'name': 'pad',
+        'arguments': [
+          {'input': 'padInput'}, {'beginningPadding': []}, {'endingPadding': []}
+        ],
+        'outputs': 'padOutput'
+      }],
+      'expectedOutputs': {
+        'padOutput': {
+          'data': [22.76361846923828],
+          'descriptor': {shape: [], dataType: 'float32'}
+        }
+      }
+    }
+  },
+  {
     'name': 'pad float32 1D constant tensor default options',
     'graph': {
       'inputs': {
@@ -690,11 +716,7 @@
     'graph': {
       'inputs': {
         'padInput': {
-          'data': [
-            22, -21, -91,
-            16, 60, -70,
-            -60, -47, 68
-          ],
+          'data': [22, -21, -91, 16, 60, -70, -60, -47, 68],
           'descriptor': {shape: [3, 3], dataType: 'int64'}
         }
       },
@@ -764,30 +786,14 @@
       'expectedOutputs': {
         'padOutput': {
           'data': [
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            22.76361846923828,
-            -21.168529510498047,
-            -91.66168975830078,
-            -Infinity,
-            -Infinity,
-            16.863798141479492,
-            60.51472091674805,
-            -70.56755065917969,
-            -Infinity,
-            -Infinity,
-            -60.643272399902344,
-            -47.8821907043457,
-            68.72557830810547,
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            -Infinity,
-            -Infinity,
+            -Infinity,         -Infinity,           -Infinity,
+            -Infinity,         -Infinity,           -Infinity,
+            22.76361846923828, -21.168529510498047, -91.66168975830078,
+            -Infinity,         -Infinity,           16.863798141479492,
+            60.51472091674805, -70.56755065917969,  -Infinity,
+            -Infinity,         -60.643272399902344, -47.8821907043457,
+            68.72557830810547, -Infinity,           -Infinity,
+            -Infinity,         -Infinity,           -Infinity,
             -Infinity
           ],
           'descriptor': {shape: [5, 5], dataType: 'float32'}
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/slice.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/slice.https.any.js
index 479340e..bca4aa7 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/slice.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/slice.https.any.js
@@ -17,6 +17,30 @@
 
 const sliceTests = [
   {
+    'name':
+        'slicing float32 0D constant tensor with empty starts and sizes should be a no-op',
+    'graph': {
+      'inputs': {
+        'sliceInput': {
+          'data': [28.846250534057617],
+          'descriptor': {shape: [], dataType: 'float32'},
+          'constant': true
+        }
+      },
+      'operators': [{
+        'name': 'slice',
+        'arguments': [{'input': 'sliceInput'}, {'starts': []}, {'sizes': []}],
+        'outputs': 'sliceOutput'
+      }],
+      'expectedOutputs': {
+        'sliceOutput': {
+          'data': [28.846250534057617],
+          'descriptor': {shape: [], dataType: 'float32'}
+        }
+      }
+    }
+  },
+  {
     'name': 'slice float32 1D constant tensor',
     'graph': {
       'inputs': {
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/argMinMax.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/argMinMax.https.any.js
index 563eb3af..2d3063a 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/argMinMax.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/argMinMax.https.any.js
@@ -62,6 +62,12 @@
       label: label,
     },
   },
+  {
+    name: '[argMin/Max] Throw if outputDataType=float32',
+    input: {dataType: 'float32', shape: [1, 2, 3, 4]},
+    axis: 1,
+    options: {outputDataType: 'float32', label: label}
+  }
 ];
 
 function runTests(operatorName, tests) {
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/batchNormalization.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/batchNormalization.https.any.js
index 6952ff0..5bf79af7 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/batchNormalization.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/batchNormalization.https.any.js
@@ -248,6 +248,16 @@
       label: label,
     },
   },
+  {
+    name: '[batchNormalization] Throw if the input is a scalar.',
+    input: {dataType: 'float32', shape: []},
+    mean: {dataType: 'float32', shape: [1]},
+    variance: {dataType: 'float32', shape: [1]},
+    options: {
+      axis: 0,
+      label: label,
+    }
+  }
 ];
 
 tests.forEach(
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/cumulativeSum.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/cumulativeSum.https.any.js
index f63a0399..04f68f9 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/cumulativeSum.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/cumulativeSum.https.any.js
@@ -15,6 +15,12 @@
     output: {dataType: 'float32', shape: [3, 2, 5]}
   },
   {
+    name: '[cumulativeSum] Test with integer input',
+    input: {dataType: 'int32', shape: [3, 2, 5]},
+    axis: 0,
+    output: {dataType: 'int32', shape: [3, 2, 5]}
+  },
+  {
     name: '[cumulativeSum] Test with axis=1',
     input: {dataType: 'float32', shape: [3, 2, 5]},
     axis: 1,
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/pad.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/pad.https.any.js
index fb285ed..adc0bd3 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/pad.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/pad.https.any.js
@@ -53,11 +53,12 @@
     output: {dataType: 'float32', shape: [4, 7]}
   },
   {
-    name: '[pad] Throw if building pad for scalar input.',
+    name:
+        '[pad] Test pad for scalar input with empty beginningPadding and endingPadding.',
     input: {dataType: 'float32', shape: []},
     beginningPadding: [],
     endingPadding: [],
-    options: {label}
+    output: {dataType: 'float32', shape: []}
   },
   {
     name:
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/slice.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/slice.https.any.js
index 1350f5c..833628a 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/slice.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/slice.https.any.js
@@ -26,7 +26,14 @@
     output: {dataType: 'float32', shape: [1, 2, 3]}
   },
   {
-    name: '[slice] Throw if input is a scalar.',
+    name: '[slice] Test slicing a scalar with empty starts and sizes.',
+    input: {dataType: 'float32', shape: []},
+    starts: [],
+    sizes: [],
+    output: {dataType: 'float32', shape: []}
+  },
+  {
+    name: '[slice] Throw if input is a scalar and starts/sizes are not empty.',
     input: {dataType: 'float32', shape: []},
     starts: [0],
     sizes: [1]
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/softmax.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/softmax.https.any.js
index 0aaae63..13ac9968 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/softmax.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/softmax.https.any.js
@@ -80,6 +80,11 @@
     name: '[softmax] Throw if the axis is greater than input rank - 1.',
     input: {dataType: 'float16', shape: [3, 1, 5, 2]},
     axis: 4
+  },
+  {
+    name: '[softmax] Throw if the input is a scalar.',
+    input: {dataType: 'float32', shape: []},
+    axis: 0
   }
 ];
 
diff --git a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/split.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/split.https.any.js
index 9bc3980..21b790bc 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/validation_tests/split.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/validation_tests/split.https.any.js
@@ -41,7 +41,7 @@
   {
     name: '[split] Throw if splitting a scalar.',
     input: {dataType: 'float32', shape: []},
-    splits: [2],
+    splits: [1],
     options: {label}
   },
   {
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index 08a77f3..ed44d6f 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit 08a77f3d88475b092c365d12576de078a54a6d91
+Subproject commit ed44d6f8deb450d8178908027ff46a0252b2d405
diff --git a/third_party/catapult b/third_party/catapult
index 179e385..423d5e6 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 179e38564ddc7cdf0b58d5c923f2c5c3b132899a
+Subproject commit 423d5e63ff44523b3e2895d94165b80d4a003227
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src
index 5436a04..75e7832 160000
--- a/third_party/compiler-rt/src
+++ b/third_party/compiler-rt/src
@@ -1 +1 @@
-Subproject commit 5436a04e9d9f47771ae83ac5942e1d0e690baf76
+Subproject commit 75e783208e3c6a8c6236cc9f45d11d10f601c14f
diff --git a/third_party/dawn b/third_party/dawn
index d1ef389..895a2f1 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit d1ef389738224f8a92c5a4557a812db47cf042cc
+Subproject commit 895a2f1fc2a1e02c99b3b9522fbb4474b0c8da93
diff --git a/third_party/depot_tools b/third_party/depot_tools
index 8fc14e1..8c6304b 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit 8fc14e1deafc4356319f2534de813899a3e01094
+Subproject commit 8c6304befd2205384c73e73d214848e57d9a0239
diff --git a/third_party/lit/v3_0/BUILD.gn b/third_party/lit/v3_0/BUILD.gn
index de34ff5..5245b4e 100644
--- a/third_party/lit/v3_0/BUILD.gn
+++ b/third_party/lit/v3_0/BUILD.gn
@@ -62,6 +62,7 @@
     "//chrome/browser/resources/privacy_sandbox/internals/private_state_tokens:build_ts",
     "//chrome/browser/resources/privacy_sandbox/internals/related_website_sets:build_ts",
     "//chrome/browser/resources/profile_internals:build_ts",
+    "//chrome/browser/resources/reload_button:build_ts",
     "//chrome/browser/resources/search_engine_choice:build_ts",
     "//chrome/browser/resources/settings:build_ts",
     "//chrome/browser/resources/side_panel/bookmarks:build_ts",
diff --git a/third_party/perfetto b/third_party/perfetto
index ff11fbe..d7ea394 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit ff11fbe7c825083afe471945766e615bc675800b
+Subproject commit d7ea394300667faed7b239e087a51447586a3132
diff --git a/third_party/rust/adler2/v2/README.chromium b/third_party/rust/adler2/v2/README.chromium
index 7e87542..c8e30b0 100644
--- a/third_party/rust/adler2/v2/README.chromium
+++ b/third_party/rust/adler2/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/adler2
 Version: 2.0.1
 Revision: 89a031a0f42eeff31c70dc598b398cbf31f1680f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/adler2-v2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/anstyle/v1/README.chromium b/third_party/rust/anstyle/v1/README.chromium
index 08e0d30..25c4551 100644
--- a/third_party/rust/anstyle/v1/README.chromium
+++ b/third_party/rust/anstyle/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/anstyle
 Version: 1.0.13
 Revision: 14dd743496d1614f8261a093ce755f26d8e2069d
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/anstyle-v1/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/anyhow/v1/README.chromium b/third_party/rust/anyhow/v1/README.chromium
index 8ed496ea..0f032122 100644
--- a/third_party/rust/anyhow/v1/README.chromium
+++ b/third_party/rust/anyhow/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/anyhow
 Version: 1.0.100
 Revision: 18c2598afa0f996f56217ef128aa3a20ea1e9512
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/anyhow-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/arrayvec/v0_7/README.chromium b/third_party/rust/arrayvec/v0_7/README.chromium
index 5a3aa0b1..fdeed49 100644
--- a/third_party/rust/arrayvec/v0_7/README.chromium
+++ b/third_party/rust/arrayvec/v0_7/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/arrayvec
 Version: 0.7.6
 Revision: 0aede877fe0bfb1ba5e3c2024df8c0958d503a83
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/arrayvec-v0_7/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/autocfg/v1/README.chromium b/third_party/rust/autocfg/v1/README.chromium
index b4ae907..ba5bac2 100644
--- a/third_party/rust/autocfg/v1/README.chromium
+++ b/third_party/rust/autocfg/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/autocfg
 Version: 1.5.0
 Revision: d912169ed67977efe5a465269b0e73cb66060c49
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/autocfg-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/base64/v0_22/README.chromium b/third_party/rust/base64/v0_22/README.chromium
index 9205349..86a1a0c 100644
--- a/third_party/rust/base64/v0_22/README.chromium
+++ b/third_party/rust/base64/v0_22/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/base64
 Version: 0.22.1
 Revision: e14400697453bcc85997119b874bc03d9601d0af
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/base64-v0_22/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/bitflags/v1/README.chromium b/third_party/rust/bitflags/v1/README.chromium
index f92723e..81680d90 100644
--- a/third_party/rust/bitflags/v1/README.chromium
+++ b/third_party/rust/bitflags/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/bitflags
 Version: 1.3.2
 Revision: ed185cfb1c447c1b4bd6ac021c9ec3bb02c9e2f2
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/bitflags-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/bitflags/v2/README.chromium b/third_party/rust/bitflags/v2/README.chromium
index 013b4a5..e0704886 100644
--- a/third_party/rust/bitflags/v2/README.chromium
+++ b/third_party/rust/bitflags/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/bitflags
 Version: 2.9.4
 Revision: de0ec28f9999bb8984fa92e19a2f53181098cc87
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/bitflags-v2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/bytemuck/v1/README.chromium b/third_party/rust/bytemuck/v1/README.chromium
index 8035f7a..f9a05bf6 100644
--- a/third_party/rust/bytemuck/v1/README.chromium
+++ b/third_party/rust/bytemuck/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/bytemuck
 Version: 1.23.2
 Revision: c069a2f6a4c7f3416257d0378c799085aa5626bb
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/bytemuck-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/bytemuck_derive/v1/README.chromium b/third_party/rust/bytemuck_derive/v1/README.chromium
index ab0ec4b..7f77a20b 100644
--- a/third_party/rust/bytemuck_derive/v1/README.chromium
+++ b/third_party/rust/bytemuck_derive/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/bytemuck_derive
 Version: 1.10.1
 Revision: 2524f62b76b0ec4804e3f4af4510fcd1253ffe66
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/bytemuck_derive-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/bytes/v1/README.chromium b/third_party/rust/bytes/v1/README.chromium
index c6eba8f..7ea6aca 100644
--- a/third_party/rust/bytes/v1/README.chromium
+++ b/third_party/rust/bytes/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/bytes
 Version: 1.10.1
 Revision: 19d1427c971f6b619356966163459e43f797de2f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/bytes-v1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/calendrical_calculations/v0_2/README.chromium b/third_party/rust/calendrical_calculations/v0_2/README.chromium
index 4767b23..f59e75e 100644
--- a/third_party/rust/calendrical_calculations/v0_2/README.chromium
+++ b/third_party/rust/calendrical_calculations/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/calendrical_calculations
 Version: 0.2.2
 Revision: fbb3eebe2f65e64a69b3a1837dce8ed9cbbe677e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/calendrical_calculations-v0_2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/cfg_if/v1/README.chromium b/third_party/rust/cfg_if/v1/README.chromium
index 7b57460..0194ec6 100644
--- a/third_party/rust/cfg_if/v1/README.chromium
+++ b/third_party/rust/cfg_if/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/cfg-if
 Version: 1.0.3
 Revision: 9c7bb0bf7184698c16ba60aad424b9b8263ac6db
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/cfg-if-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/clap/v4/README.chromium b/third_party/rust/clap/v4/README.chromium
index 9d16d09..3406e82 100644
--- a/third_party/rust/clap/v4/README.chromium
+++ b/third_party/rust/clap/v4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/clap
 Version: 4.5.48
 Revision: 8e3d03639756241aa2b7dd624a7f5852bef76f31
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/clap-v4/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/clap_builder/v4/README.chromium b/third_party/rust/clap_builder/v4/README.chromium
index f7a533c..24b833f4 100644
--- a/third_party/rust/clap_builder/v4/README.chromium
+++ b/third_party/rust/clap_builder/v4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/clap_builder
 Version: 4.5.48
 Revision: 8e3d03639756241aa2b7dd624a7f5852bef76f31
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/clap_builder-v4/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/clap_lex/v0_7/README.chromium b/third_party/rust/clap_lex/v0_7/README.chromium
index 942b30b..e9348124 100644
--- a/third_party/rust/clap_lex/v0_7/README.chromium
+++ b/third_party/rust/clap_lex/v0_7/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/clap_lex
 Version: 0.7.5
 Revision: 3716f9f4289594b43abec42b2538efd1a90ff897
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/clap_lex-v0_7/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/codespan_reporting/v0_12/README.chromium b/third_party/rust/codespan_reporting/v0_12/README.chromium
index b08d72f..18d11ee 100644
--- a/third_party/rust/codespan_reporting/v0_12/README.chromium
+++ b/third_party/rust/codespan_reporting/v0_12/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/codespan-reporting
 Version: 0.12.0
 Revision: 3d3a03a8fcc30cc10b783b16c62029d5c232059b
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/codespan-reporting-v0_12/LICENSE
 Shipped: yes
diff --git a/third_party/rust/core_maths/v0_1/README.chromium b/third_party/rust/core_maths/v0_1/README.chromium
index f066a1da..f6af182 100644
--- a/third_party/rust/core_maths/v0_1/README.chromium
+++ b/third_party/rust/core_maths/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/core_maths
 Version: 0.1.1
 Revision: d8ea96acac3893ad9a7e16cd7526936fbfc51021
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/core_maths-v0_1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/crc32fast/v1/README.chromium b/third_party/rust/crc32fast/v1/README.chromium
index 8a417b8d..cc766f9a 100644
--- a/third_party/rust/crc32fast/v1/README.chromium
+++ b/third_party/rust/crc32fast/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/crc32fast
 Version: 1.5.0
 Revision: dbf4f76cd71cdcc57d9164cbd46890d53ce0423c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/crc32fast-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/cxx/v1/README.chromium b/third_party/rust/cxx/v1/README.chromium
index 253b4ef..f2e6b8e 100644
--- a/third_party/rust/cxx/v1/README.chromium
+++ b/third_party/rust/cxx/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/cxx
 Version: 1.0.186
 Revision: 191684c5d2e88b7bc43c623f698a23b612d10772
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/cxx-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/cxxbridge_cmd/v1/README.chromium b/third_party/rust/cxxbridge_cmd/v1/README.chromium
index f2e21e5..b4d14c55 100644
--- a/third_party/rust/cxxbridge_cmd/v1/README.chromium
+++ b/third_party/rust/cxxbridge_cmd/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/cxxbridge-cmd
 Version: 1.0.186
 Revision: 191684c5d2e88b7bc43c623f698a23b612d10772
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/cxxbridge-cmd-v1/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/cxxbridge_flags/v1/README.chromium b/third_party/rust/cxxbridge_flags/v1/README.chromium
index de743902..fa5a8e0 100644
--- a/third_party/rust/cxxbridge_flags/v1/README.chromium
+++ b/third_party/rust/cxxbridge_flags/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/cxxbridge-flags
 Version: 1.0.186
 Revision: 191684c5d2e88b7bc43c623f698a23b612d10772
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/cxxbridge-flags-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/cxxbridge_macro/v1/README.chromium b/third_party/rust/cxxbridge_macro/v1/README.chromium
index 7e3ddaa..623738a 100644
--- a/third_party/rust/cxxbridge_macro/v1/README.chromium
+++ b/third_party/rust/cxxbridge_macro/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/cxxbridge-macro
 Version: 1.0.186
 Revision: 191684c5d2e88b7bc43c623f698a23b612d10772
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/cxxbridge-macro-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/derivre/v0_3/README.chromium b/third_party/rust/derivre/v0_3/README.chromium
index 3255cf2a..36baa72 100644
--- a/third_party/rust/derivre/v0_3/README.chromium
+++ b/third_party/rust/derivre/v0_3/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/derivre
 Version: 0.3.8
 Revision: c68f60791d191a05131796771f38c2e904417074
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/derivre-v0_3/LICENSE
 Shipped: yes
diff --git a/third_party/rust/diplomat/v0_13/README.chromium b/third_party/rust/diplomat/v0_13/README.chromium
index 64c7026..9a3b18e 100644
--- a/third_party/rust/diplomat/v0_13/README.chromium
+++ b/third_party/rust/diplomat/v0_13/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/diplomat
 Version: 0.13.0
 Revision: f05fabd1bd2a23b2e28f3cbba812f3719b4748c8
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/diplomat-v0_13/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/diplomat_core/v0_13/README.chromium b/third_party/rust/diplomat_core/v0_13/README.chromium
index 98b1aa5..47013e4 100644
--- a/third_party/rust/diplomat_core/v0_13/README.chromium
+++ b/third_party/rust/diplomat_core/v0_13/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/diplomat_core
 Version: 0.13.0
 Revision: f05fabd1bd2a23b2e28f3cbba812f3719b4748c8
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/diplomat_core-v0_13/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/diplomat_runtime/v0_13/README.chromium b/third_party/rust/diplomat_runtime/v0_13/README.chromium
index b8844af..34fe90e 100644
--- a/third_party/rust/diplomat_runtime/v0_13/README.chromium
+++ b/third_party/rust/diplomat_runtime/v0_13/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/diplomat-runtime
 Version: 0.13.0
 Revision: f05fabd1bd2a23b2e28f3cbba812f3719b4748c8
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/diplomat-runtime-v0_13/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/displaydoc/v0_2/README.chromium b/third_party/rust/displaydoc/v0_2/README.chromium
index 5aacdbf..bcfacd3b 100644
--- a/third_party/rust/displaydoc/v0_2/README.chromium
+++ b/third_party/rust/displaydoc/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/displaydoc
 Version: 0.2.5
 Revision: e4028851bfb82998300237f7568a45f589a19e40
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/displaydoc-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/either/v1/README.chromium b/third_party/rust/either/v1/README.chromium
index e7a2819..e302d68 100644
--- a/third_party/rust/either/v1/README.chromium
+++ b/third_party/rust/either/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/either
 Version: 1.15.0
 Revision: 59ae1fce0cec62c886fcd486e06b7e219bc7ce48
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/either-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/encoding_rs/v0_8/README.chromium b/third_party/rust/encoding_rs/v0_8/README.chromium
index fbd48de3..f09b1db 100644
--- a/third_party/rust/encoding_rs/v0_8/README.chromium
+++ b/third_party/rust/encoding_rs/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/encoding_rs
 Version: 0.8.35
 Revision: 2fa58aecf537cc76ff52c0eb3d5e9f8fda466844
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0, BSD-3-Clause
 License File: //third_party/rust/chromium_crates_io/vendor/encoding_rs-v0_8/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/equivalent/v1/README.chromium b/third_party/rust/equivalent/v1/README.chromium
index 003fc2b..f8cfbd9 100644
--- a/third_party/rust/equivalent/v1/README.chromium
+++ b/third_party/rust/equivalent/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/equivalent
 Version: 1.0.2
 Revision: 44cdd44f8b8ebb5f9ae096c7550a5e74ffb7d6ae
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/equivalent-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/fdeflate/v0_3/README.chromium b/third_party/rust/fdeflate/v0_3/README.chromium
index 23da7f3..f5f1dc95 100644
--- a/third_party/rust/fdeflate/v0_3/README.chromium
+++ b/third_party/rust/fdeflate/v0_3/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/fdeflate
 Version: 0.3.7
 Revision: c365c7e6ffa81feb2e1fb762eed7299f05c9b0ca
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/fdeflate-v0_3/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/fend_core/v1/README.chromium b/third_party/rust/fend_core/v1/README.chromium
index 4c3b09d4..df881ca9 100644
--- a/third_party/rust/fend_core/v1/README.chromium
+++ b/third_party/rust/fend_core/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/fend-core
 Version: 1.5.7
 Revision: 9886a0d35a1de1fae4975d99651285ef06f124b3
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/fend-core-v1/LICENSE.md
 Shipped: yes
diff --git a/third_party/rust/fixed_decimal/v0_7/README.chromium b/third_party/rust/fixed_decimal/v0_7/README.chromium
index 9e0895c..17ab626 100644
--- a/third_party/rust/fixed_decimal/v0_7/README.chromium
+++ b/third_party/rust/fixed_decimal/v0_7/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/fixed_decimal
 Version: 0.7.0
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/fixed_decimal-v0_7/LICENSE
 Shipped: yes
diff --git a/third_party/rust/flate2/v1/README.chromium b/third_party/rust/flate2/v1/README.chromium
index 46643ea..029b06e 100644
--- a/third_party/rust/flate2/v1/README.chromium
+++ b/third_party/rust/flate2/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/flate2
 Version: 1.1.2
 Revision: ac4d950ffdeab209350423c528d876a7a7811abb
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/flate2-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/foldhash/v0_2/README.chromium b/third_party/rust/foldhash/v0_2/README.chromium
index 6cc1d05..855d5b2 100644
--- a/third_party/rust/foldhash/v0_2/README.chromium
+++ b/third_party/rust/foldhash/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/foldhash
 Version: 0.2.0
 Revision: 8f878c636fda9c9e93384824ea45e06d03f009f5
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Zlib
 License File: //third_party/rust/chromium_crates_io/vendor/foldhash-v0_2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/font_types/v0_10/README.chromium b/third_party/rust/font_types/v0_10/README.chromium
index 9187a9d..38fb575 100644
--- a/third_party/rust/font_types/v0_10/README.chromium
+++ b/third_party/rust/font_types/v0_10/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/font-types
 Version: 0.10.0
 Revision: 1a8baba89aa129a899bc83b0b610881190f8bbad
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/font-types-v0_10/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/hashbrown/v0_15/README.chromium b/third_party/rust/hashbrown/v0_15/README.chromium
index 00e051a0..fb8b61f 100644
--- a/third_party/rust/hashbrown/v0_15/README.chromium
+++ b/third_party/rust/hashbrown/v0_15/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/hashbrown
 Version: 0.15.5
 Revision: b751eef8e99ccf3652046ef4a9e1ec47c1bfb78d
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/hashbrown-v0_15/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/heck/v0_5/README.chromium b/third_party/rust/heck/v0_5/README.chromium
index ffbdd88..ee4889a3 100644
--- a/third_party/rust/heck/v0_5/README.chromium
+++ b/third_party/rust/heck/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/heck
 Version: 0.5.0
 Revision: 070693322aee7c5c7fbee7c9964bf8d7d3a29c96
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/heck-v0_5/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/hex/v0_4/README.chromium b/third_party/rust/hex/v0_4/README.chromium
index eed24cf..86df884 100644
--- a/third_party/rust/hex/v0_4/README.chromium
+++ b/third_party/rust/hex/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/hex
 Version: 0.4.3
 Revision: b2b4370b5bf021b98ee7adc92233e8de3f2de792
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/hex-v0_4/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/icu_calendar/v2/README.chromium b/third_party/rust/icu_calendar/v2/README.chromium
index 5977bdf..92c500ee 100644
--- a/third_party/rust/icu_calendar/v2/README.chromium
+++ b/third_party/rust/icu_calendar/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_calendar
 Version: 2.0.5
 Revision: 72e94a5baa4bc7840b27eae48cc9364fc018a483
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_calendar-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_calendar_data/v2/README.chromium b/third_party/rust/icu_calendar_data/v2/README.chromium
index 7942c43..ee57b045 100644
--- a/third_party/rust/icu_calendar_data/v2/README.chromium
+++ b/third_party/rust/icu_calendar_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_calendar_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_calendar_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_casemap/v2/README.chromium b/third_party/rust/icu_casemap/v2/README.chromium
index 96c1918..165c87c 100644
--- a/third_party/rust/icu_casemap/v2/README.chromium
+++ b/third_party/rust/icu_casemap/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_casemap
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_casemap-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_casemap_data/v2/README.chromium b/third_party/rust/icu_casemap_data/v2/README.chromium
index 5025cb3..8c8a3a5 100644
--- a/third_party/rust/icu_casemap_data/v2/README.chromium
+++ b/third_party/rust/icu_casemap_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_casemap_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_casemap_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_collections/v2/README.chromium b/third_party/rust/icu_collections/v2/README.chromium
index 92d631b6..945b3bf6 100644
--- a/third_party/rust/icu_collections/v2/README.chromium
+++ b/third_party/rust/icu_collections/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_collections
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_collections-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_decimal/v2/README.chromium b/third_party/rust/icu_decimal/v2/README.chromium
index 6f729046..6b7d032 100644
--- a/third_party/rust/icu_decimal/v2/README.chromium
+++ b/third_party/rust/icu_decimal/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_decimal
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_decimal-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_decimal_data/v2/README.chromium b/third_party/rust/icu_decimal_data/v2/README.chromium
index c13c621..1c6b862 100644
--- a/third_party/rust/icu_decimal_data/v2/README.chromium
+++ b/third_party/rust/icu_decimal_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_decimal_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_decimal_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_experimental/v0_3/README.chromium b/third_party/rust/icu_experimental/v0_3/README.chromium
index ec244c2..a16f320c 100644
--- a/third_party/rust/icu_experimental/v0_3/README.chromium
+++ b/third_party/rust/icu_experimental/v0_3/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_experimental
 Version: 0.3.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_experimental-v0_3/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_experimental_data/v0_3/README.chromium b/third_party/rust/icu_experimental_data/v0_3/README.chromium
index 03d6441..52bc5e4 100644
--- a/third_party/rust/icu_experimental_data/v0_3/README.chromium
+++ b/third_party/rust/icu_experimental_data/v0_3/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_experimental_data
 Version: 0.3.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_experimental_data-v0_3/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_list/v2/README.chromium b/third_party/rust/icu_list/v2/README.chromium
index af412d3..60942c0 100644
--- a/third_party/rust/icu_list/v2/README.chromium
+++ b/third_party/rust/icu_list/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_list
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_list-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_list_data/v2/README.chromium b/third_party/rust/icu_list_data/v2/README.chromium
index e76f4c16..5ad618f 100644
--- a/third_party/rust/icu_list_data/v2/README.chromium
+++ b/third_party/rust/icu_list_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_list_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_list_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_locale/v2/README.chromium b/third_party/rust/icu_locale/v2/README.chromium
index 5295d25..deb9ab5 100644
--- a/third_party/rust/icu_locale/v2/README.chromium
+++ b/third_party/rust/icu_locale/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_locale
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_locale-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_locale_core/v2/README.chromium b/third_party/rust/icu_locale_core/v2/README.chromium
index e159099..7908ef9 100644
--- a/third_party/rust/icu_locale_core/v2/README.chromium
+++ b/third_party/rust/icu_locale_core/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_locale_core
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_locale_core-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_locale_data/v2/README.chromium b/third_party/rust/icu_locale_data/v2/README.chromium
index 883a815f..725607d 100644
--- a/third_party/rust/icu_locale_data/v2/README.chromium
+++ b/third_party/rust/icu_locale_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_locale_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_locale_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_normalizer/v2/README.chromium b/third_party/rust/icu_normalizer/v2/README.chromium
index 0555ebae..912a0cb 100644
--- a/third_party/rust/icu_normalizer/v2/README.chromium
+++ b/third_party/rust/icu_normalizer/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_normalizer
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_normalizer-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_normalizer_data/v2/README.chromium b/third_party/rust/icu_normalizer_data/v2/README.chromium
index 184d184..51df4ab 100644
--- a/third_party/rust/icu_normalizer_data/v2/README.chromium
+++ b/third_party/rust/icu_normalizer_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_normalizer_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_normalizer_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_pattern/v0_4/README.chromium b/third_party/rust/icu_pattern/v0_4/README.chromium
index 51b1726f..a908fe0c 100644
--- a/third_party/rust/icu_pattern/v0_4/README.chromium
+++ b/third_party/rust/icu_pattern/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_pattern
 Version: 0.4.0
 Revision: c8a616acb260000e0b8ef3545fd6de2c528d7f29
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_pattern-v0_4/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_plurals/v2/README.chromium b/third_party/rust/icu_plurals/v2/README.chromium
index f081c99..99e6388 100644
--- a/third_party/rust/icu_plurals/v2/README.chromium
+++ b/third_party/rust/icu_plurals/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_plurals
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_plurals-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_plurals_data/v2/README.chromium b/third_party/rust/icu_plurals_data/v2/README.chromium
index a50d8fc..4e056c9d 100644
--- a/third_party/rust/icu_plurals_data/v2/README.chromium
+++ b/third_party/rust/icu_plurals_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_plurals_data
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_plurals_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_properties/v2/README.chromium b/third_party/rust/icu_properties/v2/README.chromium
index db0b63ff..2d1fe9ab 100644
--- a/third_party/rust/icu_properties/v2/README.chromium
+++ b/third_party/rust/icu_properties/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_properties
 Version: 2.0.1
 Revision: 6fe1953b1fe2e2df9d7727f74752c04e30181e78
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_properties-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_properties_data/v2/README.chromium b/third_party/rust/icu_properties_data/v2/README.chromium
index b463405..632e00c2 100644
--- a/third_party/rust/icu_properties_data/v2/README.chromium
+++ b/third_party/rust/icu_properties_data/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_properties_data
 Version: 2.0.1
 Revision: 6fe1953b1fe2e2df9d7727f74752c04e30181e78
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_properties_data-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/icu_provider/v2/README.chromium b/third_party/rust/icu_provider/v2/README.chromium
index 28fa830..4e27ae1 100644
--- a/third_party/rust/icu_provider/v2/README.chromium
+++ b/third_party/rust/icu_provider/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/icu_provider
 Version: 2.0.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/icu_provider-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/indexmap/v2/README.chromium b/third_party/rust/indexmap/v2/README.chromium
index d3ea96f..00047de 100644
--- a/third_party/rust/indexmap/v2/README.chromium
+++ b/third_party/rust/indexmap/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/indexmap
 Version: 2.11.4
 Revision: 03f9e58626ad7ef811b1522097bced2400c18b1a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/indexmap-v2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/itertools/v0_11/README.chromium b/third_party/rust/itertools/v0_11/README.chromium
index fbacd46..68a08d5a 100644
--- a/third_party/rust/itertools/v0_11/README.chromium
+++ b/third_party/rust/itertools/v0_11/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/itertools
 Version: 0.11.0
 Revision: 62a6401afd6d45e1c2aea94c05cb5c70076b2ca4
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/itertools-v0_11/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/itoa/v1/README.chromium b/third_party/rust/itoa/v1/README.chromium
index 575bd5d..642c3ad 100644
--- a/third_party/rust/itoa/v1/README.chromium
+++ b/third_party/rust/itoa/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/itoa
 Version: 1.0.15
 Revision: e2766b868e4ac1ae2bf5bea1ac43d4c0da23b899
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/itoa-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/ixdtf/v0_6/README.chromium b/third_party/rust/ixdtf/v0_6/README.chromium
index a8e2138..eb9cb7e7 100644
--- a/third_party/rust/ixdtf/v0_6/README.chromium
+++ b/third_party/rust/ixdtf/v0_6/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/ixdtf
 Version: 0.6.3
 Revision: 4d53125a232c56fff3a947c2f4d1f4ae58b91d1d
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/ixdtf-v0_6/LICENSE
 Shipped: yes
diff --git a/third_party/rust/lazy_static/v1/README.chromium b/third_party/rust/lazy_static/v1/README.chromium
index dbde242..786c824 100644
--- a/third_party/rust/lazy_static/v1/README.chromium
+++ b/third_party/rust/lazy_static/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/lazy_static
 Version: 1.5.0
 Revision: be7c1c43f264699f956b70ce8e29941bd1e61bde
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/lazy_static-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/libc/v0_2/README.chromium b/third_party/rust/libc/v0_2/README.chromium
index 3bac76d..82776ea 100644
--- a/third_party/rust/libc/v0_2/README.chromium
+++ b/third_party/rust/libc/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/libc
 Version: 0.2.176
 Revision: 15e1389ae87935c9c08f4449a73c7b979cded21a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/libc-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/libm/v0_2/README.chromium b/third_party/rust/libm/v0_2/README.chromium
index 1475241e..9d7db85 100644
--- a/third_party/rust/libm/v0_2/README.chromium
+++ b/third_party/rust/libm/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/libm
 Version: 0.2.15
 Revision: a4c748f72a1dce652cc3e41c3a8425731bd1519a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/libm-v0_2/LICENSE.txt
 Shipped: yes
diff --git a/third_party/rust/litemap/v0_8/README.chromium b/third_party/rust/litemap/v0_8/README.chromium
index 1c07f81..0dc66bef3 100644
--- a/third_party/rust/litemap/v0_8/README.chromium
+++ b/third_party/rust/litemap/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/litemap
 Version: 0.8.0
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/litemap-v0_8/LICENSE
 Shipped: yes
diff --git a/third_party/rust/llguidance/v1/README.chromium b/third_party/rust/llguidance/v1/README.chromium
index 1289c83..a12bb0b 100644
--- a/third_party/rust/llguidance/v1/README.chromium
+++ b/third_party/rust/llguidance/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/llguidance
 Version: 1.2.0
 Revision: c65e3c3244713b9ebcc204cc5676c8a4a57f78bf
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/llguidance-v1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/log/v0_4/README.chromium b/third_party/rust/log/v0_4/README.chromium
index 7eadf4c52..4e033e7 100644
--- a/third_party/rust/log/v0_4/README.chromium
+++ b/third_party/rust/log/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/log
 Version: 0.4.28
 Revision: 6e1735597bb21c5d979a077395df85e1d633e077
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/log-v0_4/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/memchr/v2/README.chromium b/third_party/rust/memchr/v2/README.chromium
index c845930..45e1e06 100644
--- a/third_party/rust/memchr/v2/README.chromium
+++ b/third_party/rust/memchr/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/memchr
 Version: 2.7.6
 Revision: 9ba486e4ba7e865c0510305c5dacba73988d9f31
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/memchr-v2/LICENSE-MIT
 Shipped: yes
diff --git a/third_party/rust/miniz_oxide/v0_8/README.chromium b/third_party/rust/miniz_oxide/v0_8/README.chromium
index b331d9cc..48bb146 100644
--- a/third_party/rust/miniz_oxide/v0_8/README.chromium
+++ b/third_party/rust/miniz_oxide/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/miniz_oxide
 Version: 0.8.9
 Revision: 44e43c7786e379b2b1a7fde4aa0e63be719e583d
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/miniz_oxide-v0_8/LICENSE-APACHE.md
 Shipped: yes
diff --git a/third_party/rust/num_bigint/v0_4/README.chromium b/third_party/rust/num_bigint/v0_4/README.chromium
index 4950d42..8beb064 100644
--- a/third_party/rust/num_bigint/v0_4/README.chromium
+++ b/third_party/rust/num_bigint/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/num-bigint
 Version: 0.4.6
 Revision: a25836ec6c341d1aa40c97335842f330b6a62911
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/num-bigint-v0_4/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/num_integer/v0_1/README.chromium b/third_party/rust/num_integer/v0_1/README.chromium
index 4cfaa7ea..86be387 100644
--- a/third_party/rust/num_integer/v0_1/README.chromium
+++ b/third_party/rust/num_integer/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/num-integer
 Version: 0.1.46
 Revision: ede2d2cb993e55e7b1c992bfd22ecbf16601a652
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/num-integer-v0_1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/num_rational/v0_4/README.chromium b/third_party/rust/num_rational/v0_4/README.chromium
index 5c11302..77eeb06 100644
--- a/third_party/rust/num_rational/v0_4/README.chromium
+++ b/third_party/rust/num_rational/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/num-rational
 Version: 0.4.2
 Revision: 4d55ad22ac86ebbc4cb45d79a956e4a1f7af57d1
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/num-rational-v0_4/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/num_traits/v0_2/README.chromium b/third_party/rust/num_traits/v0_2/README.chromium
index fea35746..43635b9 100644
--- a/third_party/rust/num_traits/v0_2/README.chromium
+++ b/third_party/rust/num_traits/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/num-traits
 Version: 0.2.19
 Revision: 7ec3d41d39b28190ec1d42db38021107b3951f3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/num-traits-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/png/v0_18/README.chromium b/third_party/rust/png/v0_18/README.chromium
index d958b11..7a3a6611 100644
--- a/third_party/rust/png/v0_18/README.chromium
+++ b/third_party/rust/png/v0_18/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/png
 Version: 0.18.0-rc
 Revision: eb9b5d7f371b88f15aaca6a8d21c58b86c400d76
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/png-v0_18/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/potential_utf/v0_1/README.chromium b/third_party/rust/potential_utf/v0_1/README.chromium
index ef36f49c5..1bb4ae29 100644
--- a/third_party/rust/potential_utf/v0_1/README.chromium
+++ b/third_party/rust/potential_utf/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/potential_utf
 Version: 0.1.3
 Revision: fbb3eebe2f65e64a69b3a1837dce8ed9cbbe677e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/potential_utf-v0_1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/proc_macro2/v1/README.chromium b/third_party/rust/proc_macro2/v1/README.chromium
index 11b270e..50f57ec 100644
--- a/third_party/rust/proc_macro2/v1/README.chromium
+++ b/third_party/rust/proc_macro2/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/proc-macro2
 Version: 1.0.101
 Revision: d3188ea889e55be0433326695b2773c717b39bb9
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/proc-macro2-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/prost/v0_14/README.chromium b/third_party/rust/prost/v0_14/README.chromium
index c7d9e1c..d3c23c6e 100644
--- a/third_party/rust/prost/v0_14/README.chromium
+++ b/third_party/rust/prost/v0_14/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/prost
 Version: 0.14.1
 Revision: 9965a988a7f95d55c106b933a82a3e657dce02c2
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/prost-v0_14/LICENSE
 Shipped: no
diff --git a/third_party/rust/prost_derive/v0_14/README.chromium b/third_party/rust/prost_derive/v0_14/README.chromium
index 9d1b8df52..41a7988 100644
--- a/third_party/rust/prost_derive/v0_14/README.chromium
+++ b/third_party/rust/prost_derive/v0_14/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/prost-derive
 Version: 0.14.1
 Revision: 9965a988a7f95d55c106b933a82a3e657dce02c2
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/prost-derive-v0_14/LICENSE
 Shipped: no
diff --git a/third_party/rust/qr_code/v2/README.chromium b/third_party/rust/qr_code/v2/README.chromium
index 317ee30..24a0616 100644
--- a/third_party/rust/qr_code/v2/README.chromium
+++ b/third_party/rust/qr_code/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/qr_code
 Version: 2.0.0
 Revision: 341f62be3a91ecb05e6e0870e61f763308eaf2ff
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/qr_code-v2/LICENSE-APACHE.txt
 Shipped: yes
diff --git a/third_party/rust/quote/v1/README.chromium b/third_party/rust/quote/v1/README.chromium
index a9ffe7f..9ec00658 100644
--- a/third_party/rust/quote/v1/README.chromium
+++ b/third_party/rust/quote/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/quote
 Version: 1.0.41
 Revision: 594c865ce817b4adb5863713e4fa3749fbf47f0a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/quote-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/read_fonts/v0_35/README.chromium b/third_party/rust/read_fonts/v0_35/README.chromium
index fb579efe..efc365f 100644
--- a/third_party/rust/read_fonts/v0_35/README.chromium
+++ b/third_party/rust/read_fonts/v0_35/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/read-fonts
 Version: 0.35.0
 Revision: 1a8baba89aa129a899bc83b0b610881190f8bbad
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/read-fonts-v0_35/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/regex_automata/v0_4/README.chromium b/third_party/rust/regex_automata/v0_4/README.chromium
index 6919e5d8..a490ffb 100644
--- a/third_party/rust/regex_automata/v0_4/README.chromium
+++ b/third_party/rust/regex_automata/v0_4/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/regex-automata
 Version: 0.4.11
 Revision: 159fa3e1e0984ade1edf4831b80c94cdf4b3ed9f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/regex-automata-v0_4/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/regex_syntax/v0_8/README.chromium b/third_party/rust/regex_syntax/v0_8/README.chromium
index a9f1feb..1157ec6 100644
--- a/third_party/rust/regex_syntax/v0_8/README.chromium
+++ b/third_party/rust/regex_syntax/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/regex-syntax
 Version: 0.8.6
 Revision: ea834f8e1fd7b72a3c1b2319b1a47f0c50d43082
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/regex-syntax-v0_8/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/resb/v0_1/README.chromium b/third_party/rust/resb/v0_1/README.chromium
index 590ee4b6..034ed67 100644
--- a/third_party/rust/resb/v0_1/README.chromium
+++ b/third_party/rust/resb/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/resb
 Version: 0.1.0
 Revision: 7d369fbb651d594322ef44f12ea56066973628e4
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/resb-v0_1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/rustc_demangle/v0_1/README.chromium b/third_party/rust/rustc_demangle/v0_1/README.chromium
index b76b9dc5..9305d1f9 100644
--- a/third_party/rust/rustc_demangle/v0_1/README.chromium
+++ b/third_party/rust/rustc_demangle/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/rustc-demangle
 Version: 0.1.26
 Revision: c5688cfec32d2bd00701836f12beb3560ee015b8
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/rustc-demangle-v0_1/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/rustc_demangle_capi/v0_1/README.chromium b/third_party/rust/rustc_demangle_capi/v0_1/README.chromium
index 3a6af406..13cac6d4 100644
--- a/third_party/rust/rustc_demangle_capi/v0_1/README.chromium
+++ b/third_party/rust/rustc_demangle_capi/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/rustc-demangle-capi
 Version: 0.1.1
 Revision: 8145ea3869767f044ca63667ca17eab544f3a8ee
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/rustc-demangle-capi-v0_1/LICENSE-APACHE
 Shipped: no
diff --git a/third_party/rust/rustversion/v1/README.chromium b/third_party/rust/rustversion/v1/README.chromium
index f7abbcf0..b924add 100644
--- a/third_party/rust/rustversion/v1/README.chromium
+++ b/third_party/rust/rustversion/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/rustversion
 Version: 1.0.22
 Revision: 9e86f839b6a34a7d9398f243d88bf400b7fa1f7c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/rustversion-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/ryu/v1/README.chromium b/third_party/rust/ryu/v1/README.chromium
index 66becca..dda5b1b7 100644
--- a/third_party/rust/ryu/v1/README.chromium
+++ b/third_party/rust/ryu/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/ryu
 Version: 1.0.20
 Revision: 02237f8751db162e9ed0f5bd3e7135d1b256822e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/ryu-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/serde/v1/README.chromium b/third_party/rust/serde/v1/README.chromium
index efecfd6..e136a60 100644
--- a/third_party/rust/serde/v1/README.chromium
+++ b/third_party/rust/serde/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/serde
 Version: 1.0.228
 Revision: a866b336f14aa57a07f0d0be9f8762746e64ecb4
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/serde-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/serde_core/v1/README.chromium b/third_party/rust/serde_core/v1/README.chromium
index d29eb40..bbe5a3f753 100644
--- a/third_party/rust/serde_core/v1/README.chromium
+++ b/third_party/rust/serde_core/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/serde_core
 Version: 1.0.228
 Revision: a866b336f14aa57a07f0d0be9f8762746e64ecb4
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/serde_core-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/serde_derive/v1/README.chromium b/third_party/rust/serde_derive/v1/README.chromium
index d9571948..9167f7e1 100644
--- a/third_party/rust/serde_derive/v1/README.chromium
+++ b/third_party/rust/serde_derive/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/serde_derive
 Version: 1.0.228
 Revision: a866b336f14aa57a07f0d0be9f8762746e64ecb4
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/serde_derive-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/serde_json/v1/README.chromium b/third_party/rust/serde_json/v1/README.chromium
index 74e3b95..54a3814 100644
--- a/third_party/rust/serde_json/v1/README.chromium
+++ b/third_party/rust/serde_json/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/serde_json
 Version: 1.0.145
 Revision: efa66e3a1d61459ab2d325f92ebe3acbd6ca18b1
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/serde_json-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/serde_json_lenient/v0_2/README.chromium b/third_party/rust/serde_json_lenient/v0_2/README.chromium
index 6260b441..1979a99 100644
--- a/third_party/rust/serde_json_lenient/v0_2/README.chromium
+++ b/third_party/rust/serde_json_lenient/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/serde_json_lenient
 Version: 0.2.4
 Revision: ec5b6e7782647f8e165e3d2e619dbe4541071cf7
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/serde_json_lenient-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/simd_adler32/v0_3/README.chromium b/third_party/rust/simd_adler32/v0_3/README.chromium
index 8071d9d..51c9ec6 100644
--- a/third_party/rust/simd_adler32/v0_3/README.chromium
+++ b/third_party/rust/simd_adler32/v0_3/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/simd-adler32
 Version: 0.3.7
 Revision: 94f3f72eb7346d9e2bfe7e985a496582da409a63
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/simd-adler32-v0_3/LICENSE.md
 Shipped: yes
diff --git a/third_party/rust/skrifa/v0_37/README.chromium b/third_party/rust/skrifa/v0_37/README.chromium
index 53b62f2..424ab5c6 100644
--- a/third_party/rust/skrifa/v0_37/README.chromium
+++ b/third_party/rust/skrifa/v0_37/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/skrifa
 Version: 0.37.0
 Revision: 1a8baba89aa129a899bc83b0b610881190f8bbad
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/skrifa-v0_37/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/small_ctor/v0_1/README.chromium b/third_party/rust/small_ctor/v0_1/README.chromium
index cd7d385..11b29f1 100644
--- a/third_party/rust/small_ctor/v0_1/README.chromium
+++ b/third_party/rust/small_ctor/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/small_ctor
 Version: 0.1.2
 Revision: 81ca7a1ff7c309f784a4c20eb99a3aeea43b80ca
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/small_ctor-v0_1/LICENSE
 Shipped: no
diff --git a/third_party/rust/smallvec/v1/README.chromium b/third_party/rust/smallvec/v1/README.chromium
index ab45bfa..e18355c 100644
--- a/third_party/rust/smallvec/v1/README.chromium
+++ b/third_party/rust/smallvec/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/smallvec
 Version: 1.15.1
 Revision: d0f47a3ea99296498ee940b5d99f59b403c498a2
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/smallvec-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/stable_deref_trait/v1/README.chromium b/third_party/rust/stable_deref_trait/v1/README.chromium
index 40355fb..b8f3f34 100644
--- a/third_party/rust/stable_deref_trait/v1/README.chromium
+++ b/third_party/rust/stable_deref_trait/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/stable_deref_trait
 Version: 1.2.0
 Revision: 66f9d8a15b7209c45f58edee6c1b6bb497b7bd31
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/stable_deref_trait-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/static_assertions/v1/README.chromium b/third_party/rust/static_assertions/v1/README.chromium
index 437c9d6d..32dc796 100644
--- a/third_party/rust/static_assertions/v1/README.chromium
+++ b/third_party/rust/static_assertions/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/static_assertions
 Version: 1.1.0
 Revision: 18bc65a094d890fe1faa5d3ccb70f12b89eabf56
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/static_assertions-v1/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/strck/v1/README.chromium b/third_party/rust/strck/v1/README.chromium
index f215230..f3af842 100644
--- a/third_party/rust/strck/v1/README.chromium
+++ b/third_party/rust/strck/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/strck
 Version: 1.0.0
 Revision: 4c3add2f9964ce1c5720d7924dbf5291818fc37e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/strck-v1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/strsim/v0_11/README.chromium b/third_party/rust/strsim/v0_11/README.chromium
index d6e79c6c..0f135ee 100644
--- a/third_party/rust/strsim/v0_11/README.chromium
+++ b/third_party/rust/strsim/v0_11/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/strsim
 Version: 0.11.1
 Revision: 76c5a900e6e12cfc605eee5ab6e36300384c8682
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/strsim-v0_11/LICENSE
 Shipped: no
diff --git a/third_party/rust/strum/v0_27/README.chromium b/third_party/rust/strum/v0_27/README.chromium
index c373c60..0f9949e 100644
--- a/third_party/rust/strum/v0_27/README.chromium
+++ b/third_party/rust/strum/v0_27/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/strum
 Version: 0.27.2
 Revision: c8d6241123d68b2e56a8d546300508294338f69a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/strum-v0_27/LICENSE
 Shipped: yes
diff --git a/third_party/rust/strum_macros/v0_27/README.chromium b/third_party/rust/strum_macros/v0_27/README.chromium
index 67dd2887..06669e22 100644
--- a/third_party/rust/strum_macros/v0_27/README.chromium
+++ b/third_party/rust/strum_macros/v0_27/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/strum_macros
 Version: 0.27.2
 Revision: c8d6241123d68b2e56a8d546300508294338f69a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/strum_macros-v0_27/LICENSE
 Shipped: yes
diff --git a/third_party/rust/subtle/v2/README.chromium b/third_party/rust/subtle/v2/README.chromium
index 21923d8..c3f8c10b 100644
--- a/third_party/rust/subtle/v2/README.chromium
+++ b/third_party/rust/subtle/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/subtle
 Version: 2.6.1
 Revision: 5457b5448b021d1da101ababbb854e6657233943
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: BSD-3-Clause
 License File: //third_party/rust/chromium_crates_io/vendor/subtle-v2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/symphonia/v0_5/README.chromium b/third_party/rust/symphonia/v0_5/README.chromium
index f6b2562..1be7af7e 100644
--- a/third_party/rust/symphonia/v0_5/README.chromium
+++ b/third_party/rust/symphonia/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/symphonia
 Version: 0.5.4
 Revision: d3b7742fa73674b70d9ab80cc5f8384cc653df3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MPL-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/symphonia-v0_5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/symphonia_bundle_flac/v0_5/README.chromium b/third_party/rust/symphonia_bundle_flac/v0_5/README.chromium
index 67a0923..7cfeaf77 100644
--- a/third_party/rust/symphonia_bundle_flac/v0_5/README.chromium
+++ b/third_party/rust/symphonia_bundle_flac/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/symphonia-bundle-flac
 Version: 0.5.4
 Revision: d3b7742fa73674b70d9ab80cc5f8384cc653df3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MPL-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/symphonia-bundle-flac-v0_5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/symphonia_core/v0_5/README.chromium b/third_party/rust/symphonia_core/v0_5/README.chromium
index ffaace9..ea86231 100644
--- a/third_party/rust/symphonia_core/v0_5/README.chromium
+++ b/third_party/rust/symphonia_core/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/symphonia-core
 Version: 0.5.4
 Revision: d3b7742fa73674b70d9ab80cc5f8384cc653df3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MPL-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/symphonia-core-v0_5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/symphonia_metadata/v0_5/README.chromium b/third_party/rust/symphonia_metadata/v0_5/README.chromium
index 0b1e0c0..b52470e5 100644
--- a/third_party/rust/symphonia_metadata/v0_5/README.chromium
+++ b/third_party/rust/symphonia_metadata/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/symphonia-metadata
 Version: 0.5.4
 Revision: d3b7742fa73674b70d9ab80cc5f8384cc653df3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MPL-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/symphonia-metadata-v0_5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/symphonia_utils_xiph/v0_5/README.chromium b/third_party/rust/symphonia_utils_xiph/v0_5/README.chromium
index d621130..35aaf328 100644
--- a/third_party/rust/symphonia_utils_xiph/v0_5/README.chromium
+++ b/third_party/rust/symphonia_utils_xiph/v0_5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/symphonia-utils-xiph
 Version: 0.5.4
 Revision: d3b7742fa73674b70d9ab80cc5f8384cc653df3a
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MPL-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/symphonia-utils-xiph-v0_5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/syn/v2/README.chromium b/third_party/rust/syn/v2/README.chromium
index 4e0f4ef..529c692 100644
--- a/third_party/rust/syn/v2/README.chromium
+++ b/third_party/rust/syn/v2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/syn
 Version: 2.0.106
 Revision: 0e4bc64fe1e07a574b6f3133927a27991fd40c2e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/syn-v2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/synstructure/v0_13/README.chromium b/third_party/rust/synstructure/v0_13/README.chromium
index 56c21d5..1ef879a 100644
--- a/third_party/rust/synstructure/v0_13/README.chromium
+++ b/third_party/rust/synstructure/v0_13/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/synstructure
 Version: 0.13.2
 Revision: 91ead072fa43c55f35880bd7f75a2b0eab72a04e
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/synstructure-v0_13/LICENSE
 Shipped: yes
diff --git a/third_party/rust/temporal_capi/v0_1/README.chromium b/third_party/rust/temporal_capi/v0_1/README.chromium
index c419b1f..c976f82 100644
--- a/third_party/rust/temporal_capi/v0_1/README.chromium
+++ b/third_party/rust/temporal_capi/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/temporal_capi
 Version: 0.1.0
 Revision: 1d1b123ff78a3ab656d5aa19d803d1516f95e92f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/temporal_capi-v0_1/LICENSE-Apache
 Shipped: yes
diff --git a/third_party/rust/temporal_rs/v0_1/README.chromium b/third_party/rust/temporal_rs/v0_1/README.chromium
index f5fba412..937412b 100644
--- a/third_party/rust/temporal_rs/v0_1/README.chromium
+++ b/third_party/rust/temporal_rs/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/temporal_rs
 Version: 0.1.0
 Revision: 1d1b123ff78a3ab656d5aa19d803d1516f95e92f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/temporal_rs-v0_1/LICENSE-Apache
 Shipped: yes
diff --git a/third_party/rust/termcolor/v1/README.chromium b/third_party/rust/termcolor/v1/README.chromium
index 11cab0e..11fd00d 100644
--- a/third_party/rust/termcolor/v1/README.chromium
+++ b/third_party/rust/termcolor/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/termcolor
 Version: 1.4.1
 Revision: 71f0921f1eeceda85487098588a1602979d52493
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/termcolor-v1/LICENSE-MIT
 Shipped: yes
diff --git a/third_party/rust/timezone_provider/v0_1/README.chromium b/third_party/rust/timezone_provider/v0_1/README.chromium
index 407b4658..8df37c1 100644
--- a/third_party/rust/timezone_provider/v0_1/README.chromium
+++ b/third_party/rust/timezone_provider/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/timezone_provider
 Version: 0.1.0
 Revision: 1d1b123ff78a3ab656d5aa19d803d1516f95e92f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/timezone_provider-v0_1/LICENSE-Apache
 Shipped: yes
diff --git a/third_party/rust/tinystr/v0_8/README.chromium b/third_party/rust/tinystr/v0_8/README.chromium
index 05b0dbf..a573d1e 100644
--- a/third_party/rust/tinystr/v0_8/README.chromium
+++ b/third_party/rust/tinystr/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/tinystr
 Version: 0.8.1
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/tinystr-v0_8/LICENSE
 Shipped: yes
diff --git a/third_party/rust/toktrie/v1/README.chromium b/third_party/rust/toktrie/v1/README.chromium
index dea0cc1f..e49349e 100644
--- a/third_party/rust/toktrie/v1/README.chromium
+++ b/third_party/rust/toktrie/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/toktrie
 Version: 1.2.0
 Revision: c65e3c3244713b9ebcc204cc5676c8a4a57f78bf
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/toktrie-v1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/unicode_ident/v1/README.chromium b/third_party/rust/unicode_ident/v1/README.chromium
index 701f83e..fddef5d 100644
--- a/third_party/rust/unicode_ident/v1/README.chromium
+++ b/third_party/rust/unicode_ident/v1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/unicode-ident
 Version: 1.0.19
 Revision: dc018bf1ca82d295f72a84e7ed432e5d2bcbe2fe
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0, Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/unicode-ident-v1/LICENSE-APACHE,//third_party/rust/chromium_crates_io/vendor/unicode-ident-v1/LICENSE-UNICODE
 Shipped: yes
diff --git a/third_party/rust/unicode_width/v0_2/README.chromium b/third_party/rust/unicode_width/v0_2/README.chromium
index 1bddd46..3b31c102 100644
--- a/third_party/rust/unicode_width/v0_2/README.chromium
+++ b/third_party/rust/unicode_width/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/unicode-width
 Version: 0.2.1
 Revision: 0085e91db72ae9a4498e62030d9651f1c1d09b4f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/unicode-width-v0_2/LICENSE-APACHE
 Shipped: yes
diff --git a/third_party/rust/winapi_util/v0_1/README.chromium b/third_party/rust/winapi_util/v0_1/README.chromium
index 1213efd..171c2b7 100644
--- a/third_party/rust/winapi_util/v0_1/README.chromium
+++ b/third_party/rust/winapi_util/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/winapi-util
 Version: 0.1.11
 Revision: 803874c57dc1f10ecd42f7c86d9de72f53818432
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/winapi-util-v0_1/LICENSE-MIT
 Shipped: yes
diff --git a/third_party/rust/windows_aarch64_msvc/v0_52/README.chromium b/third_party/rust/windows_aarch64_msvc/v0_52/README.chromium
index fb2a91ce..269fca600 100644
--- a/third_party/rust/windows_aarch64_msvc/v0_52/README.chromium
+++ b/third_party/rust/windows_aarch64_msvc/v0_52/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/windows_aarch64_msvc
 Version: 0.52.6
 Revision: db06b51c2ebb743efb544d40e3064efa49f28d38
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/windows_aarch64_msvc-v0_52/license-apache-2.0
 Shipped: yes
diff --git a/third_party/rust/windows_i686_msvc/v0_52/README.chromium b/third_party/rust/windows_i686_msvc/v0_52/README.chromium
index a93faaa66..4df9253 100644
--- a/third_party/rust/windows_i686_msvc/v0_52/README.chromium
+++ b/third_party/rust/windows_i686_msvc/v0_52/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/windows_i686_msvc
 Version: 0.52.6
 Revision: db06b51c2ebb743efb544d40e3064efa49f28d38
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/windows_i686_msvc-v0_52/license-apache-2.0
 Shipped: yes
diff --git a/third_party/rust/windows_sys/v0_52/README.chromium b/third_party/rust/windows_sys/v0_52/README.chromium
index c8b0105..ed9829e 100644
--- a/third_party/rust/windows_sys/v0_52/README.chromium
+++ b/third_party/rust/windows_sys/v0_52/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/windows-sys
 Version: 0.52.0
 Revision: 3a605cba064b26f2a198ac58085f8c8836f47c38
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/windows-sys-v0_52/license-apache-2.0
 Shipped: yes
diff --git a/third_party/rust/windows_targets/v0_52/README.chromium b/third_party/rust/windows_targets/v0_52/README.chromium
index 95449a78..66226cb 100644
--- a/third_party/rust/windows_targets/v0_52/README.chromium
+++ b/third_party/rust/windows_targets/v0_52/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/windows-targets
 Version: 0.52.6
 Revision: db06b51c2ebb743efb544d40e3064efa49f28d38
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/windows-targets-v0_52/license-apache-2.0
 Shipped: yes
diff --git a/third_party/rust/windows_x86_64_msvc/v0_52/README.chromium b/third_party/rust/windows_x86_64_msvc/v0_52/README.chromium
index 3f3d03f..8aa1e9b1 100644
--- a/third_party/rust/windows_x86_64_msvc/v0_52/README.chromium
+++ b/third_party/rust/windows_x86_64_msvc/v0_52/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/windows_x86_64_msvc
 Version: 0.52.6
 Revision: db06b51c2ebb743efb544d40e3064efa49f28d38
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Apache-2.0
 License File: //third_party/rust/chromium_crates_io/vendor/windows_x86_64_msvc-v0_52/license-apache-2.0
 Shipped: yes
diff --git a/third_party/rust/writeable/v0_6/README.chromium b/third_party/rust/writeable/v0_6/README.chromium
index 3aea2866..367847b4 100644
--- a/third_party/rust/writeable/v0_6/README.chromium
+++ b/third_party/rust/writeable/v0_6/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/writeable
 Version: 0.6.1
 Revision: e9ab7308efb2fdc0fca96f71106c68f9f5840056
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/writeable-v0_6/LICENSE
 Shipped: yes
diff --git a/third_party/rust/yoke/v0_8/README.chromium b/third_party/rust/yoke/v0_8/README.chromium
index bce5620..6dac633f 100644
--- a/third_party/rust/yoke/v0_8/README.chromium
+++ b/third_party/rust/yoke/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/yoke
 Version: 0.8.0
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/yoke-v0_8/LICENSE
 Shipped: yes
diff --git a/third_party/rust/yoke_derive/v0_8/README.chromium b/third_party/rust/yoke_derive/v0_8/README.chromium
index 57a6376..b8a7f75 100644
--- a/third_party/rust/yoke_derive/v0_8/README.chromium
+++ b/third_party/rust/yoke_derive/v0_8/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/yoke-derive
 Version: 0.8.0
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/yoke-derive-v0_8/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zerofrom/v0_1/README.chromium b/third_party/rust/zerofrom/v0_1/README.chromium
index 8c51421c..6cec69f3 100644
--- a/third_party/rust/zerofrom/v0_1/README.chromium
+++ b/third_party/rust/zerofrom/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zerofrom
 Version: 0.1.6
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zerofrom-v0_1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zerofrom_derive/v0_1/README.chromium b/third_party/rust/zerofrom_derive/v0_1/README.chromium
index be30c4f..c694510 100644
--- a/third_party/rust/zerofrom_derive/v0_1/README.chromium
+++ b/third_party/rust/zerofrom_derive/v0_1/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zerofrom-derive
 Version: 0.1.6
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zerofrom-derive-v0_1/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zerotrie/v0_2/README.chromium b/third_party/rust/zerotrie/v0_2/README.chromium
index fe81530..9252b17 100644
--- a/third_party/rust/zerotrie/v0_2/README.chromium
+++ b/third_party/rust/zerotrie/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zerotrie
 Version: 0.2.2
 Revision: 5e404744dd6c9dd7f86aac82586e3fa98ea75f7f
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zerotrie-v0_2/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zerovec/v0_11/README.chromium b/third_party/rust/zerovec/v0_11/README.chromium
index 1f44b2e8..ab73938 100644
--- a/third_party/rust/zerovec/v0_11/README.chromium
+++ b/third_party/rust/zerovec/v0_11/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zerovec
 Version: 0.11.4
 Revision: 23b31cd3b6fe6d6d58e9211e0c87689194638efd
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zerovec-v0_11/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zerovec_derive/v0_11/README.chromium b/third_party/rust/zerovec_derive/v0_11/README.chromium
index 8aad5e09..68f9d9b 100644
--- a/third_party/rust/zerovec_derive/v0_11/README.chromium
+++ b/third_party/rust/zerovec_derive/v0_11/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zerovec-derive
 Version: 0.11.1
 Revision: f4290a877dfcb0f87cad6de4abdd65f0cbb33c9c
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zerovec-derive-v0_11/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zip/v5/README.chromium b/third_party/rust/zip/v5/README.chromium
index fe854aaf..851976b5 100644
--- a/third_party/rust/zip/v5/README.chromium
+++ b/third_party/rust/zip/v5/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zip
 Version: 5.1.1
 Revision: 6423fee132a8819c82c2cf73ea6fb07dd3016b72
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: MIT
 License File: //third_party/rust/chromium_crates_io/vendor/zip-v5/LICENSE
 Shipped: yes
diff --git a/third_party/rust/zoneinfo64/v0_2/README.chromium b/third_party/rust/zoneinfo64/v0_2/README.chromium
index aa3f52a7..4b3e513 100644
--- a/third_party/rust/zoneinfo64/v0_2/README.chromium
+++ b/third_party/rust/zoneinfo64/v0_2/README.chromium
@@ -2,7 +2,7 @@
 URL: https://crates.io/crates/zoneinfo64
 Version: 0.2.0
 Revision: c1c377b49af283bdf89937b4f5ce516710e55a37
-Update Mechanism: Manual
+Update Mechanism: Manual (https://crbug.com/449898466)
 License: Unicode-3.0
 License File: //third_party/rust/chromium_crates_io/vendor/zoneinfo64-v0_2/LICENSE
 Shipped: yes
diff --git a/third_party/skia b/third_party/skia
index 3480f588..e4dc4fd 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 3480f588eb09d25a4b1c15e643197a1eef058718
+Subproject commit e4dc4fdb541d30b786d373b09217d769d06ed946
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index cd34cfe6..90603b2 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit cd34cfe6a579d03c0675b32844599294773634aa
+Subproject commit 90603b2036a87d17dde4d38f5fa16fc770961e94
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 07a7e8a..1acbea5 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 07a7e8afd318ba34ac2a999002e6602d88205c41
+Subproject commit 1acbea52c1e445b9398ecc228cb3bb115d97aac5
diff --git a/third_party/webrtc b/third_party/webrtc
index 85cbfaf..661a2e6 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 85cbfaf6b96394215415527d67546d4bd872208a
+Subproject commit 661a2e642d3bec939e203650fb0b86e1af815c63
diff --git a/tools/crates/gnrt/lib/readme.rs b/tools/crates/gnrt/lib/readme.rs
index 6bb911c..609a9c71 100644
--- a/tools/crates/gnrt/lib/readme.rs
+++ b/tools/crates/gnrt/lib/readme.rs
@@ -20,12 +20,6 @@
 use strum_macros::EnumIter;
 
 #[derive(Clone, Debug, Serialize)]
-pub enum UpdateMechanism {
-    Autoroll,
-    Manual,
-}
-
-#[derive(Clone, Debug, Serialize)]
 pub struct ReadmeFile {
     name: String,
     url: String,
@@ -36,7 +30,7 @@
     license: String,
     license_files: Vec<String>,
     revision: Option<String>,
-    update_mechanism: UpdateMechanism,
+    update_mechanism: String,
 }
 
 /// Returns a map keyed by the directory where the README file should be
@@ -201,9 +195,10 @@
         license,
         license_files,
         revision,
-        // TODO(crbug.com/427084604): Currently all packages are rolled manually.
-        // Set to `UpdateMechanism::Autoroll` when automatic rolls are supported.
-        update_mechanism: UpdateMechanism::Manual,
+        // All Rust dependencies are granted a shared temporary exemption for
+        // autorolling, because while they are manually rolled, they are
+        // well managed.
+        update_mechanism: "Manual (https://crbug.com/449898466)".to_string(),
     };
 
     Ok((crate_build_dir, readme))
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec
index 72cad6c..3e1ccfc 100644
--- a/tools/gritsettings/resource_ids.spec
+++ b/tools/gritsettings/resource_ids.spec
@@ -586,6 +586,10 @@
     "META": {"sizes": {"includes": [20]}},
     "includes": [4660],
   },
+   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/reload_button/resources.grd": {
+    "META": {"sizes": {"includes": [10]}},
+    "includes": [4670],
+  },
   "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/sandbox_internals/resources.grd": {
     "META": {"sizes": {"includes": [5],}},
     "includes": [4680],
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index f30a3de..0d82c9a 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -2606,6 +2606,7 @@
   <int value="49" label="Enter Picture in Picture"/>
   <int value="50" label="Exit Picture in Picture"/>
   <int value="51" label="Open in Incognito window"/>
+  <int value="52" label="View page source"/>
 </enum>
 
 <!-- LINT.ThenChange(//chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java:ContextMenuUma.Action) -->
@@ -16368,6 +16369,7 @@
       label="UnifiedPasswordManagerLocalPasswordsAndroidAccessLossWarning:disabled"/>
   <int value="773919225" label="disable-office-editing-component-extension"/>
   <int value="773952982" label="ReduceIPAddressChangeNotification:disabled"/>
+  <int value="774417826" label="VidsAppPreinstall:enabled"/>
   <int value="775075949" label="ImeInputLogicHmm:enabled"/>
   <int value="775148009" label="OsSettingsDeepLinking:disabled"/>
   <int value="775373286" label="TabModelInitFixes:enabled"/>
@@ -19146,6 +19148,7 @@
   <int value="1764618580" label="MojoLinuxChannelSharedMem:disabled"/>
   <int value="1765184717"
       label="HighlightManagedPrefDisclaimerAndroid:disabled"/>
+  <int value="1765591001" label="VidsAppPreinstall:disabled"/>
   <int value="1766048620" label="FedCmError:enabled"/>
   <int value="1766676896" label="affiliation-based-matching:disabled"/>
   <int value="1767218791" label="TouchDragAndContextMenu:enabled"/>
diff --git a/tools/metrics/histograms/metadata/android/enums.xml b/tools/metrics/histograms/metadata/android/enums.xml
index c183faf..fc87f016 100644
--- a/tools/metrics/histograms/metadata/android/enums.xml
+++ b/tools/metrics/histograms/metadata/android/enums.xml
@@ -825,7 +825,7 @@
 
 <enum name="BackupNavbarInsetsSource">
   <int value="0" label="None"/>
-  <int value="1" label="Tappable Element"/>
+  <int value="1" label="Tappable Element (Deprecated)"/>
   <int value="2" label="Mandatory system gestures"/>
   <int value="3" label="Filtered explicitly disabled"/>
   <int value="4" label="Filtered weaker signals"/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 92f0628..9fbbf0d8 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -1812,31 +1812,10 @@
   <summary>
     Records the duration in ms of drag process when drop happend inside
     ContentView containing web contents, regardless DragEvent#getResult. Does
-    not capture drag events that end outside the ContentView (Use
-    Android.DragDrop.FromWebContent.Duration instead). Android only.
+    not capture drag events that end outside the ContentView. Android only.
   </summary>
 </histogram>
 
-<histogram name="Android.DragDrop.FromWebContent.Duration.{DropResult}"
-    units="ms" expires_after="2025-09-14">
-  <owner>wenyufu@chromium.org</owner>
-  <owner>clank-large-form-factors@google.com</owner>
-  <summary>
-    Records the duration in ms of drag process when {DropResult}. Recorded for
-    the drag process starts from the web content, and drop happens outside of
-    the web content. Does not capture drag events that end inside the
-    ContentView containing web contents. Recorded when such a drag event ends.
-    Android only.
-
-    For more information regarding drag results, see:
-    https://developer.android.com/reference/android/view/DragEvent#getResult()
-  </summary>
-  <token key="DropResult">
-    <variant name="Canceled" summary="DragEvent#getResult() returns false."/>
-    <variant name="Success" summary="DragEvent#getResult() returns true."/>
-  </token>
-</histogram>
-
 <histogram name="Android.DragDrop.FromWebContent.TargetType"
     enum="AndroidDragTargetType" expires_after="2026-03-01">
   <owner>wenyufu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 02693fd..f6bec4f 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -5441,6 +5441,17 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.SafariImport.Import.TapBackOnStage"
+    enum="SafariDataImportStage" expires_after="2026-03-29">
+  <owner>ginnyhuang@chromium.org</owner>
+  <owner>bling-pandamonium@google.com</owner>
+  <summary>
+    Logs the import stage when the user taps the &quot;back&quot; button import
+    screen. Should only be applicable for &quot;not started&quot; and
+    &quot;ready to import&quot; stages.
+  </summary>
+</histogram>
+
 <histogram name="IOS.SafeBrowsing.Enhanced.Infobar.Interaction"
     enum="IOSEnhancedSafeBrowseringInfobarInteraction"
     expires_after="2026-06-26">
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 286e158..ed914ec 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -8279,13 +8279,32 @@
     expires_after="2026-02-09">
   <owner>yoichio@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
+  <improvement direction="LOWER_IS_BETTER"/>
   <summary>
     Records the proportion of writes when URLLoader was blocked by
-    MOJO_RESULT_SHOULD_WAIT where the renderer process seems to be busy. Lower
-    is better. Logged every time a URLLoader completes a load.
+    MOJO_RESULT_SHOULD_WAIT where the renderer process seems to be busy. Logged
+    every time a URLLoader completes a load.
   </summary>
 </histogram>
 
+<histogram
+    name="Net.URLLoader.SlopBucket.ProportionOfWritesBlockedByMojo.{CacheEntryStatus}"
+    units="%" expires_after="2026-02-09">
+  <owner>yoichio@chromium.org</owner>
+  <owner>chrome-loading@google.com</owner>
+  <improvement direction="LOWER_IS_BETTER"/>
+  <summary>
+    Records the proportion of writes when URLLoader was blocked by
+    MOJO_RESULT_SHOULD_WAIT where the renderer process seems to be busy. Logged
+    every time a URLLoader completes a load and only when SlopBucket is actually
+    used and response cache type is {CacheEntryStatus}.
+  </summary>
+  <token key="CacheEntryStatus">
+    <variant name="All"/>
+    <variant name="NoCache"/>
+  </token>
+</histogram>
+
 <histogram name="Net.URLLoaderThrottle.OnReceiveResponseTime" units="ms"
     expires_after="2026-03-01">
   <owner>nidhijaju@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 788ee65..f147f35 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -1278,6 +1278,9 @@
     <variant name="HST" summary="to reach the head chunk start"/>
     <variant name="SCT"
         summary="from the server response time to receive the body chunk"/>
+    <variant name="SGL"
+        summary="from the previous navigation to the reload that triggers
+                 this navigation"/>
     <variant name="SRT"
         summary="from the navigation start to receive the HTTP headers"/>
     <variant name="TimeBetweenHCTAndSCT"
@@ -1614,6 +1617,8 @@
   </summary>
   <token key="MileStone">
     <variant name="AFTEnd2" summary="AFT end event is sent"/>
+    <variant name="AFTEndWithPreNavigationLatency"
+        summary="AFT end event is sent with pre-navigation latency"/>
     <variant name="AFTStart2" summary="AFT start event is sent"/>
     <variant name="BodyChunkEnd2"
         summary="end of the header chunk start event is sent"/>
diff --git a/tools/metrics/histograms/metadata/startup/enums.xml b/tools/metrics/histograms/metadata/startup/enums.xml
index 268a07e..7494e11 100644
--- a/tools/metrics/histograms/metadata/startup/enums.xml
+++ b/tools/metrics/histograms/metadata/startup/enums.xml
@@ -113,6 +113,8 @@
   <int value="3" label="Broadcast Receiver"/>
 </enum>
 
+<!-- LINT.IfChange(StartupTemperature) -->
+
 <enum name="StartupTemperature">
   <int value="0" label="Cold startup (mostly hard faults)"/>
   <int value="1" label="Warm startup (nearly no hard faults)"/>
@@ -120,6 +122,8 @@
   <int value="3" label="Unable to determine the startup temperature"/>
 </enum>
 
+<!-- LINT.ThenChange(//components/startup_metric_utils/browser/startup_metric_utils.h:StartupTemperature) -->
+
 </enums>
 
 </histogram-configuration>
diff --git a/tools/metrics/histograms/metadata/ui/enums.xml b/tools/metrics/histograms/metadata/ui/enums.xml
index 7483647..0515985 100644
--- a/tools/metrics/histograms/metadata/ui/enums.xml
+++ b/tools/metrics/histograms/metadata/ui/enums.xml
@@ -624,6 +624,7 @@
   <int value="-1949142440" label="chrome://smb-credentials-dialog/"/>
   <int value="-1941995226" label="chrome://attribution-internals/"/>
   <int value="-1911971715" label="chrome://history/"/>
+  <int value="-1905481895" label="chrome://reload-button.top-chrome/"/>
   <int value="-1899361569" label="chrome-untrusted://eche-app/"/>
   <int value="-1887206190" label="chrome://nfc-debug/"/>
   <int value="-1877210733" label="chrome-untrusted://privacy-sandbox-dialog/"/>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index d840e63..54671fb 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v52.0/linux-arm64/trace_processor_shell"
         },
         "win": {
-            "hash": "6fdad3f95d3c19e7b9fa7c5e968f9cc3063fad94",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/eced455f5d17079fef42f07fc82fa37fcf17c338/trace_processor_shell.exe"
+            "hash": "6f322c5ad508809f050144220c0b0ca2c81aa3a6",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/d7ea394300667faed7b239e087a51447586a3132/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "46d798c1864490cbb2ee053d6eda436184470e69",
@@ -21,8 +21,8 @@
             "full_remote_path": "perfetto-luci-artifacts/ebf44e57a3b734c5281bdff53d9945805486004e/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "bfb880cc4d2608b1a324b2169d790d9b88e256da",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/11a3d5fb3890853111293ec0991ebff03b28a4f6/trace_processor_shell"
+            "hash": "a1ede3006d8e33c6c0533c36a1a66106549b0484",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/d7ea394300667faed7b239e087a51447586a3132/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/accessibility/accessibility_features.cc b/ui/accessibility/accessibility_features.cc
index 0377c03..f4a6867 100644
--- a/ui/accessibility/accessibility_features.cc
+++ b/ui/accessibility/accessibility_features.cc
@@ -399,6 +399,11 @@
       ::features::kDataCollectionModeForScreen2x);
 }
 
+BASE_FEATURE(kImmersiveReadingMode, base::FEATURE_DISABLED_BY_DEFAULT);
+bool IsImmersiveReadingModeEnabled() {
+  return base::FeatureList::IsEnabled(::features::kImmersiveReadingMode);
+}
+
 BASE_FEATURE(kMainNodeAnnotations, base::FEATURE_DISABLED_BY_DEFAULT);
 bool IsMainNodeAnnotationsEnabled() {
   return base::FeatureList::IsEnabled(::features::kMainNodeAnnotations);
diff --git a/ui/accessibility/accessibility_features.h b/ui/accessibility/accessibility_features.h
index e1011b0..15f37f3 100644
--- a/ui/accessibility/accessibility_features.h
+++ b/ui/accessibility/accessibility_features.h
@@ -316,6 +316,10 @@
 AX_BASE_EXPORT BASE_DECLARE_FEATURE(kDataCollectionModeForScreen2x);
 AX_BASE_EXPORT bool IsDataCollectionModeForScreen2xEnabled();
 
+// Enable Immersive Mode for Read Anything.
+AX_BASE_EXPORT BASE_DECLARE_FEATURE(kImmersiveReadingMode);
+AX_BASE_EXPORT bool IsImmersiveReadingModeEnabled();
+
 // Identify and annotate the main node of the AXTree where one was not already
 // provided.
 AX_BASE_EXPORT BASE_DECLARE_FEATURE(kMainNodeAnnotations);
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn
index 2a4ddd0b..4811910f 100644
--- a/ui/android/BUILD.gn
+++ b/ui/android/BUILD.gn
@@ -565,6 +565,7 @@
     "java/src/org/chromium/ui/widget/ViewLookupCachingFrameLayout.java",
     "java/src/org/chromium/ui/widget/ViewRectProvider.java",
     "java/src/org/chromium/ui/widget/ViewRectUpdater.java",
+    "java/src/org/chromium/ui/widget/WindowBoundsChangeDetector.java",
     "java/src/org/chromium/ui/xr/scenecore/XrSceneCoreSessionInitializer.java",
     "java/src/org/chromium/ui/xr/scenecore/XrSceneCoreSessionManager.java",
   ]
diff --git a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
index 66d2d9b..b422fb1 100644
--- a/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
+++ b/ui/android/java/src/org/chromium/ui/dragdrop/DragAndDropDelegateImpl.java
@@ -437,8 +437,6 @@
         // Only record metrics when drop does not happen for ContentView.
         if (!mIsDropOnView) {
             assert mDragStartSystemElapsedTime > 0;
-            long dragDuration = SystemClock.elapsedRealtime() - mDragStartSystemElapsedTime;
-            recordDragDurationAndResult(dragDuration, dragResult);
             recordDragTargetType(mDragTargetType);
         }
         // Allow drop into ContentView when files are supported by clank.
@@ -486,10 +484,4 @@
         RecordHistogram.recordEnumeratedHistogram(
                 "Android.DragDrop.FromWebContent.TargetType", type, DragTargetType.NUM_ENTRIES);
     }
-
-    private void recordDragDurationAndResult(long duration, boolean result) {
-        String histogramPrefix = "Android.DragDrop.FromWebContent.Duration.";
-        String suffix = result ? "Success" : "Canceled";
-        RecordHistogram.deprecatedRecordMediumTimesHistogram(histogramPrefix + suffix, duration);
-    }
 }
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java
index 6501b39..c2697bec 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java
@@ -132,6 +132,11 @@
         }
     }
 
+    /** Returns whether the popup menu is currently showing. */
+    public boolean isMenuShowing() {
+        return mPopupMenus.size() > 0;
+    }
+
     /** Shows a popupWindow built by ListMenuButton */
     public void showMenu() {
         if (!mView.isAttachedToWindow()) return;
@@ -182,6 +187,7 @@
                                 new ColorDrawable(Color.TRANSPARENT),
                                 () -> contentView,
                                 mDelegate.getRectProvider(mView))
+                        .setDismissOnScreenSizeChange(true)
                         .setVerticalOverlapAnchor(mMenuVerticalOverlapAnchor)
                         .setHorizontalOverlapAnchor(mMenuHorizontalOverlapAnchor)
                         .setMaxWidth(mMenuMaxWidth)
diff --git a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
index 2a9adcfa..e1830fb 100644
--- a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
@@ -243,6 +243,8 @@
 
     private @StyleRes int mAnimationStyleId;
     private boolean mAnimateFromAnchor;
+    private boolean mDismissOnScreenSizeChange;
+    private @Nullable WindowBoundsChangeDetector mWindowBoundsChangeDetector;
 
     /** A builder for {@link AnchoredPopupWindow} instances. */
     public static class Builder {
@@ -270,6 +272,7 @@
         private int mPreferredHorizontalOrientation = HorizontalOrientation.MAX_AVAILABLE_SPACE;
 
         private boolean mDismissOnTouchInteraction;
+        private boolean mDismissOnScreenSizeChange;
         private boolean mVerticalOverlapAnchor;
         private boolean mHorizontalOverlapAnchor;
         private boolean mUpdateOrientationOnChange;
@@ -417,6 +420,14 @@
         }
 
         /**
+         * @param dismiss Whether or not to dismiss this popup when the screen size changes.
+         */
+        public Builder setDismissOnScreenSizeChange(boolean dismiss) {
+            mDismissOnScreenSizeChange = dismiss;
+            return this;
+        }
+
+        /**
          * @param overlap Whether the popup should vertically overlap the anchor.
          */
         public Builder setVerticalOverlapAnchor(boolean overlap) {
@@ -538,6 +549,7 @@
         setPreferredVerticalOrientation(builder.mPreferredVerticalOrientation);
         setPreferredHorizontalOrientation(builder.mPreferredHorizontalOrientation);
         setDismissOnTouchInteraction(builder.mDismissOnTouchInteraction);
+        setDismissOnScreenSizeChange(builder.mDismissOnScreenSizeChange);
         setVerticalOverlapAnchor(builder.mVerticalOverlapAnchor);
         setHorizontalOverlapAnchor(builder.mHorizontalOverlapAnchor);
         setUpdateOrientationOnChange(builder.mUpdateOrientationOnChange);
@@ -665,6 +677,10 @@
     public void show() {
         if (mPopupWindow.isShowing()) return;
 
+        if (mDismissOnScreenSizeChange) {
+            mWindowBoundsChangeDetector = new WindowBoundsChangeDetector(mRootView, this::dismiss);
+        }
+
         mRectProvider.startObserving(this);
         mViewportRectProvider.startObserving(this);
 
@@ -678,6 +694,10 @@
      * @see PopupWindow#dismiss()
      */
     public void dismiss() {
+        if (mWindowBoundsChangeDetector != null) {
+            mWindowBoundsChangeDetector.detach();
+            mWindowBoundsChangeDetector = null;
+        }
         mPopupWindow.dismiss();
     }
 
@@ -744,6 +764,15 @@
     }
 
     /**
+     * @param dismiss Whether or not to dismiss this popup when the screen size changes.
+     * @deprecated Use the {@link Builder} to set this value during construction.
+     */
+    @Deprecated
+    public void setDismissOnScreenSizeChange(boolean dismiss) {
+        mDismissOnScreenSizeChange = dismiss;
+    }
+
+    /**
      * If set to true, popup will be notified when an outside touch happens. It is not the
      * equivalent of closing the popup on all touch events. The user can still interact with the
      * popup by sending inside touch events. If set to false, the popup won't be notified about the
diff --git a/ui/android/java/src/org/chromium/ui/widget/WindowBoundsChangeDetector.java b/ui/android/java/src/org/chromium/ui/widget/WindowBoundsChangeDetector.java
new file mode 100644
index 0000000..a04f00b8
--- /dev/null
+++ b/ui/android/java/src/org/chromium/ui/widget/WindowBoundsChangeDetector.java
@@ -0,0 +1,55 @@
+// Copyright 2025 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.ui.widget;
+
+import android.graphics.Rect;
+import android.view.View;
+
+import org.chromium.build.annotations.NullMarked;
+
+/** A utility class to detect changes in a view's bounds. */
+@NullMarked
+public class WindowBoundsChangeDetector implements View.OnLayoutChangeListener {
+    private final View mView;
+    private final Runnable mOnBoundsChangedCallback;
+    private final Rect mCachedBounds = new Rect();
+
+    /**
+     * Constructs a new {@link WindowBoundsChangeDetector}.
+     *
+     * @param view The view to observe for layout changes.
+     * @param onBoundsChangedCallback The callback to run when the view's bounds change.
+     */
+    public WindowBoundsChangeDetector(View view, Runnable onBoundsChangedCallback) {
+        mView = view;
+        mOnBoundsChangedCallback = onBoundsChangedCallback;
+        mView.addOnLayoutChangeListener(this);
+        mCachedBounds.set(0, 0, view.getWidth(), view.getHeight());
+    }
+
+    @Override
+    public void onLayoutChange(
+            View v,
+            int left,
+            int top,
+            int right,
+            int bottom,
+            int oldLeft,
+            int oldTop,
+            int oldRight,
+            int oldBottom) {
+        int width = right - left;
+        int height = bottom - top;
+        if (mCachedBounds.width() != width || mCachedBounds.height() != height) {
+            mCachedBounds.set(0, 0, width, height);
+            mOnBoundsChangedCallback.run();
+        }
+    }
+
+    /** Stops observing the view for layout changes. */
+    public void detach() {
+        mView.removeOnLayoutChangeListener(this);
+    }
+}
diff --git a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
index 2c79c42..73c9c95 100644
--- a/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
+++ b/ui/android/junit/src/org/chromium/ui/dragdrop/DragAndDropDelegateImplUnitTest.java
@@ -700,11 +700,6 @@
     }
 
     private void assertDragOutsideWebContentHistogramsRecorded(boolean dropResult) {
-        // Verify drop outside metrics recorded.
-        final String histogram =
-                "Android.DragDrop.FromWebContent.Duration." + (dropResult ? "Success" : "Canceled");
-        assertHistogramRecorded(histogram, true, "Drop outside of web content.");
-
         // Verify drop inside metrics not recorded.
         assertHistogramRecorded(
                 "Android.DragDrop.FromWebContent.DropInWebContent.Duration",
@@ -718,16 +713,6 @@
                 "Android.DragDrop.FromWebContent.DropInWebContent.Duration",
                 true,
                 "Drop inside web content.");
-
-        // Verify drop outside metrics not recorded.
-        assertHistogramRecorded(
-                "Android.DragDrop.FromWebContent.Duration.Success",
-                false,
-                "Should not recorded when drop inside web content.");
-        assertHistogramRecorded(
-                "Android.DragDrop.FromWebContent.Duration.Canceled",
-                false,
-                "Should not recorded when drop inside web content.");
     }
 
     private void assertHistogramRecorded(String histogram, boolean recorded, String reason) {
diff --git a/ui/display/manager/display_change_observer_unittest.cc b/ui/display/manager/display_change_observer_unittest.cc
index 8417818..ce62c37 100644
--- a/ui/display/manager/display_change_observer_unittest.cc
+++ b/ui/display/manager/display_change_observer_unittest.cc
@@ -495,9 +495,8 @@
   const auto display_color_spaces = display_info.display_color_spaces();
   EXPECT_FALSE(display_color_spaces.SupportsHDR());
 
-  EXPECT_EQ(
-      DisplaySnapshot::PrimaryFormat(),
-      display_color_spaces.GetOutputBufferFormat(gfx::ContentColorUsage::kSRGB,
+  EXPECT_EQ(DisplaySnapshot::PrimarySharedImageFormat(),
+            display_color_spaces.GetOutputFormat(gfx::ContentColorUsage::kSRGB,
                                                  /*needs_alpha=*/true));
 
   const auto color_space = display_color_spaces.GetRasterAndCompositeColorSpace(
@@ -528,9 +527,8 @@
   const auto display_color_spaces = display_info.display_color_spaces();
   EXPECT_FALSE(display_color_spaces.SupportsHDR());
 
-  EXPECT_EQ(
-      DisplaySnapshot::PrimaryFormat(),
-      display_color_spaces.GetOutputBufferFormat(gfx::ContentColorUsage::kSRGB,
+  EXPECT_EQ(DisplaySnapshot::PrimarySharedImageFormat(),
+            display_color_spaces.GetOutputFormat(gfx::ContentColorUsage::kSRGB,
                                                  /*needs_alpha=*/true));
 
   const auto color_space = display_color_spaces.GetRasterAndCompositeColorSpace(
@@ -561,9 +559,8 @@
   const auto display_color_spaces = display_info.display_color_spaces();
   EXPECT_FALSE(display_color_spaces.SupportsHDR());
 
-  EXPECT_EQ(
-      DisplaySnapshot::PrimaryFormat(),
-      display_color_spaces.GetOutputBufferFormat(gfx::ContentColorUsage::kSRGB,
+  EXPECT_EQ(DisplaySnapshot::PrimarySharedImageFormat(),
+            display_color_spaces.GetOutputFormat(gfx::ContentColorUsage::kSRGB,
                                                  /*needs_alpha=*/true));
 
   const auto color_space = display_color_spaces.GetRasterAndCompositeColorSpace(
@@ -609,17 +606,15 @@
   EXPECT_TRUE(display_color_spaces.SupportsHDR());
 
   // Ensure that all spaces be HDR10, and have headroom of 3x (609/203).
-  EXPECT_EQ(
-      gfx::BufferFormat::RGBA_1010102,
-      display_color_spaces.GetOutputBufferFormat(gfx::ContentColorUsage::kSRGB,
+  EXPECT_EQ(viz::SinglePlaneFormat::kRGBA_1010102,
+            display_color_spaces.GetOutputFormat(gfx::ContentColorUsage::kSRGB,
                                                  /*needs_alpha=*/true));
   EXPECT_EQ(
       gfx::ColorSpace::CreateHDR10(),
       display_color_spaces.GetOutputColorSpace(gfx::ContentColorUsage::kSRGB,
                                                /*needs_alpha=*/true));
-  EXPECT_EQ(
-      gfx::BufferFormat::RGBA_1010102,
-      display_color_spaces.GetOutputBufferFormat(gfx::ContentColorUsage::kHDR,
+  EXPECT_EQ(viz::SinglePlaneFormat::kRGBA_1010102,
+            display_color_spaces.GetOutputFormat(gfx::ContentColorUsage::kHDR,
                                                  /*needs_alpha=*/true));
   EXPECT_EQ(
       gfx::ColorSpace::CreateHDR10(),
diff --git a/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/EdgeToEdgeManager.java b/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/EdgeToEdgeManager.java
index ca1374d..f500457f 100644
--- a/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/EdgeToEdgeManager.java
+++ b/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/EdgeToEdgeManager.java
@@ -59,7 +59,7 @@
     })
     public @interface BackupNavbarInsetsSource {
         int NO_APPLICABLE_BACKUP = 0;
-        int TAPPABLE_ELEMENT = 1;
+        @Deprecated int TAPPABLE_ELEMENT = 1;
         int MANDATORY_SYSTEM_GESTURES = 2;
         int FILTERED_EXPLICITLY_DISABLED = 3;
         int FILTERED_WEAKER_SIGNALS = 4;
@@ -173,7 +173,6 @@
             WindowInsetsCompat windowInsets,
             @BackupNavbarInsetsCallSite String callSite,
             EdgeToEdgeFieldTrial useBackupNavbarInsetsFieldTrial,
-            boolean canUseTappableElementInsets,
             boolean canUseMandatoryGesturesInsets) {
         if (!useBackupNavbarInsetsFieldTrial.isEnabledForManufacturerVersion()) {
             recordBackupNavbarInsetsHistogram(
@@ -181,22 +180,7 @@
             return null;
         }
 
-        // Check clearer signals, like the tappable element, first.
-
-        Insets tappableInsets = windowInsets.getInsets(WindowInsetsCompat.Type.tappableElement());
-        // A single non-zero tappable inset is most likely the navigation bar, even if the
-        // navigation bar insets are missing for some reason. Tappable elements are strong
-        // signals for the presence of tappable system bars, and are used to distinguish between
-        // gesture and tappable navigation, and thus should be a reliable signal for detecting a
-        // navigation bar, even if the navigation bar inset is missing for some reason.
-        // The top inset should be ignored, as that would correspond to the status bar.
-        if (WindowInsetsUtils.hasOneNonZeroInsetExcludingTop(tappableInsets)
-                && canUseTappableElementInsets) {
-            recordBackupNavbarInsetsHistogram(callSite, BackupNavbarInsetsSource.TAPPABLE_ELEMENT);
-            return Insets.of(tappableInsets.left, 0, tappableInsets.right, tappableInsets.bottom);
-        }
-
-        // Restrict less clear signals, like the system gestures, if non-zero navigation bar insets
+        // Restrict weak signals, like the system gestures, if non-zero navigation bar insets
         // have previously been seen during the session for this Activity / window.
         if (hasSeenNonZeroNavigationBarInsets) {
             recordBackupNavbarInsetsHistogram(
diff --git a/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutCoordinator.java b/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutCoordinator.java
index 83359b0..026b731 100644
--- a/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutCoordinator.java
+++ b/ui/edge_to_edge/android/java/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutCoordinator.java
@@ -51,7 +51,6 @@
 
     private final boolean mUseBackupNavbarInsetsEnabled;
     private final @Nullable EdgeToEdgeFieldTrial mUseBackupNavbarInsetsFieldTrial;
-    private final boolean mCanUseTappableElementInsets;
     private final boolean mCanUseMandatoryGesturesInsets;
 
     /**
@@ -65,8 +64,6 @@
      *     seem to be missing.
      * @param useBackupNavbarInsetsFieldTrial The EdgeToEdgeFieldTrial to use to verify if backup
      *     insets are allowed on devices by the current manufacturer.
-     * @param canUseTappableElementInsets Whether tappable element insets can be used as backup
-     *     navbar insets.
      * @param canUseMandatoryGesturesInsets Whether mandatory system gesture insets can be used as
      *     backup navbar insets.
      */
@@ -75,13 +72,11 @@
             @Nullable InsetObserver insetObserver,
             boolean useBackupNavbarInsetsEnabled,
             @Nullable EdgeToEdgeFieldTrial useBackupNavbarInsetsFieldTrial,
-            boolean canUseTappableElementInsets,
             boolean canUseMandatoryGesturesInsets) {
         mContext = context;
         mInsetObserver = insetObserver;
         mUseBackupNavbarInsetsEnabled = useBackupNavbarInsetsEnabled;
         mUseBackupNavbarInsetsFieldTrial = useBackupNavbarInsetsFieldTrial;
-        mCanUseTappableElementInsets = canUseTappableElementInsets;
         mCanUseMandatoryGesturesInsets = canUseMandatoryGesturesInsets;
     }
 
@@ -101,7 +96,6 @@
                 insetObserver,
                 /* useBackupNavbarInsetsEnabled= */ false,
                 /* useBackupNavbarInsetsFieldTrial= */ null,
-                /* canUseTappableElementInsets= */ false,
                 /* canUseMandatoryGesturesInsets= */ false);
     }
 
@@ -202,31 +196,38 @@
 
     private Insets getNavigationBarInsets(WindowInsetsCompat windowInsets) {
         Insets navBarInsets = windowInsets.getInsets(Type.navigationBars());
+        Insets tappableInsets = windowInsets.getInsets(WindowInsetsCompat.Type.tappableElement());
+        Insets nonTopTappableInsets =
+                Insets.of(tappableInsets.left, 0, tappableInsets.right, tappableInsets.bottom);
+        Insets navBarAndTappableInsets = Insets.max(navBarInsets, nonTopTappableInsets);
 
-        if (!mUseBackupNavbarInsetsEnabled) return navBarInsets;
-        if (mInsetObserver == null || mUseBackupNavbarInsetsFieldTrial == null) return navBarInsets;
+        if (!mUseBackupNavbarInsetsEnabled) return navBarAndTappableInsets;
+        if (mInsetObserver == null || mUseBackupNavbarInsetsFieldTrial == null) {
+            return navBarAndTappableInsets;
+        }
 
-        if (navBarInsets.left == 0 && navBarInsets.right == 0 && navBarInsets.bottom == 0) {
+        if (navBarAndTappableInsets.left == 0
+                && navBarAndTappableInsets.right == 0
+                && navBarAndTappableInsets.bottom == 0) {
             @Nullable Insets backupNavbarInsets =
                     EdgeToEdgeManager.getBackupNavbarInsets(
                             mInsetObserver.hasSeenNonZeroNavigationBarInsets(),
                             windowInsets,
                             BackupNavbarInsetsCallSite.EDGE_TO_EDGE_LAYOUT,
                             mUseBackupNavbarInsetsFieldTrial,
-                            mCanUseTappableElementInsets,
                             mCanUseMandatoryGesturesInsets);
             // If applicable, apply backup navbar insets to the left, right, and bottom (not the
             // top, as that's always the status bar).
             if (backupNavbarInsets != null) {
-                navBarInsets =
+                navBarAndTappableInsets =
                         Insets.of(
                                 backupNavbarInsets.left,
-                                navBarInsets.top,
+                                navBarAndTappableInsets.top,
                                 backupNavbarInsets.right,
                                 backupNavbarInsets.bottom);
             }
         }
-        return navBarInsets;
+        return navBarAndTappableInsets;
     }
 
     /** Returns the edge-to-edge layout view. */
diff --git a/ui/edge_to_edge/android/javatests/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutViewTest.java b/ui/edge_to_edge/android/javatests/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutViewTest.java
index 0cbff58e7..550ee978 100644
--- a/ui/edge_to_edge/android/javatests/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutViewTest.java
+++ b/ui/edge_to_edge/android/javatests/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutViewTest.java
@@ -99,7 +99,6 @@
                                     null,
                                     /* useBackupNavbarInsetsEnabled= */ true,
                                     /* useBackupNavbarInsetsFieldTrial= */ mUseBackupNavbarInsetsFieldTrial,
-                                    /* canUseTappableElementInsets= */ true,
                                     /* canUseMandatoryGesturesInsets= */ true);
 
                     mContentView = new FrameLayout(sActivity, null);
diff --git a/ui/edge_to_edge/android/junit/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutUnitTest.java b/ui/edge_to_edge/android/junit/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutUnitTest.java
index 19904c8..51c1d90 100644
--- a/ui/edge_to_edge/android/junit/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutUnitTest.java
+++ b/ui/edge_to_edge/android/junit/src/org/chromium/ui/edge_to_edge/layout/EdgeToEdgeLayoutUnitTest.java
@@ -273,7 +273,7 @@
                 new WindowInsetsCompat.Builder()
                         .setInsets(STATUS_BARS, Insets.of(0, STATUS_BAR_SIZE, 0, 0))
                         .setInsets(NAVIGATION_BARS, Insets.of(0, 0, 0, 0))
-                        .setInsets(TAPPABLE_ELEMENT, Insets.of(0, 0, 0, NAV_BAR_SIZE))
+                        .setInsets(TAPPABLE_ELEMENT, Insets.of(0, 0, 0, 0))
                         .setInsets(
                                 MANDATORY_SYSTEM_GESTURES,
                                 Insets.of(0, STATUS_BAR_SIZE, 0, NAV_BAR_SIZE))
@@ -1023,7 +1023,6 @@
                         insetObserver,
                         /* useBackupNavbarInsetsEnabled= */ useBackupNavbarInsets,
                         /* useBackupNavbarInsetsFieldTrial= */ mUseBackupNavbarFieldTrial,
-                        /* canUseTappableElementInsets= */ true,
                         /* canUseMandatoryGesturesInsets= */ true);
         mEdgeToEdgeLayout =
                 (EdgeToEdgeBaseLayout)
diff --git a/ui/gfx/display_color_spaces.cc b/ui/gfx/display_color_spaces.cc
index b26d6b47..ce73340 100644
--- a/ui/gfx/display_color_spaces.cc
+++ b/ui/gfx/display_color_spaces.cc
@@ -113,10 +113,11 @@
   return color_spaces_[GetIndex(color_usage, needs_alpha)];
 }
 
-BufferFormat DisplayColorSpaces::GetOutputBufferFormat(
+viz::SharedImageFormat DisplayColorSpaces::GetOutputFormat(
     ContentColorUsage color_usage,
     bool needs_alpha) const {
-  return buffer_formats_[GetIndex(color_usage, needs_alpha)];
+  return viz::GetSharedImageFormat(
+      buffer_formats_[GetIndex(color_usage, needs_alpha)]);
 }
 
 ColorSpace DisplayColorSpaces::GetRasterAndCompositeColorSpace(
@@ -179,7 +180,7 @@
 void DisplayColorSpaces::ToStrings(
     std::vector<std::string>* out_names,
     std::vector<gfx::ColorSpace>* out_color_spaces,
-    std::vector<gfx::BufferFormat>* out_buffer_formats) const {
+    std::vector<viz::SharedImageFormat>* out_formats) const {
   // The names of the configurations.
   std::array<const char*, kConfigCount> config_names = {
       "sRGB/no-alpha", "sRGB/alpha",   "WCG/no-alpha",
@@ -234,7 +235,7 @@
 
     // Add an entry, and continue with the interval [j, j).
     out_names->push_back(name);
-    out_buffer_formats->push_back(buffer_formats_[i]);
+    out_formats->push_back(viz::GetSharedImageFormat(buffer_formats_[i]));
     out_color_spaces->push_back(color_spaces_[i]);
     i = j;
   };
diff --git a/ui/gfx/display_color_spaces.h b/ui/gfx/display_color_spaces.h
index 847d4a7c..3f2ee89 100644
--- a/ui/gfx/display_color_spaces.h
+++ b/ui/gfx/display_color_spaces.h
@@ -78,8 +78,8 @@
   // Retrieve parameters for a specific usage and alpha.
   ColorSpace GetOutputColorSpace(ContentColorUsage color_usage,
                                  bool needs_alpha) const;
-  BufferFormat GetOutputBufferFormat(ContentColorUsage color_usage,
-                                     bool needs_alpha) const;
+  viz::SharedImageFormat GetOutputFormat(ContentColorUsage color_usage,
+                                         bool needs_alpha) const;
 
   // Set the maximum SDR luminance, in nits. This is a non-default value only
   // on Windows.
@@ -128,10 +128,10 @@
 
   // Output as a vector of strings. This is a helper function for printing in
   // about:gpu. All output vectors will be the same length. Each entry will be
-  // the configuration name, its buffer format, and its color space.
+  // the configuration name, its format, and its color space.
   void ToStrings(std::vector<std::string>* out_names,
                  std::vector<gfx::ColorSpace>* out_color_spaces,
-                 std::vector<gfx::BufferFormat>* out_buffer_formats) const;
+                 std::vector<viz::SharedImageFormat>* out_formats) const;
 
   bool operator==(const DisplayColorSpaces& other) const;
 
diff --git a/ui/gfx/geometry/transform_util_unittest.cc b/ui/gfx/geometry/transform_util_unittest.cc
index 42cdc3a9..e0ffd72d 100644
--- a/ui/gfx/geometry/transform_util_unittest.cc
+++ b/ui/gfx/geometry/transform_util_unittest.cc
@@ -157,10 +157,7 @@
   const float infinity_or_zero = std::numeric_limits<float>::has_infinity
                                      ? std::numeric_limits<float>::infinity()
                                      : 0;
-  const float denorm_min_or_zero =
-      (std::numeric_limits<float>::has_denorm == std::denorm_present)
-          ? std::numeric_limits<float>::denorm_min()
-          : 0;
+  const float denorm_min = std::numeric_limits<float>::denorm_min();
 
   const struct {
     Transform transform;
@@ -254,7 +251,7 @@
       {Transform::RowMajor(3, 0, 0, -23,
                            0, 7, 0, 31,
                            0, 0, 11, 47,
-                           0, 0, 0, denorm_min_or_zero),
+                           0, 0, 0, denorm_min),
        std::nullopt},
       // clang-format on
   };
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_action.css b/ui/webui/resources/cr_components/searchbox/searchbox_action.css
index d542be5..c3b7ad96 100644
--- a/ui/webui/resources/cr_components/searchbox/searchbox_action.css
+++ b/ui/webui/resources/cr_components/searchbox/searchbox_action.css
@@ -74,6 +74,11 @@
   width: 16px;
 }
 
+:host-context(:is(:focus, [selected])) #action-icon {
+  background-color: var(--color-searchbox-results-action-chip-icon-selected,
+      var(--color-searchbox-results-action-chip-icon));
+}
+
 #text {
   overflow: hidden;
   padding-inline-start: 8px;
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_icon.css b/ui/webui/resources/cr_components/searchbox/searchbox_icon.css
index d6d7ac6..46b1aa4 100644
--- a/ui/webui/resources/cr_components/searchbox/searchbox_icon.css
+++ b/ui/webui/resources/cr_components/searchbox/searchbox_icon.css
@@ -101,6 +101,11 @@
   background-color: var(--color-searchbox-answer-icon-foreground);
 }
 
+:host([has-icon-container-background][is-starter-pack]:not([in-searchbox])) #icon {
+  background-color: var(--color-searchbox-results-starter-pack-icon,
+      var(--color-searchbox-answer-icon-foreground));
+}
+
 #iconImg {
   height: var(--cr-searchbox-results-search-icon-size,16px);
   width: var(--cr-searchbox-results-search-icon-size,16px);
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_icon.ts b/ui/webui/resources/cr_components/searchbox/searchbox_icon.ts
index 56c8de1..68a4fa1 100644
--- a/ui/webui/resources/cr_components/searchbox/searchbox_icon.ts
+++ b/ui/webui/resources/cr_components/searchbox/searchbox_icon.ts
@@ -85,6 +85,14 @@
       },
 
       /**
+       * Whether icon belongs to a starter pack match.
+       */
+      isStarterPack: {
+        type: Boolean,
+        reflect: true,
+      },
+
+      /**
        * Whether suggestion answer is of answer type weather. Weather answers
        * don't have the same background as other suggestion answers.
        */
@@ -151,6 +159,7 @@
   accessor hasIconContainerBackground: boolean = false;
   accessor inSearchbox: boolean = false;
   accessor isAnswer: boolean = false;
+  accessor isStarterPack = false;
   accessor isWeatherAnswer: boolean = false;
   accessor isEnterpriseSearchAggregatorPeopleType: boolean = false;
   accessor maskImage: string = '';
@@ -174,6 +183,7 @@
       this.isAnswer = this.computeIsAnswer_();
       this.isEnterpriseSearchAggregatorPeopleType =
           this.computeIsEnterpriseSearchAggregatorPeopleType_();
+      this.isStarterPack = this.computeIsStarterPack_();
       this.isWeatherAnswer = this.computeIsWeatherAnswer_();
       this.maskImage = this.computeMaskImage_();
     }
@@ -390,6 +400,10 @@
     }
     return false;
   }
+
+  private computeIsStarterPack_(): boolean {
+    return this.match?.type === STARTER_PACK;
+  }
 }
 
 declare global {
diff --git a/ui/webui/resources/cr_components/searchbox/searchbox_match.css b/ui/webui/resources/cr_components/searchbox/searchbox_match.css
index 049d7748..382b058 100644
--- a/ui/webui/resources/cr_components/searchbox/searchbox_match.css
+++ b/ui/webui/resources/cr_components/searchbox/searchbox_match.css
@@ -238,12 +238,20 @@
 }
 
 #remove {
-  --cr-icon-button-fill-color:
-      var(--color-searchbox-results-icon-selected);
   display: none;
   margin-inline-end: 1px;
 }
 
+:host-context(cr-searchbox-match:-webkit-any(:focus-within, [selected])) #remove {
+  --cr-icon-button-fill-color: var(--color-searchbox-results-icon-selected);
+}
+
+
+:host-context(cr-searchbox-match:-webkit-any(:focus-within, [selected])) #remove:hover {
+  --cr-icon-button-hover-background-color:
+      var(--color-searchbox-results-button-selected-hover);
+}
+
 :host-context(.vertical) .container:hover #remove,
 :host-context(cr-searchbox-match:-webkit-any(:focus-within, [selected])):host-context(.vertical) #remove {
   display: inline-flex;
diff --git a/url/gurl.cc b/url/gurl.cc
index ee910fb..dda561c 100644
--- a/url/gurl.cc
+++ b/url/gurl.cc
@@ -105,8 +105,7 @@
     // We can't do this check on the inner_url of a filesystem URL, as
     // canonical_spec actually points to the start of the outer URL, so we'd
     // end up with infinite recursion in this constructor.
-    if (!url::FindAndCompareScheme(spec_.data(), spec_.length(),
-                                   url::kFileSystemScheme, &scheme) ||
+    if (!url::FindAndCompareScheme(spec_, url::kFileSystemScheme, &scheme) ||
         scheme.begin == parsed_.scheme.begin) {
       // We need to retain trailing whitespace on path URLs, as the |parsed_|
       // spec we originally received may legitimately contain trailing white-
diff --git a/url/url_util.cc b/url/url_util.cc
index 0042c108..e47605c 100644
--- a/url/url_util.cc
+++ b/url/url_util.cc
@@ -224,18 +224,15 @@
   return false;
 }
 
-// TODO(crbug.com/350788890): Replace `str` and `str_len` with a
-// basic_string_view or a base::span.
-template<typename CHAR>
-bool DoFindAndCompareScheme(const CHAR* str,
-                            int str_len,
+template <typename CHAR>
+bool DoFindAndCompareScheme(std::basic_string_view<CHAR> str,
                             const char* compare,
                             Component* found_scheme) {
   // Before extracting scheme, canonicalize the URL to remove any whitespace.
   // This matches the canonicalization done in DoCanonicalize function.
   STACK_UNINITIALIZED RawCanonOutputT<CHAR> whitespace_buffer;
-  std::basic_string_view<CHAR> spec = RemoveUrlWhitespace(
-      {str, base::checked_cast<size_t>(str_len)}, &whitespace_buffer, nullptr);
+  std::basic_string_view<CHAR> spec =
+      RemoveUrlWhitespace(str, &whitespace_buffer, nullptr);
 
   Component our_scheme;
   if (!ExtractScheme(spec, &our_scheme)) {
@@ -749,18 +746,16 @@
                        GetSchemeRegistry().referrer_schemes);
 }
 
-bool FindAndCompareScheme(const char* str,
-                          int str_len,
+bool FindAndCompareScheme(std::string_view str,
                           const char* compare,
                           Component* found_scheme) {
-  return DoFindAndCompareScheme(str, str_len, compare, found_scheme);
+  return DoFindAndCompareScheme(str, compare, found_scheme);
 }
 
 bool FindAndCompareScheme(std::u16string_view str,
                           const char* compare,
                           Component* found_scheme) {
-  return DoFindAndCompareScheme(str.data(), base::checked_cast<int>(str.size()),
-                                compare, found_scheme);
+  return DoFindAndCompareScheme(str, compare, found_scheme);
 }
 
 bool DomainIs(std::string_view canonical_host,
diff --git a/url/url_util.h b/url/url_util.h
index 3689cf4f..035d839 100644
--- a/url/url_util.h
+++ b/url/url_util.h
@@ -146,15 +146,16 @@
 // input (if any). The |compare| scheme must be a valid canonical scheme or
 // the result of the comparison is undefined.
 COMPONENT_EXPORT(URL)
-bool FindAndCompareScheme(const char* str,
-                          int str_len,
+bool FindAndCompareScheme(std::string_view str,
                           const char* compare,
                           Component* found_scheme);
-inline bool FindAndCompareScheme(std::string_view str,
+inline bool FindAndCompareScheme(const char* str,
+                                 int str_len,
                                  const char* compare,
                                  Component* found_scheme) {
-  return FindAndCompareScheme(str.data(), static_cast<int>(str.size()),
-                              compare, found_scheme);
+  return FindAndCompareScheme(
+      std::string_view(str, static_cast<size_t>(str_len)), compare,
+      found_scheme);
 }
 COMPONENT_EXPORT(URL)
 bool FindAndCompareScheme(std::u16string_view str,
diff --git a/url/url_util_unittest.cc b/url/url_util_unittest.cc
index 2e42d3f..a10ea12 100644
--- a/url/url_util_unittest.cc
+++ b/url/url_util_unittest.cc
@@ -90,47 +90,38 @@
 
   // Simple case where the scheme is found and matches.
   const char kStr1[] = "http://www.com/";
-  EXPECT_TRUE(FindAndCompareScheme(kStr1, static_cast<int>(strlen(kStr1)),
-                                   "http", nullptr));
-  EXPECT_TRUE(FindAndCompareScheme(
-      kStr1, static_cast<int>(strlen(kStr1)), "http", &found_scheme));
+  EXPECT_TRUE(FindAndCompareScheme(kStr1, "http", nullptr));
+  EXPECT_TRUE(FindAndCompareScheme(kStr1, "http", &found_scheme));
   EXPECT_TRUE(found_scheme == Component(0, 4));
 
   // A case where the scheme is found and doesn't match.
-  EXPECT_FALSE(FindAndCompareScheme(
-      kStr1, static_cast<int>(strlen(kStr1)), "https", &found_scheme));
+  EXPECT_FALSE(FindAndCompareScheme(kStr1, "https", &found_scheme));
   EXPECT_TRUE(found_scheme == Component(0, 4));
 
   // A case where there is no scheme.
   const char kStr2[] = "httpfoobar";
-  EXPECT_FALSE(FindAndCompareScheme(
-      kStr2, static_cast<int>(strlen(kStr2)), "http", &found_scheme));
+  EXPECT_FALSE(FindAndCompareScheme(kStr2, "http", &found_scheme));
   EXPECT_TRUE(found_scheme == Component());
 
   // When there is an empty scheme, it should match the empty scheme.
   const char kStr3[] = ":foo.com/";
-  EXPECT_TRUE(FindAndCompareScheme(
-      kStr3, static_cast<int>(strlen(kStr3)), "", &found_scheme));
+  EXPECT_TRUE(FindAndCompareScheme(kStr3, "", &found_scheme));
   EXPECT_TRUE(found_scheme == Component(0, 0));
 
   // But when there is no scheme, it should fail.
-  EXPECT_FALSE(FindAndCompareScheme("", 0, "", &found_scheme));
+  EXPECT_FALSE(FindAndCompareScheme("", "", &found_scheme));
   EXPECT_TRUE(found_scheme == Component());
 
   // When there is a whitespace char in scheme, it should canonicalize the URL
   // before comparison.
   const char whtspc_str[] = " \r\n\tjav\ra\nscri\tpt:alert(1)";
-  EXPECT_TRUE(FindAndCompareScheme(whtspc_str,
-                                   static_cast<int>(strlen(whtspc_str)),
-                                   "javascript", &found_scheme));
+  EXPECT_TRUE(FindAndCompareScheme(whtspc_str, "javascript", &found_scheme));
   EXPECT_TRUE(found_scheme == Component(1, 10));
 
   // Control characters should be stripped out on the ends, and kept in the
   // middle.
   const char ctrl_str[] = "\02jav\02scr\03ipt:alert(1)";
-  EXPECT_FALSE(FindAndCompareScheme(ctrl_str,
-                                    static_cast<int>(strlen(ctrl_str)),
-                                    "javascript", &found_scheme));
+  EXPECT_FALSE(FindAndCompareScheme(ctrl_str, "javascript", &found_scheme));
   EXPECT_TRUE(found_scheme == Component(1, 11));
 }
 
diff --git a/v8 b/v8
index 033fd2f..99022d9 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 033fd2f04cb7ff9d69cbaf0876e808186ca2dc5c
+Subproject commit 99022d9158c6e40babc442b84dc0b60ed64cd378