diff --git a/DEPS b/DEPS
index b7ce704e..6c5b2aa 100644
--- a/DEPS
+++ b/DEPS
@@ -240,7 +240,7 @@
   # luci-go CIPD package version.
   # Make sure the revision is uploaded by infra-packagers builder.
   # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console
-  'luci_go': 'git_revision:6645da847edf4e1ebcfe8cf4d860ad75e63b20cb',
+  'luci_go': 'git_revision:4305585b28910a1c5951f82f6172f1b41b9567bb',
 
   # This can be overridden, e.g. with custom_vars, to build clang from HEAD
   # instead of downloading the prebuilt pinned revision.
@@ -305,11 +305,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '96c17864244a5d24cebd6605e8895b4f414ed1f8',
+  'src_internal_revision': '954353405806383ec740f812cfd40c08c435c4a5',
   # 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': 'ce23f015d43b027ee200e6038b22c559fb459c2a',
+  'skia_revision': '1724ceaf73c4616f06582d8ef7104da6e4d4792e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -317,7 +317,7 @@
   # 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': '074eec2f148edf8fb9f1672e54cec3472d6d7a67',
+  'angle_revision': '8af6c56672bf1819bfb72c539a072e2b12964cf3',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -389,7 +389,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling fuzztest
   # and whatever else without interference from each other.
-  'fuzztest_revision': '84914079865928884331819a7952c5d66c516ce5',
+  'fuzztest_revision': 'f505c8ba2faf9806900e72aeb52fa68ade30d8b7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling domato
   # and whatever else without interference from each other.
@@ -397,7 +397,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '88892c172e1091cf6163adffd0f094fbb5c56325',
+  'devtools_frontend_revision': '719e4cbccab5277c60c67869c06d2741cd0919be',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -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': 'fd1225f5306e0f879ceed9f389e2f7d68488002c',
+  'dawn_revision': '78fff7bf05e787a29cfd37a037c2cb63a55e923a',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1190,7 +1190,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm',
-              'version': 'tRjGLESwT05Y1zcwi1zj5V-rskX2AwibUMqk3j7ytzsC',
+              'version': '1woBUXDaJKgtW-MRcyH2p76NNt0UGXIf44aNBalCT98C',
           },
       ],
       'condition': 'checkout_android',
@@ -1201,7 +1201,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': '0bETcCTRkl5my677AFjfhCnu6tv0yyCdsir05cxRKWUC',
+              'version': 'MmallF5Pshh2WIexxvaM75DSxZlxVpvq2y_npONrRpAC',
           },
       ],
       'condition': 'checkout_android',
@@ -1212,7 +1212,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/orderfiles/arm',
-              'version': 'qCdt2pmEH9jnR7DWYCeLZ1x9_VGrWiAl6zpKvY0zXrwC',
+              'version': '4fNjIzQphdYeFmZF6nVakgvA58O8fhPASwXtX2PcUAIC',
           },
       ],
       'condition': 'checkout_android',
@@ -1223,7 +1223,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/orderfiles/arm64',
-              'version': 'haaYN16zzNffsrSwqgBBU-OTJ905NzjjVNhKhXfIpBAC',
+              'version': 'nQZ9Zbj2dk4fsqFNRrdZElTYC2fIKYIPN1wYvmgRX0EC',
           },
       ],
       'condition': 'checkout_android',
@@ -1608,7 +1608,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/variations/cipd',
-        'version': '43HF-NL8EENMG2iOOo__aOFsT0UdEzzKQeBeuWukN08C',
+        'version': 'Y_geYqk7HbgSvG-xdulw1jZpH-KKBhjfmhMqjjem2UkC',
       },
     ],
     'dep_type': 'cipd',
@@ -1619,7 +1619,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'a1cdb512a2766a95f6951d17383fe33866937534',
+    '9e4d283fad19a1dcbca60502aa223a944a0b567b',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1719,7 +1719,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'j2oBRvHyF_9ZkCK_FWoqLWt3DH8JPYNvttri5JCa3csC',
+          'version': 'O3zoHHNQHsLDnn6zr5o8dT5304bMe3CZQ8-O8VOV2NMC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -1823,7 +1823,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/manifest_merger',
-               'version': '-QZQHB3DVUsl1l8AAX4iNcR7p3aFVQk6Bh4Bu9e8YfoC',
+               'version': 'UVOeU4qVAlqzi1egh2W5_YKXJDam0q7Zdmb_KBQwY5MC',
           },
       ],
       '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' + '@' + 'e8e09ca53f60e795fee64892aec3f8f3f997d362',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '3008b57e5d18ee9c92baf851dd33c61cfd6fad21',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
@@ -2924,16 +2924,16 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@103f88b8d55f294ebfb66d188b718157f410ad45',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@b197e9ddd86d6105721f0f2eb48298f0adffa4e6',
   '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',
+  'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@9268f3057354a2cb65991ba5f38b16d81e803692',
   'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@b9997dafc791634ce51f6bed7ab886ea0e600a15',
-  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@f5fad0a209a2e09eb5e622d930d5eade1a235b13',
+  'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@33d7f512583b8de44d1b6384aa1cf482f92e53e9',
   '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@c5efe5a2f1bbb905ee8e4ee0a29f62274f9ddee6',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@6f5b5a4b034768139ff4fd1d797f6955d16e0f86',
 
   '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' + '@' + '4c45016de25d27c0809ef4efcfc3165990534144',
+    Var('webrtc_git') + '/src.git' + '@' + '8799eb90b451d970ac637022ceeb9bbc3460f269',
 
   # 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.
@@ -3054,7 +3054,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-arm64',
-          'version': 'gEn7lApH-VlAwkkxnYbyKyVpLRT9NcqEse6SU0R1CD4C',
+          'version': 'yZVTeqmfUoCss6wv6VH54bs2RpmfRa-AZRVsqQNZzx0C',
         },
       ],
       'dep_type': 'cipd',
@@ -3685,7 +3685,7 @@
 
   'src/components/optimization_guide/internal': {
       'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' +
-        '257e69c2cd8457dd9d8d180c96295ad7ea650b1e',
+        '1f7cf078657b763c3ac434cfde2cfb54ee648e5e',
       'condition': 'checkout_src_internal',
   },
 
diff --git a/WATCHLISTS b/WATCHLISTS
index a6fb4b4..ed5e2ed 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -3194,8 +3194,7 @@
                         'lizeb+pa@chromium.org',
                         'bartekn+watch@chromium.org'],
     'password_manager': ['gcasto+watchlist@chromium.org',
-                         'vasilii+watchlistpasswordmanager@chromium.org',
-                        'milicau+watchlistpasswordmanager@google.com'],
+                         'vasilii+watchlistpasswordmanager@chromium.org'],
     'payments': ['slobodan+watch@chromium.org'],
     'pdf': ['pdf-reviews@chromium.org'],
     'pdf_ocr': ['kyungjunlee+watch@google.com',
diff --git a/android_webview/java/src/org/chromium/android_webview/AwSelectionDropdownMenuDelegate.java b/android_webview/java/src/org/chromium/android_webview/AwSelectionDropdownMenuDelegate.java
index ce283399..61d861e 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwSelectionDropdownMenuDelegate.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwSelectionDropdownMenuDelegate.java
@@ -219,7 +219,7 @@
         return new BasicListMenu(
                 windowContext,
                 items,
-                clickListener::onItemClick,
+                (model, view) -> clickListener.onItemClick(model),
                 /* backgroundDrawable= */ Resources.ID_NULL,
                 /* backgroundTintColor= */ Resources.ID_NULL,
                 /* bottomHairlineColor= */ null);
diff --git a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
index 1e26c9f0..490a53e 100644
--- a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
@@ -7781,6 +7781,7 @@
     method clone
     method constructor
     method formData
+    method getRetryOptions
     method json
     method text
 interface ResizeObserver
diff --git a/base/BUILD.gn b/base/BUILD.gn
index b28189b..537c542 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -1223,6 +1223,7 @@
       "android/shared_preferences/shared_preferences_manager.h",
       "android/statistics_recorder_android.cc",
       "android/sys_utils.cc",
+      "android/sys_utils.h",
       "android/task_scheduler/post_task_android.cc",
       "android/task_scheduler/post_task_android.h",
       "android/task_scheduler/task_runner_android.cc",
diff --git a/base/android/java/src/org/chromium/base/DeviceInfo.java b/base/android/java/src/org/chromium/base/DeviceInfo.java
index 34b7aef7..47366af 100644
--- a/base/android/java/src/org/chromium/base/DeviceInfo.java
+++ b/base/android/java/src/org/chromium/base/DeviceInfo.java
@@ -9,6 +9,7 @@
 import android.app.UiModeManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
@@ -48,6 +49,7 @@
     private static @Nullable Boolean sIsRetailDemoModeForTesting;
     private final IDeviceInfo mIDeviceInfo;
     private @Nullable Boolean mIsRetailDemoMode;
+    private @Nullable ApplicationInfo mGmsAppInfo;
 
     // This is the minimum width in DP that defines a large display device
     public static final int LARGE_DISPLAY_MIN_SCREEN_WIDTH_600_DP = 600;
@@ -88,6 +90,10 @@
         return getInstance().mIDeviceInfo.gmsVersionCode;
     }
 
+    public static @Nullable ApplicationInfo getGmsAppInfo() {
+        return getInstance().mGmsAppInfo;
+    }
+
     @CalledByNativeForTesting
     public static void setGmsVersionCodeForTest(@JniType("std::string") String gmsVersionCode) {
         sGmsVersionCodeForTesting = gmsVersionCode;
@@ -220,10 +226,13 @@
         mIDeviceInfo = new IDeviceInfo();
         sInitialized = true;
         PackageInfo gmsPackageInfo = PackageUtils.getPackageInfo("com.google.android.gms", 0);
-        mIDeviceInfo.gmsVersionCode =
-                gmsPackageInfo != null
-                        ? String.valueOf(packageVersionCode(gmsPackageInfo))
-                        : "gms versionCode not available.";
+        if (gmsPackageInfo != null) {
+            mGmsAppInfo = gmsPackageInfo.applicationInfo;
+            mIDeviceInfo.gmsVersionCode =
+                    gmsPackageInfo != null
+                            ? String.valueOf(packageVersionCode(gmsPackageInfo))
+                            : "gms versionCode not available.";
+        }
         if (sGmsVersionCodeForTesting != null) {
             mIDeviceInfo.gmsVersionCode = sGmsVersionCodeForTesting;
         }
diff --git a/base/android/java/src/org/chromium/base/SysUtils.java b/base/android/java/src/org/chromium/base/SysUtils.java
index bf4cb2a1..d44a1f5 100644
--- a/base/android/java/src/org/chromium/base/SysUtils.java
+++ b/base/android/java/src/org/chromium/base/SysUtils.java
@@ -9,6 +9,7 @@
 import android.content.pm.PackageManager;
 import android.os.StrictMode;
 
+import org.jni_zero.CalledByNative;
 import org.jni_zero.JNINamespace;
 import org.jni_zero.NativeMethods;
 
@@ -35,6 +36,7 @@
     private static @Nullable Boolean sLowEndDevice;
     private static @Nullable Integer sAmountOfPhysicalMemoryKB;
     private static @Nullable Boolean sHasCameraForTesting;
+    private static int sLowMemoryThresholdMB = LOW_MEMORY_DEVICE_THRESHOLD_MB;
 
     private SysUtils() {}
 
@@ -178,6 +180,15 @@
         // LINT.ThenChange(//base/system/sys_info.cc)
     }
 
+    public static void setLowMemoryDeviceThresholdMb(int thresholdMb) {
+        sLowMemoryThresholdMB = thresholdMb;
+    }
+
+    @CalledByNative
+    private static int getLowMemoryDeviceThresholdMb() {
+        return sLowMemoryThresholdMB;
+    }
+
     /**
      * Creates a new trace event to log the number of minor / major page faults, if tracing is
      * enabled.
diff --git a/base/android/java/src/org/chromium/base/task/ChromiumExecutorServiceFactory.java b/base/android/java/src/org/chromium/base/task/ChromiumExecutorServiceFactory.java
index 69e7d91..d05eb54 100644
--- a/base/android/java/src/org/chromium/base/task/ChromiumExecutorServiceFactory.java
+++ b/base/android/java/src/org/chromium/base/task/ChromiumExecutorServiceFactory.java
@@ -34,7 +34,12 @@
 
     /** Creates a {@link ScheduledExecutorService}. */
     public static ListeningScheduledExecutorService create(@TaskTraits int taskTraits) {
-        return MoreExecutors.listeningDecorator(new ScheduledExecutorServiceImpl(taskTraits));
+        TaskRunner taskRunner = PostTask.getTaskRunner(taskTraits);
+        return create(taskRunner);
+    }
+
+    public static ListeningScheduledExecutorService create(TaskRunner taskRunner) {
+        return MoreExecutors.listeningDecorator(new ScheduledExecutorServiceImpl(taskRunner));
     }
 
     private static long getCurrentTimeNanos() {
@@ -131,10 +136,10 @@
     }
 
     private static final class ScheduledExecutorServiceImpl implements ScheduledExecutorService {
-        @TaskTraits private final int mTaskTraits;
+        private final TaskRunner mTaskRunner;
 
-        public ScheduledExecutorServiceImpl(@TaskTraits int taskTraits) {
-            this.mTaskTraits = taskTraits;
+        public ScheduledExecutorServiceImpl(TaskRunner taskRunner) {
+            mTaskRunner = taskRunner;
         }
 
         @Override
@@ -259,12 +264,12 @@
 
         @Override
         public void execute(Runnable runnable) {
-            PostTask.postDelayedTask(mTaskTraits, runnable, 0);
+            mTaskRunner.postDelayedTask(runnable, 0);
         }
 
         @NullUnmarked // https://github.com/uber/NullAway/issues/1075
         private <T extends @Nullable Object> void postTask(ScheduledFutureTask<T> task) {
-            PostTask.postDelayedTask(mTaskTraits, () -> runTask(task), task.getDelay(MILLISECONDS));
+            mTaskRunner.postDelayedTask(() -> runTask(task), task.getDelay(MILLISECONDS));
         }
 
         private <T extends @Nullable Object> void runTask(ScheduledFutureTask<T> task) {
diff --git a/base/android/sys_utils.cc b/base/android/sys_utils.cc
index 0424fc08..5dbbb698 100644
--- a/base/android/sys_utils.cc
+++ b/base/android/sys_utils.cc
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "base/process/process_metrics.h"
-#include "base/trace_event/trace_event.h"
+#include <jni.h>
 
-// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "base/android/jni_android.h"
+#include "base/process/process_metrics.h"
 #include "base/sys_utils_jni/SysUtils_jni.h"
+#include "base/trace_event/trace_event.h"
 
 namespace base {
 namespace android {
@@ -31,6 +32,11 @@
                    "major", counts.major);
 }
 
+int GetCachedLowMemoryDeviceThresholdMb() {
+  JNIEnv* env = AttachCurrentThread();
+  return static_cast<int>(Java_SysUtils_getLowMemoryDeviceThresholdMb(env));
+}
+
 }  // namespace android
 
 }  // namespace base
diff --git a/base/android/sys_utils.h b/base/android/sys_utils.h
new file mode 100644
index 0000000..138078e
--- /dev/null
+++ b/base/android/sys_utils.h
@@ -0,0 +1,18 @@
+// 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 BASE_ANDROID_SYS_UTILS_H_
+#define BASE_ANDROID_SYS_UTILS_H_
+
+#include "base/base_export.h"
+
+namespace base::android {
+
+// Returns the RAM thresholds below which a device is considered low-RAM,
+// obtained from a feature param
+BASE_EXPORT int GetCachedLowMemoryDeviceThresholdMb();
+
+}  // namespace base::android
+
+#endif  // BASE_ANDROID_SYS_UTILS_H_
diff --git a/base/memory/memory_pressure_listener.cc b/base/memory/memory_pressure_listener.cc
index 6ca6eff6..9f24e9b 100644
--- a/base/memory/memory_pressure_listener.cc
+++ b/base/memory/memory_pressure_listener.cc
@@ -87,11 +87,19 @@
 SyncMemoryPressureListenerRegistration::SyncMemoryPressureListenerRegistration(
     MemoryPressureListenerTag tag,
     MemoryPressureCallback memory_pressure_callback)
-    : memory_pressure_callback_(std::move(memory_pressure_callback)),
-      tag_(tag) {
+    : tag_(tag),
+      memory_pressure_callback_(std::move(memory_pressure_callback)) {
   MemoryPressureListenerRegistry::Get().AddObserver(this);
 }
 
+SyncMemoryPressureListenerRegistration::SyncMemoryPressureListenerRegistration(
+    MemoryPressureListenerTag tag,
+    MemoryPressureListener* memory_pressure_listener)
+    : SyncMemoryPressureListenerRegistration(
+          tag,
+          base::BindRepeating(&MemoryPressureListener::OnMemoryPressure,
+                              base::Unretained(memory_pressure_listener))) {}
+
 SyncMemoryPressureListenerRegistration::
     ~SyncMemoryPressureListenerRegistration() {
   MemoryPressureListenerRegistry::Get().RemoveObserver(this);
@@ -167,6 +175,17 @@
 }
 
 AsyncMemoryPressureListenerRegistration::
+    AsyncMemoryPressureListenerRegistration(
+        const base::Location& creation_location,
+        MemoryPressureListenerTag tag,
+        MemoryPressureListener* memory_pressure_listener)
+    : AsyncMemoryPressureListenerRegistration(
+          creation_location,
+          tag,
+          base::BindRepeating(&MemoryPressureListener::OnMemoryPressure,
+                              base::Unretained(memory_pressure_listener))) {}
+
+AsyncMemoryPressureListenerRegistration::
     ~AsyncMemoryPressureListenerRegistration() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (main_thread_) {
@@ -207,6 +226,16 @@
           tag,
           std::move(memory_pressure_callback))) {}
 
+MemoryPressureListenerRegistration::MemoryPressureListenerRegistration(
+    const Location& creation_location,
+    MemoryPressureListenerTag tag,
+    MemoryPressureListener* memory_pressure_listener)
+    : MemoryPressureListenerRegistration(
+          creation_location,
+          tag,
+          base::BindRepeating(&MemoryPressureListener::OnMemoryPressure,
+                              base::Unretained(memory_pressure_listener))) {}
+
 MemoryPressureListenerRegistration::~MemoryPressureListenerRegistration() =
     default;
 
diff --git a/base/memory/memory_pressure_listener.h b/base/memory/memory_pressure_listener.h
index 6f981406..6cd65fd 100644
--- a/base/memory/memory_pressure_listener.h
+++ b/base/memory/memory_pressure_listener.h
@@ -19,6 +19,7 @@
 #include "base/memory/memory_pressure_level.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/observer_list_types.h"
 #include "base/sequence_checker.h"
 #include "base/threading/thread_checker.h"
 
@@ -110,7 +111,7 @@
 //    // Stop listening.
 //    listener.reset();
 
-class BASE_EXPORT MemoryPressureListener {
+class BASE_EXPORT MemoryPressureListener : public CheckedObserver {
  public:
   // Intended for use by the platform specific implementation.
   // Note: This simply forwards the call to MemoryPressureListenerRegistry to
@@ -131,6 +132,8 @@
   // runs.
   static void SimulatePressureNotificationAsync(
       MemoryPressureLevel memory_pressure_level);
+
+  virtual void OnMemoryPressure(MemoryPressureLevel memory_pressure_level) = 0;
 };
 
 // Used for listeners that live on the main thread and must be called
@@ -140,10 +143,17 @@
  public:
   using MemoryPressureCallback = RepeatingCallback<void(MemoryPressureLevel)>;
 
-  explicit SyncMemoryPressureListenerRegistration(
+  // Constructor using a callback.
+  // DEPRECATED. Use the MemoryPressureListener interface.
+  SyncMemoryPressureListenerRegistration(
       MemoryPressureListenerTag tag,
       MemoryPressureCallback memory_pressure_callback);
 
+  // Constructor using the MemoryPressureListener interface.
+  SyncMemoryPressureListenerRegistration(
+      MemoryPressureListenerTag,
+      MemoryPressureListener* memory_pressure_listener);
+
   SyncMemoryPressureListenerRegistration(
       const SyncMemoryPressureListenerRegistration&) = delete;
   SyncMemoryPressureListenerRegistration& operator=(
@@ -156,11 +166,11 @@
   MemoryPressureListenerTag tag() { return tag_; }
 
  private:
+  MemoryPressureListenerTag tag_;
+
   MemoryPressureCallback memory_pressure_callback_
       GUARDED_BY_CONTEXT(thread_checker_);
 
-  MemoryPressureListenerTag tag_;
-
   THREAD_CHECKER(thread_checker_);
 };
 
@@ -170,11 +180,19 @@
  public:
   using MemoryPressureCallback = RepeatingCallback<void(MemoryPressureLevel)>;
 
+  // Constructor using a callback.
+  // DEPRECATED. Use the MemoryPressureListener interface.
   AsyncMemoryPressureListenerRegistration(
       const base::Location& creation_location,
       MemoryPressureListenerTag tag,
       MemoryPressureCallback memory_pressure_callback);
 
+  // Constructor using the MemoryPressureListener interface.
+  AsyncMemoryPressureListenerRegistration(
+      const base::Location& creation_location,
+      MemoryPressureListenerTag tag,
+      MemoryPressureListener* memory_pressure_listener);
+
   AsyncMemoryPressureListenerRegistration(
       const AsyncMemoryPressureListenerRegistration&) = delete;
   AsyncMemoryPressureListenerRegistration& operator=(
@@ -213,11 +231,19 @@
  public:
   using MemoryPressureCallback = RepeatingCallback<void(MemoryPressureLevel)>;
 
+  // Constructor using a callback.
+  // DEPRECATED. Use the MemoryPressureListener interface.
   MemoryPressureListenerRegistration(
       const Location& creation_location,
       MemoryPressureListenerTag tag,
       MemoryPressureCallback memory_pressure_callback);
 
+  // Constructor using the MemoryPressureListener interface.
+  MemoryPressureListenerRegistration(
+      const Location& creation_location,
+      MemoryPressureListenerTag tag,
+      MemoryPressureListener* memory_pressure_listener);
+
   MemoryPressureListenerRegistration(
       const MemoryPressureListenerRegistration&) = delete;
   MemoryPressureListenerRegistration& operator=(
diff --git a/base/memory/memory_pressure_listener_unittest.cc b/base/memory/memory_pressure_listener_unittest.cc
index c0842fa3..4532991 100644
--- a/base/memory/memory_pressure_listener_unittest.cc
+++ b/base/memory/memory_pressure_listener_unittest.cc
@@ -7,6 +7,7 @@
 #include "base/functional/bind.h"
 #include "base/memory/memory_pressure_level.h"
 #include "base/memory/memory_pressure_listener_registry.h"
+#include "base/memory/mock_memory_pressure_listener.h"
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -14,29 +15,21 @@
 namespace base {
 
 class MemoryPressureListenerTest : public testing::Test {
- public:
-  MemoryPressureListenerTest()
-      : listener_(base::MemoryPressureListenerTag::kTest,
-                  BindRepeating(&MemoryPressureListenerTest::OnMemoryPressure,
-                                Unretained(this))) {}
-
  protected:
   void ExpectNotification(void (*notification_function)(MemoryPressureLevel),
                           MemoryPressureLevel level) {
-    EXPECT_CALL(*this, OnMemoryPressure(level)).Times(1);
+    EXPECT_CALL(listener_, OnMemoryPressure(level)).Times(1);
     notification_function(level);
   }
 
   void ExpectNoNotification(void (*notification_function)(MemoryPressureLevel),
                             MemoryPressureLevel level) {
-    EXPECT_CALL(*this, OnMemoryPressure(testing::_)).Times(0);
+    EXPECT_CALL(listener_, OnMemoryPressure(testing::_)).Times(0);
     notification_function(level);
   }
 
  private:
-  MOCK_METHOD1(OnMemoryPressure, void(MemoryPressureLevel));
-
-  SyncMemoryPressureListenerRegistration listener_;
+  RegisteredMockMemoryPressureListener listener_;
 };
 
 TEST_F(MemoryPressureListenerTest, NotifyMemoryPressure) {
@@ -71,24 +64,18 @@
   base::test::SingleThreadTaskEnvironment task_env;
 
   auto listener_to_be_deleted =
-      std::make_unique<MemoryPressureListenerRegistration>(
-          FROM_HERE, base::MemoryPressureListenerTag::kTest,
-          BindRepeating([](MemoryPressureLevel) {
-            FAIL() << "Async callback should not be called.";
-          }));
+      std::make_unique<RegisteredMockAsyncMemoryPressureListener>();
+  EXPECT_CALL(*listener_to_be_deleted, OnMemoryPressure(testing::_)).Times(0);
 
   auto deleter_listener =
-      std::make_unique<SyncMemoryPressureListenerRegistration>(
-          base::MemoryPressureListenerTag::kTest,
-          BindLambdaForTesting([&](MemoryPressureLevel) {
-            // This should not deadlock.
-            listener_to_be_deleted.reset();
-          }));
+      std::make_unique<RegisteredMockMemoryPressureListener>();
+  EXPECT_CALL(*deleter_listener, OnMemoryPressure(testing::_)).WillOnce([&]() {
+    listener_to_be_deleted.reset();
+  });
 
   // This should trigger the sync callback in |deleter_listener|, which will
   // delete |listener_to_be_deleted|.
-  ExpectNotification(&MemoryPressureListener::NotifyMemoryPressure,
-                     MEMORY_PRESSURE_LEVEL_CRITICAL);
+  MemoryPressureListener::NotifyMemoryPressure(MEMORY_PRESSURE_LEVEL_CRITICAL);
 }
 
 }  // namespace base
diff --git a/base/memory/mock_memory_pressure_listener.cc b/base/memory/mock_memory_pressure_listener.cc
new file mode 100644
index 0000000..eafcffa
--- /dev/null
+++ b/base/memory/mock_memory_pressure_listener.cc
@@ -0,0 +1,35 @@
+// 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 "base/memory/mock_memory_pressure_listener.h"
+
+#include "base/functional/bind.h"
+
+namespace base {
+
+MockMemoryPressureListener::MockMemoryPressureListener() = default;
+
+MockMemoryPressureListener::~MockMemoryPressureListener() = default;
+
+RegisteredMockMemoryPressureListener::RegisteredMockMemoryPressureListener()
+    : registration_(
+          MemoryPressureListenerTag::kTest,
+          base::BindRepeating(&MockMemoryPressureListener::OnMemoryPressure,
+                              base::Unretained(this))) {}
+
+RegisteredMockMemoryPressureListener::~RegisteredMockMemoryPressureListener() =
+    default;
+
+RegisteredMockAsyncMemoryPressureListener::
+    RegisteredMockAsyncMemoryPressureListener()
+    : registration_(
+          FROM_HERE,
+          MemoryPressureListenerTag::kTest,
+          base::BindRepeating(&MockMemoryPressureListener::OnMemoryPressure,
+                              base::Unretained(this))) {}
+
+RegisteredMockAsyncMemoryPressureListener::
+    ~RegisteredMockAsyncMemoryPressureListener() = default;
+
+}  // namespace base
diff --git a/base/memory/mock_memory_pressure_listener.h b/base/memory/mock_memory_pressure_listener.h
new file mode 100644
index 0000000..603409a
--- /dev/null
+++ b/base/memory/mock_memory_pressure_listener.h
@@ -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.
+
+#ifndef BASE_MEMORY_MOCK_MEMORY_PRESSURE_LISTENER_H_
+#define BASE_MEMORY_MOCK_MEMORY_PRESSURE_LISTENER_H_
+
+#include "base/memory/memory_pressure_listener.h"
+#include "testing/gmock/include/gmock/gmock.h"
+
+namespace base {
+
+class MockMemoryPressureListener {
+ public:
+  MockMemoryPressureListener();
+  ~MockMemoryPressureListener();
+
+  MOCK_METHOD(void, OnMemoryPressure, (base::MemoryPressureLevel));
+};
+
+// Same as MockMemoryPressureListener, but automatically registers with the
+// global registry.
+class RegisteredMockMemoryPressureListener : public MockMemoryPressureListener {
+ public:
+  RegisteredMockMemoryPressureListener();
+  ~RegisteredMockMemoryPressureListener();
+
+ private:
+  SyncMemoryPressureListenerRegistration registration_;
+};
+
+// Async version of RegisteredMockMemoryPressureListener.
+class RegisteredMockAsyncMemoryPressureListener
+    : public MockMemoryPressureListener {
+ public:
+  RegisteredMockAsyncMemoryPressureListener();
+  ~RegisteredMockAsyncMemoryPressureListener();
+
+ private:
+  AsyncMemoryPressureListenerRegistration registration_;
+};
+
+}  // namespace base
+
+#endif  // BASE_MEMORY_MOCK_MEMORY_PRESSURE_LISTENER_H_
diff --git a/base/synchronization/waitable_event.h b/base/synchronization/waitable_event.h
index 9956e176..81880a2 100644
--- a/base/synchronization/waitable_event.h
+++ b/base/synchronization/waitable_event.h
@@ -249,15 +249,14 @@
     ~WaitableEventKernel();
   };
 
-  typedef std::pair<WaitableEvent*, size_t> WaiterAndIndex;
+  using WaiterAndIndex = std::pair<WaitableEvent*, size_t>;
 
   // When dealing with arrays of WaitableEvent*, we want to sort by the address
   // of the WaitableEvent in order to have a globally consistent locking order.
   // In that case we keep them, in sorted order, in an array of pairs where the
   // second element is the index of the WaitableEvent in the original,
   // unsorted, array.
-  static size_t EnqueueMany(WaiterAndIndex* waitables,
-                            size_t count,
+  static size_t EnqueueMany(base::span<WaiterAndIndex> waitables,
                             Waiter* waiter);
 
   bool SignalAll();
diff --git a/base/synchronization/waitable_event_posix.cc b/base/synchronization/waitable_event_posix.cc
index c880a46..180e5924 100644
--- a/base/synchronization/waitable_event_posix.cc
+++ b/base/synchronization/waitable_event_posix.cc
@@ -12,7 +12,7 @@
 #include <vector>
 
 #include "base/check_op.h"
-#include "base/compiler_specific.h"
+#include "base/containers/adapters.h"
 #include "base/memory/stack_allocated.h"
 #include "base/synchronization/condition_variable.h"
 #include "base/synchronization/lock.h"
@@ -247,7 +247,7 @@
 
   SyncWaiter sw;
 
-  const size_t r = EnqueueMany(waitables.data(), waitables.size(), &sw);
+  const size_t r = EnqueueMany(waitables, &sw);
   if (r < waitables.size()) {
     // One of the events is already signaled. The SyncWaiter has not been
     // enqueued anywhere.
@@ -311,35 +311,33 @@
 // -----------------------------------------------------------------------------
 // static
 // NO_THREAD_SAFETY_ANALYSIS: Complex control flow.
-size_t WaitableEvent::EnqueueMany(std::pair<WaitableEvent*, size_t>* waitables,
-                                  size_t count,
+size_t WaitableEvent::EnqueueMany(base::span<WaiterAndIndex> waitables,
                                   Waiter* waiter) NO_THREAD_SAFETY_ANALYSIS {
-  size_t winner = count;
-  size_t winner_index = count;
-  for (size_t i = 0; i < count; ++i) {
-    auto& kernel = UNSAFE_TODO(waitables[i]).first->kernel_;
+  size_t winner = waitables.size();
+  size_t winner_index = waitables.size();
+  for (size_t i = 0; i < waitables.size(); ++i) {
+    auto& kernel = waitables[i].first->kernel_;
     kernel->lock_.Acquire();
-    if (kernel->signaled_ && UNSAFE_TODO(waitables[i]).second < winner) {
-      winner = UNSAFE_TODO(waitables[i]).second;
+    if (kernel->signaled_ && waitables[i].second < winner) {
+      winner = waitables[i].second;
       winner_index = i;
     }
   }
 
   // No events signaled. All locks acquired. Enqueue the Waiter on all of them
   // and return.
-  if (winner == count) {
-    for (size_t i = 0; i < count; ++i) {
-      UNSAFE_TODO(waitables[i]).first->Enqueue(waiter);
+  if (winner == waitables.size()) {
+    for (auto& w : waitables) {
+      w.first->Enqueue(waiter);
     }
-    return count;
+    return waitables.size();
   }
 
   // Unlock in reverse order and possibly clear the chosen winner's signal
   // before returning its index.
-  for (auto* w = UNSAFE_TODO(waitables + count - 1); w >= waitables;
-       UNSAFE_TODO(--w)) {
-    auto& kernel = w->first->kernel_;
-    if (w->second == winner) {
+  for (auto& w : base::Reversed(waitables)) {
+    auto& kernel = w.first->kernel_;
+    if (w.second == winner) {
       if (!kernel->manual_reset_) {
         kernel->signaled_ = false;
       }
diff --git a/base/system/sys_info.cc b/base/system/sys_info.cc
index 5782b000..b95916c 100644
--- a/base/system/sys_info.cc
+++ b/base/system/sys_info.cc
@@ -18,6 +18,9 @@
 #include "base/task/thread_pool.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#if BUILDFLAG(IS_ANDROID)
+#include "base/android/sys_utils.h"
+#endif  // BUILDFLAG(IS_ANDROID)
 
 namespace base {
 namespace {
@@ -197,6 +200,14 @@
   }
 
   ByteCount ram_size = SysInfo::AmountOfPhysicalMemory();
+#if BUILDFLAG(IS_ANDROID)
+  if (FeatureList::GetInstance() == nullptr) {
+    int threshold_mb = base::android::GetCachedLowMemoryDeviceThresholdMb();
+    if (threshold_mb > 0) {
+      return ram_size > ByteCount(0) && ram_size <= MiB(threshold_mb);
+    }
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
   return ram_size > ByteCount(0) &&
          ram_size <= MiB(features::kLowMemoryDeviceThresholdMB.Get());
   // LINT.ThenChange(//base/android/java/src/org/chromium/base/SysUtils.java)
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
index 8164ccb..3ce8362 100644
--- a/base/test/BUILD.gn
+++ b/base/test/BUILD.gn
@@ -49,6 +49,8 @@
 static_library("test_support") {
   testonly = true
   sources = [
+    "../memory/mock_memory_pressure_listener.cc",
+    "../memory/mock_memory_pressure_listener.h",
     "../memory_coordinator/mock_memory_consumer.cc",
     "../memory_coordinator/mock_memory_consumer.h",
     "../memory_coordinator/test_memory_consumer_registry.cc",
diff --git a/build/linux/dump_app_syms.py b/build/linux/dump_app_syms.py
old mode 100644
new mode 100755
index ca2d700..adb94431
--- a/build/linux/dump_app_syms.py
+++ b/build/linux/dump_app_syms.py
@@ -1,3 +1,4 @@
+#!/usr/bin/env python3
 # Copyright 2015 The Chromium Authors
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
@@ -27,4 +28,4 @@
     subprocess.check_call([dumpsyms, '-m', '-d', infile], stdout=outfileobj)
 
 if strip_binary != '0':
-  subprocess.check_call(['strip', infile])
+  subprocess.check_call(['strip', infile])
\ No newline at end of file
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc
index f0da049..2ddc8a8c 100644
--- a/cc/mojo_embedder/viz_layer_context.cc
+++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -467,7 +467,7 @@
 
 void SerializeUIResourceRequest(
     cc::LayerTreeHostImpl& host_impl,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     viz::mojom::LayerTreeUpdate& update,
     cc::UIResourceId uid,
     viz::mojom::TransferableUIResourceRequest::Type type) {
@@ -479,7 +479,7 @@
     bool opaque = host_impl.IsUIResourceOpaque(uid);
     ids.push_back(resource_id);
     host_impl.resource_provider()->PrepareSendToParent(ids, &resources,
-                                                       &context_provider);
+                                                       context_provider);
     CHECK_EQ(resources.size(), ids.size());
 
     auto& request = update.ui_resource_requests.emplace_back(
@@ -500,11 +500,11 @@
 viz::mojom::TileResourcePtr SerializeTileResource(
     const Tile& tile,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider) {
+    viz::RasterContextProvider* context_provider) {
   const auto& draw_info = tile.draw_info();
   std::vector<viz::ResourceId> ids(1, draw_info.resource_id_for_export());
   std::vector<viz::TransferableResource> resources;
-  resource_provider.PrepareSendToParent(ids, &resources, &context_provider);
+  resource_provider.PrepareSendToParent(ids, &resources, context_provider);
   CHECK_EQ(resources.size(), 1u);
 
   auto wire = viz::mojom::TileResource::New();
@@ -517,7 +517,7 @@
 viz::mojom::TilePtr SerializeTile(
     const Tile& tile,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider) {
+    viz::RasterContextProvider* context_provider) {
   auto wire = viz::mojom::Tile::New();
   wire->column_index = tile.tiling_i_index();
   wire->row_index = tile.tiling_j_index();
@@ -556,7 +556,7 @@
     float scale_key,
     base::span<const std::pair<TileIndex, const Tile*>> tile_updates,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider) {
+    viz::RasterContextProvider* context_provider) {
   // Handle the case where the tiling no longer exists (deleted).
   if (!tiling) {
     auto deleted_tiling = viz::mojom::Tiling::New();
@@ -613,7 +613,7 @@
 void SerializePictureLayerTileUpdates(
     PictureLayerImpl& layer,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     std::vector<viz::mojom::TilingPtr>& tilings,
     bool needs_full_sync) {
   auto updates =
@@ -646,7 +646,7 @@
 void SerializeHudLayerExtra(HeadsUpDisplayLayerImpl& layer,
                             viz::mojom::TextureLayerExtraPtr& extra,
                             viz::ClientResourceProvider& resource_provider,
-                            viz::RasterContextProvider& context_provider) {
+                            viz::RasterContextProvider* context_provider) {
   // HUD layers are typically drawn onto a transparent background and then
   // composited. They don't have a specific background color to blend with.
   extra->blend_background_color = false;
@@ -662,7 +662,7 @@
   if (resource_id != viz::kInvalidResourceId) {
     std::vector<viz::ResourceId> ids = {resource_id};
     std::vector<viz::TransferableResource> resources;
-    resource_provider.PrepareSendToParent(ids, &resources, &context_provider);
+    resource_provider.PrepareSendToParent(ids, &resources, context_provider);
     CHECK_EQ(resources.size(), 1u);
     extra->transferable_resource = resources[0];
     extra->uv_top_left = gfx::PointF();
@@ -681,7 +681,7 @@
 void SerializeTextureLayerExtra(TextureLayerImpl& layer,
                                 viz::mojom::TextureLayerExtraPtr& extra,
                                 viz::ClientResourceProvider& resource_provider,
-                                viz::RasterContextProvider& context_provider) {
+                                viz::RasterContextProvider* context_provider) {
   extra->blend_background_color = layer.blend_background_color();
   extra->force_texture_to_opaque = layer.force_texture_to_opaque();
   extra->uv_top_left = layer.uv_top_left();
@@ -691,7 +691,7 @@
     if (layer.resource_id() != viz::kInvalidResourceId) {
       std::vector<viz::ResourceId> ids(1, layer.resource_id());
       std::vector<viz::TransferableResource> resources;
-      resource_provider.PrepareSendToParent(ids, &resources, &context_provider);
+      resource_provider.PrepareSendToParent(ids, &resources, context_provider);
       CHECK_EQ(resources.size(), 1u);
       extra->transferable_resource = resources[0];
     } else {
@@ -819,7 +819,7 @@
 
 void SerializeLayer(LayerImpl& layer,
                     viz::ClientResourceProvider& resource_provider,
-                    viz::RasterContextProvider& context_provider,
+                    viz::RasterContextProvider* context_provider,
                     viz::mojom::LayerTreeUpdate& update,
                     bool needs_full_sync) {
   auto& wire = *update.layers.emplace_back(viz::mojom::Layer::New());
@@ -1298,7 +1298,7 @@
 base::TimeTicks VizLayerContext::UpdateDisplayTreeFrom(
     LayerTreeImpl& tree,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     const gfx::Rect& viewport_damage_rect,
     const viz::LocalSurfaceId& target_local_surface_id) {
   auto& property_trees = *tree.property_trees();
@@ -1463,7 +1463,7 @@
     PictureLayerImpl& layer,
     const Tile& tile,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     bool update_damage) {
   if (needs_full_sync_) {
     // If |needs_full_sync_| is set due to context lost, we will need to sync
diff --git a/cc/mojo_embedder/viz_layer_context.h b/cc/mojo_embedder/viz_layer_context.h
index 7f9ae65..af9f577 100644
--- a/cc/mojo_embedder/viz_layer_context.h
+++ b/cc/mojo_embedder/viz_layer_context.h
@@ -44,13 +44,13 @@
   base::TimeTicks UpdateDisplayTreeFrom(
       LayerTreeImpl& tree,
       viz::ClientResourceProvider& resource_provider,
-      viz::RasterContextProvider& context_provider,
+      viz::RasterContextProvider* context_provider,
       const gfx::Rect& viewport_damage_rect,
       const viz::LocalSurfaceId& target_local_surface_id) override;
   void UpdateDisplayTile(PictureLayerImpl& layer,
                          const Tile& tile,
                          viz::ClientResourceProvider& resource_provider,
-                         viz::RasterContextProvider& context_provider,
+                         viz::RasterContextProvider* context_provider,
                          bool update_damage) override;
 
   // viz::mojom::LayerContextClient:
diff --git a/cc/paint/BUILD.gn b/cc/paint/BUILD.gn
index d9714b8..accb7b9 100644
--- a/cc/paint/BUILD.gn
+++ b/cc/paint/BUILD.gn
@@ -180,6 +180,7 @@
     "//cc/paint",
     "//components/viz/test:test_support",
     "//gpu/command_buffer/service:gles2",
+    "//gpu/skia_bindings",
   ]
 }
 
diff --git a/cc/paint/DEPS b/cc/paint/DEPS
index d976a78..f9621cb 100644
--- a/cc/paint/DEPS
+++ b/cc/paint/DEPS
@@ -16,6 +16,7 @@
   "paint_op_raster_fuzzer.cc": [
     "+components/viz/test",
     "+gpu/command_buffer",
+    "+gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h",
   ],
   "paint_op_reader.cc": [
     "+components/crash/core/common",
diff --git a/cc/paint/paint_op_raster_fuzzer.cc b/cc/paint/paint_op_raster_fuzzer.cc
index 8eb0891..d97c166 100644
--- a/cc/paint/paint_op_raster_fuzzer.cc
+++ b/cc/paint/paint_op_raster_fuzzer.cc
@@ -22,12 +22,16 @@
 #include "cc/paint/paint_op_writer.h"
 #include "cc/test/transfer_cache_test_helper.h"
 #include "components/viz/test/test_context_provider.h"
+#include "components/viz/test/test_gles2_interface.h"
 #include "gpu/command_buffer/common/buffer.h"
 #include "gpu/command_buffer/service/service_font_manager.h"
+#include "gpu/skia_bindings/gl_bindings_skia_cmd_buffer.h"
 #include "third_party/skia/include/core/SkSurface.h"
 #include "third_party/skia/include/gpu/GpuTypes.h"
 #include "third_party/skia/include/gpu/ganesh/GrDirectContext.h"
 #include "third_party/skia/include/gpu/ganesh/SkSurfaceGanesh.h"
+#include "third_party/skia/include/gpu/ganesh/gl/GrGLDirectContext.h"
+#include "third_party/skia/include/gpu/ganesh/gl/GrGLInterface.h"
 
 struct Environment {
   Environment() {
@@ -76,7 +80,7 @@
   base::flat_map<uint32_t, scoped_refptr<gpu::Buffer>> buffers_;
 };
 
-void Raster(scoped_refptr<viz::TestContextProvider> context_provider,
+void Raster(GrDirectContext* gr_context,
             SkStrikeClient* strike_client,
             cc::ServicePaintCache* paint_cache,
             const uint8_t* data,
@@ -85,8 +89,8 @@
 
   SkImageInfo image_info = SkImageInfo::MakeN32(
       kRasterDimension, kRasterDimension, kOpaque_SkAlphaType);
-  sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(
-      context_provider->GrContext(), skgpu::Budgeted::kYes, image_info);
+  sk_sp<SkSurface> surface =
+      SkSurfaces::RenderTarget(gr_context, skgpu::Budgeted::kYes, image_info);
   SkCanvas* canvas = surface->getCanvas();
 
   cc::PlaybackParams params(nullptr, canvas->getLocalToDevice());
@@ -157,16 +161,25 @@
 
   auto context_provider_no_support = viz::TestContextProvider::Create();
   context_provider_no_support->BindToCurrentSequence();
-  CHECK(!context_provider_no_support->GrContext()->supportsDistanceFieldText());
-  Raster(context_provider_no_support, font_manager->strike_client(),
+  auto gr_context_no_support =
+      GrDirectContexts::MakeGL(skia_bindings::CreateGLES2InterfaceBindings(
+          context_provider_no_support->ContextGL(),
+          context_provider_no_support->ContextSupport()));
+  CHECK(!!gr_context_no_support);
+  CHECK(!gr_context_no_support->supportsDistanceFieldText());
+  Raster(gr_context_no_support.get(), font_manager->strike_client(),
          &paint_cache, raster_data, raster_size);
 
   auto context_provider_with_support = viz::TestContextProvider::Create(
       std::string("GL_OES_standard_derivatives"));
   context_provider_with_support->BindToCurrentSequence();
-  CHECK(
-      context_provider_with_support->GrContext()->supportsDistanceFieldText());
-  Raster(context_provider_with_support, font_manager->strike_client(),
+  auto gr_context_with_support =
+      GrDirectContexts::MakeGL(skia_bindings::CreateGLES2InterfaceBindings(
+          context_provider_with_support->ContextGL(),
+          context_provider_with_support->ContextSupport()));
+  CHECK(!!gr_context_with_support);
+  CHECK(gr_context_with_support->supportsDistanceFieldText());
+  Raster(gr_context_with_support.get(), font_manager->strike_client(),
          &paint_cache, raster_data, raster_size);
 
   font_manager->Unlock(locked_handles);
diff --git a/cc/test/fake_layer_context.cc b/cc/test/fake_layer_context.cc
index 85fefba..38e6381 100644
--- a/cc/test/fake_layer_context.cc
+++ b/cc/test/fake_layer_context.cc
@@ -13,7 +13,7 @@
 base::TimeTicks FakeLayerContext::UpdateDisplayTreeFrom(
     LayerTreeImpl& tree,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     const gfx::Rect& viewport_damage_rect,
     const viz::LocalSurfaceId& target_local_surface_id) {
   return base::TimeTicks::Now();
@@ -23,7 +23,7 @@
     PictureLayerImpl& layer,
     const Tile& tile,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     bool update_damage) {}
 
 }  // namespace cc
diff --git a/cc/test/fake_layer_context.h b/cc/test/fake_layer_context.h
index 0d37fe9..92e507f6 100644
--- a/cc/test/fake_layer_context.h
+++ b/cc/test/fake_layer_context.h
@@ -19,14 +19,14 @@
   base::TimeTicks UpdateDisplayTreeFrom(
       LayerTreeImpl& tree,
       viz::ClientResourceProvider& resource_provider,
-      viz::RasterContextProvider& context_provider,
+      viz::RasterContextProvider* context_provider,
       const gfx::Rect& viewport_damage_rect,
       const viz::LocalSurfaceId& target_local_surface_id) override;
 
   void UpdateDisplayTile(PictureLayerImpl& layer,
                          const Tile& tile,
                          viz::ClientResourceProvider& resource_provider,
-                         viz::RasterContextProvider& context_provider,
+                         viz::RasterContextProvider* context_provider,
                          bool update_damage) override;
 };
 
diff --git a/cc/test/test_layer_context.cc b/cc/test/test_layer_context.cc
index 78dcc6d..e6df2712 100644
--- a/cc/test/test_layer_context.cc
+++ b/cc/test/test_layer_context.cc
@@ -11,7 +11,7 @@
 base::TimeTicks TestLayerContext::UpdateDisplayTreeFrom(
     LayerTreeImpl& tree,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     const gfx::Rect& viewport_damage_rect,
     const viz::LocalSurfaceId& target_local_surface_id) {
   return base::TimeTicks::Now();
@@ -21,7 +21,7 @@
     PictureLayerImpl& layer,
     const Tile& tile,
     viz::ClientResourceProvider& resource_provider,
-    viz::RasterContextProvider& context_provider,
+    viz::RasterContextProvider* context_provider,
     bool update_damage) {}
 
 }  // namespace cc
diff --git a/cc/test/test_layer_context.h b/cc/test/test_layer_context.h
index 6b3a1c6..eedcddca 100644
--- a/cc/test/test_layer_context.h
+++ b/cc/test/test_layer_context.h
@@ -19,14 +19,14 @@
   base::TimeTicks UpdateDisplayTreeFrom(
       LayerTreeImpl& tree,
       viz::ClientResourceProvider& resource_provider,
-      viz::RasterContextProvider& context_provider,
+      viz::RasterContextProvider* context_provider,
       const gfx::Rect& viewport_damage_rect,
       const viz::LocalSurfaceId& target_local_surface_id) override;
 
   void UpdateDisplayTile(PictureLayerImpl& layer,
                          const Tile& tile,
                          viz::ClientResourceProvider& resource_provider,
-                         viz::RasterContextProvider& context_provider,
+                         viz::RasterContextProvider* context_provider,
                          bool update_damage) override;
 };
 
diff --git a/cc/tiles/decoded_image_tracker.cc b/cc/tiles/decoded_image_tracker.cc
index 34a2da9d..69c5ee3 100644
--- a/cc/tiles/decoded_image_tracker.cc
+++ b/cc/tiles/decoded_image_tracker.cc
@@ -3,6 +3,9 @@
 // found in the LICENSE file.
 
 #include "cc/tiles/decoded_image_tracker.h"
+
+#include <algorithm>
+
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/default_tick_clock.h"
 #include "base/trace_event/trace_event.h"
@@ -37,8 +40,13 @@
     scoped_refptr<base::SequencedTaskRunner> task_runner)
     : image_controller_(controller),
       task_runner_(std::move(task_runner)),
-      tick_clock_(base::DefaultTickClock::GetInstance()) {
+      tick_clock_(base::DefaultTickClock::GetInstance()),
+      expiration_timer_(std::make_unique<base::RepeatingTimer>(tick_clock_)) {
   DCHECK(image_controller_);
+  expiration_timer_->SetTaskRunner(task_runner_);
+  // This must be done after weak_ptr_factory_ is initialized.
+  timer_closure_ = std::make_unique<base::RepeatingClosure>(base::BindRepeating(
+      &DecodedImageTracker::OnTimeoutImages, weak_ptr_factory_.GetWeakPtr()));
 }
 
 DecodedImageTracker::~DecodedImageTracker() {
@@ -73,6 +81,13 @@
     locked_images_.erase(draw_image.paint_image().stable_id());
 }
 
+void DecodedImageTracker::SetTickClockForTesting(
+    const base::TickClock* tick_clock) {
+  tick_clock_ = tick_clock;
+  expiration_timer_ = std::make_unique<base::RepeatingTimer>(tick_clock_);
+  expiration_timer_->SetTaskRunner(task_runner_);
+}
+
 void DecodedImageTracker::ImageDecodeFinished(
     base::OnceCallback<void(bool)> callback,
     PaintImage::Id image_id,
@@ -91,7 +106,9 @@
     locked_images_.emplace(
         image_id, std::make_unique<ImageLock>(
                       this, request_id, tick_clock_->NowTicks() + timeout));
-    EnqueueTimeout();
+    if (!expiration_timer_->IsRunning()) {
+      StartTimer(timeout);
+    }
   }
   bool decode_succeeded =
       result == ImageController::ImageDecodeResult::SUCCESS ||
@@ -100,35 +117,29 @@
 }
 
 void DecodedImageTracker::OnTimeoutImages() {
-  timeout_pending_ = false;
   if (locked_images_.size() == 0)
     return;
 
   auto now = tick_clock_->NowTicks();
+  base::TimeDelta delay = base::TimeDelta::Max();
   for (auto it = locked_images_.begin(); it != locked_images_.end();) {
     auto& image = it->second;
     if (now < image->expiration()) {
+      delay = std::min(delay, image->expiration() - now);
       ++it;
       continue;
     }
     it = locked_images_.erase(it);
   }
 
-  EnqueueTimeout();
+  StartTimer(delay);
 }
 
-void DecodedImageTracker::EnqueueTimeout() {
-  if (timeout_pending_)
+void DecodedImageTracker::StartTimer(base::TimeDelta delay) {
+  if (delay == base::TimeDelta::Max()) {
     return;
-  if (locked_images_.size() == 0)
-    return;
-
-  timeout_pending_ = true;
-  task_runner_->PostDelayedTask(
-      FROM_HERE,
-      base::BindOnce(&DecodedImageTracker::OnTimeoutImages,
-                     weak_ptr_factory_.GetWeakPtr()),
-      base::Milliseconds(kTimeoutDurationMs));
+  }
+  expiration_timer_->Start(FROM_HERE, delay, *timer_closure_);
 }
 
 }  // namespace cc
diff --git a/cc/tiles/decoded_image_tracker.h b/cc/tiles/decoded_image_tracker.h
index 376e89b..2045fa6e 100644
--- a/cc/tiles/decoded_image_tracker.h
+++ b/cc/tiles/decoded_image_tracker.h
@@ -14,6 +14,7 @@
 #include "base/task/sequenced_task_runner.h"
 #include "base/time/tick_clock.h"
 #include "base/time/time.h"
+#include "base/timer/timer.h"
 #include "cc/cc_export.h"
 #include "cc/paint/target_color_params.h"
 #include "cc/tiles/image_controller.h"
@@ -53,9 +54,7 @@
   // unlock them.
   void OnImagesUsedInDraw(const std::vector<DrawImage>& draw_images);
 
-  void SetTickClockForTesting(const base::TickClock* tick_clock) {
-    tick_clock_ = tick_clock;
-  }
+  void SetTickClockForTesting(const base::TickClock* tick_clock);
 
   // Test only functions:
   size_t NumLockedImagesForTesting() const { return locked_images_.size(); }
@@ -69,7 +68,7 @@
                            ImageController::ImageDecodeRequestId request_id,
                            ImageController::ImageDecodeResult result);
   void OnTimeoutImages();
-  void EnqueueTimeout();
+  void StartTimer(base::TimeDelta);
 
   raw_ptr<ImageController> image_controller_;
 
@@ -92,11 +91,12 @@
     const base::TimeTicks expiration_;
   };
   base::flat_map<PaintImage::Id, std::unique_ptr<ImageLock>> locked_images_;
-  bool timeout_pending_ = false;
-  scoped_refptr<base::SequencedTaskRunner> task_runner_;
 
   // Defaults to base::TimeTicks::Now(), but overrideable for testing.
+  scoped_refptr<base::SequencedTaskRunner> task_runner_;
   raw_ptr<const base::TickClock> tick_clock_;
+  std::unique_ptr<base::RepeatingTimer> expiration_timer_;
+  std::unique_ptr<base::RepeatingClosure> timer_closure_;
 
   base::WeakPtrFactory<DecodedImageTracker> weak_ptr_factory_{this};
 };
diff --git a/cc/trees/layer_context.h b/cc/trees/layer_context.h
index 4df30fb..e3c3791 100644
--- a/cc/trees/layer_context.h
+++ b/cc/trees/layer_context.h
@@ -39,7 +39,7 @@
   virtual base::TimeTicks UpdateDisplayTreeFrom(
       LayerTreeImpl& tree,
       viz::ClientResourceProvider& resource_provider,
-      viz::RasterContextProvider& context_provider,
+      viz::RasterContextProvider* context_provider,
       const gfx::Rect& viewport_damage_rect,
       const viz::LocalSurfaceId& target_local_surface_id) = 0;
 
@@ -47,7 +47,7 @@
   virtual void UpdateDisplayTile(PictureLayerImpl& layer,
                                  const Tile& tile,
                                  viz::ClientResourceProvider& resource_provider,
-                                 viz::RasterContextProvider& context_provider,
+                                 viz::RasterContextProvider* context_provider,
                                  bool update_damage) = 0;
 };
 
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
index e71a510..f65ca1a 100644
--- a/cc/trees/layer_tree_host_impl.cc
+++ b/cc/trees/layer_tree_host_impl.cc
@@ -2205,7 +2205,7 @@
     // successfully sent to Viz via UpdateDisplayTree().
     layer_context_->UpdateDisplayTile(
         static_cast<PictureLayerImpl&>(*layer_impl), *tile,
-        *resource_provider(), *layer_tree_frame_sink_->context_provider(),
+        *resource_provider(), layer_tree_frame_sink_->context_provider(),
         update_damage);
   }
 
@@ -3407,7 +3407,7 @@
 
   return layer_context_->UpdateDisplayTreeFrom(
       *active_tree(), *resource_provider(),
-      *layer_tree_frame_sink_->context_provider(), viewport_damage_rect_,
+      layer_tree_frame_sink_->context_provider(), viewport_damage_rect_,
       target_local_surface_id_);
 }
 
diff --git a/chrome/VERSION b/chrome/VERSION
index cc6db4a4..9de6add 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=143
 MINOR=0
-BUILD=7463
+BUILD=7464
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 43ae637..5470f94 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2099,6 +2099,7 @@
       "java/src/org/chromium/chrome/browser/app/serial/SerialNotificationService.java",
       "java/src/org/chromium/chrome/browser/app/usb/UsbNotificationService.java",
       "java/src/org/chromium/chrome/browser/backup/ChromeBackupAgent.java",
+      "java/src/org/chromium/chrome/browser/base/ApplicationInitHook.java",
       "java/src/org/chromium/chrome/browser/base/ColdStartTracker.java",
       "java/src/org/chromium/chrome/browser/base/DexFixer.java",
       "java/src/org/chromium/chrome/browser/base/DexFixerReason.java",
@@ -2180,6 +2181,7 @@
       # TODO(crbug.com/40148088): Consider moving these to the chrome module to
       # reduce base dex size.
       "$google_play_services_package:google_play_services_cast_framework_java",
+      "//base:service_loader_java",
       "//chrome/android/modules/on_demand:provider_java",
       "//components/background_task_scheduler:background_task_scheduler_java",
       "//components/payments/content/android:service_java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupRowView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupRowView.java
index 0a0a8c5..fa84ae1 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupRowView.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupRowView.java
@@ -196,7 +196,7 @@
         return BrowserUiListMenuUtils.getBasicListMenu(
                 getContext(),
                 listItems,
-                (item) -> onItemSelected(item, openRunnable, deleteRunnable, leaveRunnable));
+                (item, view) -> onItemSelected(item, openRunnable, deleteRunnable, leaveRunnable));
     }
 
     private void onItemSelected(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabOverflowMenuCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabOverflowMenuCoordinator.java
index 7829293c..849a146 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabOverflowMenuCoordinator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabOverflowMenuCoordinator.java
@@ -150,7 +150,7 @@
                     createAdapter(
                             modelList,
                             Set.of(),
-                            (model) -> {
+                            (model, view) -> {
                                 // Because ListMenuItemAdapter always uses the delegate if there is
                                 // one, we need to manually call click listeners.
                                 if (model.containsKey(CLICK_LISTENER)
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
index 41303df..98c1ca2e 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceMediator.java
@@ -1441,7 +1441,7 @@
     }
 
     @Override
-    public void onItemSelected(PropertyModel item) {
+    public void onItemSelected(PropertyModel item, View view) {
         assert mSectionHeaderModel != null;
         int itemId = item.get(ListMenuItemProperties.MENU_ITEM_ID);
         int feedType =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java
index e1e3d8c8..5ecae7e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeApplicationImpl.java
@@ -8,6 +8,7 @@
 import android.content.res.Configuration;
 
 import org.chromium.base.BinderCallsListener;
+import org.chromium.base.SysUtils;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.version_info.Channel;
 import org.chromium.base.version_info.VersionConstants;
@@ -57,6 +58,9 @@
             BrowserUiUtilsCachedFlags.getInstance()
                     .setAsyncNotificationManagerFlag(
                             ChromeFeatureList.sAsyncNotificationManager.isEnabled());
+            // TODO(crbug.com/423925400): Remove if finch is initialized earlier
+            SysUtils.setLowMemoryDeviceThresholdMb(
+                    ChromeFeatureList.sLowMemoryDeviceThresholdMb.getValue());
 
             // Only trace Binder IPCs for pre-Beta channels.
             if (VersionConstants.CHANNEL <= Channel.DEV) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/ApplicationInitHook.java b/chrome/android/java/src/org/chromium/chrome/browser/base/ApplicationInitHook.java
new file mode 100644
index 0000000..e802df7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/ApplicationInitHook.java
@@ -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.
+
+package org.chromium.chrome.browser.base;
+
+import org.chromium.build.annotations.NullMarked;
+
+/** ServiceLoader hook for internal code to run during attachBaseContext(). */
+@NullMarked
+public interface ApplicationInitHook {
+    void onAttachBaseContext(boolean isBrowserProcess, boolean isIsolatedProcess);
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
index 38b5afb0..b159b63b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/base/SplitCompatApplication.java
@@ -25,6 +25,7 @@
 import org.chromium.base.LocaleUtils;
 import org.chromium.base.Log;
 import org.chromium.base.PathUtils;
+import org.chromium.base.ServiceLoaderUtil;
 import org.chromium.base.TraceEvent;
 import org.chromium.base.library_loader.LibraryLoader;
 import org.chromium.base.library_loader.LibraryProcessType;
@@ -85,7 +86,7 @@
         private SplitCompatApplication mApplication;
 
         @Initializer
-        private final void setApplication(SplitCompatApplication application) {
+        private void setApplication(SplitCompatApplication application) {
             mApplication = application;
         }
 
@@ -273,6 +274,11 @@
             CustomAssertionHandler.installPreNativeHandler(factory);
         }
 
+        ApplicationInitHook initHook = ServiceLoaderUtil.maybeCreate(ApplicationInitHook.class);
+        if (initHook != null) {
+            initHook.onAttachBaseContext(isBrowserProcess, isIsolatedProcess);
+        }
+
         TraceEvent.end(ATTACH_BASE_CONTEXT_EVENT);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappPermissionStore.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappPermissionStore.java
index c4bce50e..cb916fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappPermissionStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/permissiondelegation/InstalledWebappPermissionStore.java
@@ -4,7 +4,7 @@
 
 package org.chromium.chrome.browser.browserservices.permissiondelegation;
 
-import static org.chromium.components.permissions.PermissionUtil.getGeolocationType;
+import static org.chromium.components.permissions.PermissionsAndroidFeatureList.sApproximateGeolocationPermission;
 
 import android.content.Context;
 import android.content.SharedPreferences;
@@ -190,13 +190,17 @@
         Set<String> origins = getStoredOrigins();
         origins.remove(origin.toString());
 
+        var geolocationType =
+                sApproximateGeolocationPermission.isEnabled()
+                        ? ContentSettingsType.GEOLOCATION_WITH_OPTIONS
+                        : ContentSettingsType.GEOLOCATION;
         mPreferences
                 .edit()
                 .putStringSet(KEY_ALL_ORIGINS, origins)
                 .remove(createPermissionKey(ContentSettingsType.NOTIFICATIONS, origin))
                 .remove(createPermissionSettingKey(ContentSettingsType.NOTIFICATIONS, origin))
-                .remove(createPermissionKey(getGeolocationType(), origin))
-                .remove(createPermissionSettingKey(getGeolocationType(), origin))
+                .remove(createPermissionKey(geolocationType, origin))
+                .remove(createPermissionSettingKey(geolocationType, origin))
                 .remove(createAppNameKey(origin))
                 .remove(createPackageNameKey(origin))
                 .remove(createAllDelegateAppsKey(origin))
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 eb75f2cd..0ae4ab6 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
@@ -356,12 +356,23 @@
                         int oldRootId,
                         @Nullable Token oldTabGroupId,
                         @DidRemoveTabGroupReason int removalReason) {
-                    if (oldTabGroupId != null) clearClosingGroupTitleState(oldTabGroupId);
-                    // dismiss the iph text bubble when the synced tab group is unsynced.
-                    if (mLastSyncedGroupIdForIph != null
-                            && mLastSyncedGroupIdForIph.equals(oldTabGroupId)) {
-                        dismissTabStripSyncIph();
+                    if (oldTabGroupId == null) return;
+
+                    StripLayoutGroupTitle groupTitle = findGroupTitle(oldTabGroupId);
+                    // TODO(crbug.com/443337907) If we're closing for a close button click, we don't
+                    // want to
+                    //  clobber the existing animations. This check can be removed once we update
+                    // the tab strip
+                    //  close button clicks to immediately remove from the model.
+                    if (!mCloseAnimationsRequested || groupTitle == null || groupTitle.isDying()) {
+                        clearClosingGroupTitleState(oldTabGroupId);
+                    } else {
+                        mClosingGroupTitles.add(groupTitle);
+                        requestCloseAnimations();
                     }
+
+                    // Dismiss the iph text bubble when the synced tab group is unsynced.
+                    if (oldTabGroupId.equals(mLastSyncedGroupIdForIph)) dismissTabStripSyncIph();
                     onWillCloseView(
                             StripLayoutUtils.findGroupTitle(mStripGroupTitles, oldTabGroupId));
                 }
@@ -387,7 +398,6 @@
                     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
                     // below.
@@ -473,6 +483,10 @@
     private @Nullable Animator mRunningAnimator;
     private final List<Animator> mQueuedAnimators = new ArrayList<>();
 
+    private boolean mCloseAnimationsRequested;
+    private final Set<StripLayoutTab> mClosingTabs = new HashSet<>();
+    private final Set<StripLayoutGroupTitle> mClosingGroupTitles = new HashSet<>();
+
     private final TintedCompositorButton mNewTabButton;
     private final @Nullable CompositorButton mModelSelectorButton;
 
@@ -618,7 +632,6 @@
     private final StripLayoutTabDelegate mTabDelegate;
 
     // Pinned tabs.
-    private int mPinnedTabCount;
     private boolean mIsPinnedOnlyStripRecorded;
 
     @FunctionalInterface
@@ -1446,8 +1459,8 @@
         // 3. Update tab spinners.
         updateSpinners(time);
 
+        queueCloseAnimationsIfAny();
         startQueuedAnimationsIfAny();
-        final boolean doneAnimating = mRunningAnimator == null || !mRunningAnimator.isRunning();
         updateStrip();
 
         // If this is the first layout pass, scroll to the selected tab so that it is visible.
@@ -1475,6 +1488,7 @@
         }
 
         // 4. Attempt to show one iph text bubble at a time on tab strip.
+        final boolean doneAnimating = mRunningAnimator == null || !mRunningAnimator.isRunning();
         if (doneAnimating && mScrollDelegate.isFinished()) {
             Iterator<QueuedIph> iterator = mQueuedIphList.iterator();
             while (iterator.hasNext()) {
@@ -1588,7 +1602,6 @@
      */
     public void tabSelected(long time, int id, int prevId) {
         StripLayoutTab stripTab = findTabById(id);
-
         if (stripTab == null) {
             tabCreated(time, id, prevId, true, false, false);
             updateSelectedTab(id, prevId);
@@ -1668,8 +1681,18 @@
      * @param tabs The list of tabs that are being closed.
      */
     public void multipleTabsClosed(List<Tab> tabs) {
-        rebuildStripTabs(/* deferAnimations= */ false);
-        clearPendingMouseTabClosureState();
+        for (Tab tab : tabs) {
+            StripLayoutTab stripTab = findTabById(tab.getId());
+            if (stripTab != null && !stripTab.isDying()) mClosingTabs.add(stripTab);
+        }
+        if (!mClosingTabs.isEmpty()) {
+            requestCloseAnimations();
+        } else {
+            // TODO(crbug.com/443337907): Can be removed once we update the tab strip close buttons
+            //  to this new animation method.
+            rebuildStripTabs(/* deferAnimations= */ false);
+            clearPendingMouseTabClosureState();
+        }
     }
 
     /** Called when all tabs are closed at once. */
@@ -1686,8 +1709,10 @@
      */
     public void tabClosureCancelled(long time, int id) {
         if (mModel == null) return;
+        finishAnimations();
         final boolean selected = TabModelUtils.getCurrentTabId(mModel) == id;
         tabCreated(time, id, Tab.INVALID_TAB_ID, selected, true, false);
+        updateGroupTextAndSharedState(mModel.getTabByIdChecked(id).getTabGroupId());
     }
 
     /**
@@ -2892,6 +2917,16 @@
                 ANIM_TAB_CLOSED_MS);
     }
 
+    private Animator getViewWidthAnimator(StripLayoutView view, float targetWidth, int duration) {
+        return CompositorAnimator.ofFloatProperty(
+                mUpdateHost.getAnimationHandler(),
+                view,
+                StripLayoutView.WIDTH,
+                view.getWidth(),
+                targetWidth,
+                duration);
+    }
+
     private List<Animator> getTabClosingAnimators(Collection<StripLayoutTab> tabs) {
         if (ChromeFeatureList.sTabletTabStripAnimation.isEnabled()) {
             // computeAndUpdateTabWidth handles animating a tab closing.
@@ -3528,6 +3563,80 @@
         mUpdateHost.requestUpdate();
     }
 
+    private void requestCloseAnimations() {
+        finishAnimations();
+        mCloseAnimationsRequested = true;
+        mUpdateHost.requestUpdate();
+    }
+
+    private void queueCloseAnimationsIfAny() {
+        if (!mCloseAnimationsRequested) return;
+        mCloseAnimationsRequested = false;
+
+        // TODO(crbug.com/450076798): Unify closing tabs + closing group titles logic.
+        // Set initial state.
+        for (StripLayoutView view : mClosingTabs) view.setIsDying(true);
+        for (StripLayoutView view : mClosingGroupTitles) view.setIsDying(true);
+
+        // Create animators.
+        List<Animator> animationList = getTabClosingAnimators(mClosingTabs);
+        if (ChromeFeatureList.sTabletTabStripAnimation.isEnabled()) {
+            for (StripLayoutGroupTitle groupTitle : mClosingGroupTitles) {
+                animationList.add(
+                        getViewWidthAnimator(
+                                groupTitle, mGroupTitleOverlapWidth, ANIM_TAB_CLOSED_MS));
+            }
+        }
+
+        // Queue the animations.
+        queueAnimations(
+                animationList,
+                new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        // Reset any closing-related state on the closing views before they are
+                        // reused in the following rebuild.
+                        resetClosingViewsState();
+                        boolean runImprovedTabAnimations = mStripTabs.length > 1;
+                        rebuildStripTabs(/* deferAnimations= */ false);
+                        if (!ChromeFeatureList.sTabletTabStripAnimation.isEnabled()) {
+                            resizeStripOnTabClose(runImprovedTabAnimations);
+                        }
+                        clearStateOnCloseAnimationsEnd();
+                    }
+                });
+    }
+
+    private void resetClosingViewsState() {
+        // TODO(crbug.com/443337907): If the tab closure(s) are cancelled, we are notified after the
+        //  Tabs are already readded to the TabModel. This causes us to reuse these (stale) closing
+        //  views in the subsequent rebuild. As a temporary fix, we manually reset the relevant
+        //  state here. A longer term fix would be to be notified of the cancellation earlier in the
+        //  flow so we can #finishAnimations and rebuild without these closing views, so that we
+        //  don't end up reusing these stale views (and having to clear this state). e.g., add some
+        //  #willCancelTabClosure event.
+        for (StripLayoutGroupTitle groupTitle : mClosingGroupTitles) {
+            groupTitle.setIsDying(/* isDying= */ false);
+            groupTitle.setWillClose(/* willClose= */ false);
+        }
+        for (StripLayoutTab tab : mClosingTabs) {
+            tab.setOffsetY(/* offsetY= */ 0);
+            tab.setDrawY(/* y= */ 0);
+            tab.setIsDying(/* isDying= */ false);
+            tab.setWillClose(/* willClose= */ false);
+            tab.setIsClosed(/* isClosed= */ false);
+        }
+    }
+
+    private void clearStateOnCloseAnimationsEnd() {
+        for (StripLayoutGroupTitle groupTitle : mClosingGroupTitles) {
+            clearClosingGroupTitleState(groupTitle.getTabGroupId());
+        }
+        clearPendingMouseTabClosureState();
+        mClosingTabs.clear();
+        mClosingGroupTitles.clear();
+    }
+
     private AnimatorSet getAnimatorSet(
             @Nullable List<Animator> animationList, @Nullable AnimatorListener listener) {
         AnimatorSet set = new AnimatorSet();
@@ -3649,32 +3758,21 @@
         final int count = mModel.getCount();
         StripLayoutTab[] tabs = new StripLayoutTab[count];
 
-        int oldPinnedTabCount = mPinnedTabCount;
-        mPinnedTabCount = 0;
         for (int i = 0; i < count; i++) {
             final Tab tab = assumeNonNull(mModel.getTabAt(i));
             final int id = tab.getId();
             final StripLayoutTab oldTab = findTabById(id);
             boolean isPinned = isTabPinningFromStripEnabled() && tab.getIsPinned();
             tabs[i] = oldTab != null ? oldTab : createStripTab(id, isPinned);
-            mPinnedTabCount += isPinned ? 1 : 0;
             setAccessibilityDescription(tabs[i], tab);
         }
 
-        int oldTabsLength = mStripTabs.length;
         mStripTabs = tabs;
         // Update stripViews since tabs are updated.
         rebuildStripViews();
 
-        // If the number of tabs did not change, no action is required. If a tab close is animating,
-        // the resize may be handled elsewhere.
-        if (mPinnedTabCount == oldPinnedTabCount
-                && (mStripTabs.length == oldTabsLength
-                        || mMultiStepTabCloseAnimRunning
-                        || mPendingMouseTabClosure)) {
-            return null;
-        }
-
+        // If a tab close is animating, the resize may be handled elsewhere.
+        if (mMultiStepTabCloseAnimRunning || mPendingMouseTabClosure) return null;
         recordPinnedOnlyTabStripUserAction();
 
         // Otherwise, animate the required width changes.
@@ -3774,13 +3872,7 @@
             return null;
         }
 
-        return CompositorAnimator.ofFloatProperty(
-                mUpdateHost.getAnimationHandler(),
-                tab,
-                StripLayoutTab.WIDTH,
-                tab.getWidth(),
-                TAB_OVERLAP_WIDTH_DP,
-                ANIM_TAB_RESIZE_MS);
+        return getViewWidthAnimator(tab, TAB_OVERLAP_WIDTH_DP, ANIM_TAB_RESIZE_MS);
     }
 
     private void updateTabGroupCollapsed(
@@ -4452,6 +4544,7 @@
         float stripWidth = getStripWidthForResizing();
         for (int i = 0; i < mStripGroupTitles.length; i++) {
             final StripLayoutGroupTitle groupTitle = mStripGroupTitles[i];
+            if (groupTitle.isDying()) continue;
             stripWidth -= (groupTitle.getWidth() - mGroupTitleOverlapWidth);
         }
         return stripWidth - getTotalPinnedTabsWidth();
@@ -4506,25 +4599,17 @@
         if (animate) resizeAnimationList = new ArrayList<>();
         for (int i = 0; i < mStripTabs.length; i++) {
             StripLayoutTab tab = mStripTabs[i];
-            if (tab.isClosed()) tab.setWidth(TAB_OVERLAP_WIDTH_DP);
             if ((tab.isDying() && !ChromeFeatureList.sTabletTabStripAnimation.isEnabled())
                     || tab.isCollapsed()) {
                 continue;
             }
             float cachedTabWidth = getCachedTabWidth(tab.getIsPinned());
             if (resizeAnimationList != null) {
-                CompositorAnimator animator;
                 // Handle animating a tab being closed for TabletTabStripAnimation.
                 if (tab.isDying()) {
-                    animator =
-                            CompositorAnimator.ofFloatProperty(
-                                    mUpdateHost.getAnimationHandler(),
-                                    tab,
-                                    StripLayoutTab.WIDTH,
-                                    tab.getWidth(),
-                                    TAB_OVERLAP_WIDTH_DP,
-                                    NEW_ANIM_TAB_RESIZE_MS);
-                    resizeAnimationList.add(animator);
+                    resizeAnimationList.add(
+                            getViewWidthAnimator(
+                                    tab, TAB_OVERLAP_WIDTH_DP, NEW_ANIM_TAB_RESIZE_MS));
                     continue;
                 }
 
@@ -4533,21 +4618,11 @@
                     continue;
                 }
 
-                int duration = ANIM_TAB_RESIZE_MS;
-
-                if (ChromeFeatureList.sTabletTabStripAnimation.isEnabled()) {
-                    duration = NEW_ANIM_TAB_RESIZE_MS;
-                }
-                animator =
-                        CompositorAnimator.ofFloatProperty(
-                                mUpdateHost.getAnimationHandler(),
-                                tab,
-                                StripLayoutTab.WIDTH,
-                                tab.getWidth(),
-                                cachedTabWidth,
-                                duration);
-
-                resizeAnimationList.add(animator);
+                int duration =
+                        ChromeFeatureList.sTabletTabStripAnimation.isEnabled()
+                                ? NEW_ANIM_TAB_RESIZE_MS
+                                : ANIM_TAB_RESIZE_MS;
+                resizeAnimationList.add(getViewWidthAnimator(tab, cachedTabWidth, duration));
             } else {
                 mStripTabs[i].setWidth(cachedTabWidth);
             }
@@ -5266,6 +5341,14 @@
         return mDelayedReorderView;
     }
 
+    Set<StripLayoutTab> getClosingTabsForTesting() {
+        return mClosingTabs;
+    }
+
+    Set<StripLayoutGroupTitle> getClosingGroupTitlesForTesting() {
+        return mClosingGroupTitles;
+    }
+
     @Nullable Animator getRunningAnimatorForTesting() {
         return mRunningAnimator;
     }
@@ -5563,7 +5646,7 @@
     private void onWillCloseView(@Nullable StripLayoutView view) {
         if (view == null) return;
 
-        view.setWillClose();
+        view.setWillClose(/* willClose= */ true);
         if (view == mDelayedReorderView) resetDelayedReorderState();
         if (view == mReorderDelegate.getInteractingView()) stopReorderMode();
     }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java
index 7b65d47..39dd86c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutView.java
@@ -372,8 +372,8 @@
     }
 
     /** Marks that the view will be closed due to an incoming TabModel update. */
-    public void setWillClose() {
-        mWillClose = true;
+    public void setWillClose(boolean willClose) {
+        mWillClose = willClose;
     }
 
     /** Returns whether or not the view will be closed due to an incoming TabModel update. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
index eea1904d..339a087 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
@@ -407,6 +407,10 @@
 
         mDialogs.subList(clearFromIndex, mDialogs.size()).clear();
         mListViews.subList(clearFromIndex, mListViews.size()).clear();
+
+        if (mDialogs.size() > 0) {
+            mDialogs.get(mDialogs.size() - 1).popupWindow.setWindowFocus(true);
+        }
     }
 
     @Override
@@ -444,7 +448,12 @@
                             }
                         });
 
+        assert mDialogs.size() > 0;
+        mDialogs.get(mDialogs.size() - 1).popupWindow.setWindowFocus(false);
+
+        dialog.setWindowFocus(true);
         dialog.show();
+
         mDialogs.add(new FlyoutPopupEntry(item, dialog));
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemWithIconButtonProperties.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemWithIconButtonProperties.java
index f4edd659..3ae1563 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemWithIconButtonProperties.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuItemWithIconButtonProperties.java
@@ -4,6 +4,8 @@
 
 package org.chromium.chrome.browser.contextmenu;
 
+import static org.chromium.ui.listmenu.ListMenuItemProperties.KEY_LISTENER;
+
 import android.graphics.drawable.Drawable;
 import android.view.View;
 
@@ -35,6 +37,7 @@
                 CLICK_LISTENER,
                 HOVER_LISTENER,
                 IS_HIGHLIGHTED,
+                KEY_LISTENER,
                 START_ICON_DRAWABLE
             };
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
index c1c3b746..97612f6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbar.java
@@ -1903,23 +1903,18 @@
         public void showBrandingLocationBar() {
             mBrandingStarted = true;
 
-            if (ChromeFeatureList.sCctRevampedBranding.isEnabled()) {
-                ViewStub stub = findViewById(R.id.branding_stub);
+            ViewStub stub = findViewById(R.id.branding_stub);
+            if (stub != null) {
+                PropertyModel model =
+                        new PropertyModel.Builder(ToolbarBrandingOverlayProperties.ALL_KEYS)
+                                .with(
+                                        ToolbarBrandingOverlayProperties.COLOR_DATA,
+                                        new ToolbarBrandingOverlayProperties.ColorData(
+                                                getBackground().getColor(), mBrandedColorScheme))
+                                .build();
+                mBrandingOverlayCoordinator = new ToolbarBrandingOverlayCoordinator(stub, model);
 
-                if (stub != null) {
-                    PropertyModel model =
-                            new PropertyModel.Builder(ToolbarBrandingOverlayProperties.ALL_KEYS)
-                                    .with(
-                                            ToolbarBrandingOverlayProperties.COLOR_DATA,
-                                            new ToolbarBrandingOverlayProperties.ColorData(
-                                                    getBackground().getColor(),
-                                                    mBrandedColorScheme))
-                                    .build();
-                    mBrandingOverlayCoordinator =
-                            new ToolbarBrandingOverlayCoordinator(stub, model);
-
-                    return;
-                }
+                return;
             }
 
             // Store the title and domain setting, if the empty state is not in used. Otherwise
@@ -1955,10 +1950,8 @@
         public void showRegularToolbar() {
             mCurrentlyShowingBranding = false;
 
-            if (ChromeFeatureList.sCctRevampedBranding.isEnabled()) {
-                if (mBrandingOverlayCoordinator != null) {
-                    mBrandingOverlayCoordinator.hideAndDestroy();
-                }
+            if (mBrandingOverlayCoordinator != null) {
+                mBrandingOverlayCoordinator.hideAndDestroy();
             }
 
             recoverFromRegularState();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
index 72bfad2..3254e0c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/ContextMenuManager.java
@@ -267,7 +267,7 @@
                 BrowserUiListMenuUtils.getBasicListMenu(
                         mAnchorView.getContext(),
                         menuModel,
-                        model ->
+                        (model, view) ->
                                 handleMenuItemClick(
                                         model.get(ListMenuItemProperties.MENU_ITEM_ID), delegate));
         mListContextMenu = new ListMenuHost(mAnchorView, null);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/selection/ChromeSelectionDropdownMenuDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/selection/ChromeSelectionDropdownMenuDelegate.java
index 6f693944..f8b6dee 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/selection/ChromeSelectionDropdownMenuDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/selection/ChromeSelectionDropdownMenuDelegate.java
@@ -47,7 +47,8 @@
 
         Rect dropdownRect = new Rect(x, y, x + 1, y + 1);
         BasicListMenu menu =
-                BrowserUiListMenuUtils.getBasicListMenu(context, items, clickListener::onItemClick);
+                BrowserUiListMenuUtils.getBasicListMenu(
+                        context, items, (model, view) -> clickListener.onItemClick(model));
 
         mPopupWindow =
                 new AnchoredPopupWindow(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MultiColumnSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MultiColumnSettings.java
index 26e9d187..cda32f3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MultiColumnSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MultiColumnSettings.java
@@ -97,11 +97,21 @@
         // Update the detail pane, if the intent is specified.
         Fragment fragment = processPendingFragmentIntent();
         if (fragment != null) {
-            getChildFragmentManager()
+            // Opening a new page. If we already have back stack entries, clean it up for
+            // - back button behavior
+            // - detailed page title
+            var fragmentManager = getChildFragmentManager();
+            if (fragmentManager.getBackStackEntryCount() > 0) {
+                var entry = fragmentManager.getBackStackEntryAt(0);
+                fragmentManager.popBackStack(
+                        entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
+            }
+
+            // Then, open the fragment.
+            fragmentManager
                     .beginTransaction()
                     .setReorderingAllowed(true)
                     .replace(R.id.preferences_detail, fragment)
-                    .addToBackStack(null)
                     .commit();
             getSlidingPaneLayout().open();
         }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
index a96da7c..e98b5c5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperTest.java
@@ -126,6 +126,7 @@
 import org.chromium.chrome.browser.tabmodel.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabGroupModelFilter;
 import org.chromium.chrome.browser.tabmodel.TabGroupModelFilterObserver;
+import org.chromium.chrome.browser.tabmodel.TabGroupModelFilterObserver.DidRemoveTabGroupReason;
 import org.chromium.chrome.browser.tabmodel.TabGroupTitleUtils;
 import org.chromium.chrome.browser.tabmodel.TabModelActionListener;
 import org.chromium.chrome.browser.tabmodel.TabModelActionListener.DialogType;
@@ -835,6 +836,55 @@
     }
 
     @Test
+    public void testQueueAnimationsForNonStripClosures() {
+        // Disable testing mode so we can queue animations. Initialize and group first two tabs.
+        CompositorAnimationHandler.setTestingMode(/* enabled= */ false);
+        initializeTest(false, false, 0);
+        groupTabs(0, 2, TAB_GROUP_ID_1);
+
+        // Notify tab closures and verify state.
+        List<Tab> closingTabs = new ArrayList<>();
+        closingTabs.add(mModel.getTabAt(0));
+        closingTabs.add(mModel.getTabAt(1));
+        mModel.closeTabs(TabClosureParams.closeTabs(closingTabs).build());
+        mStripLayoutHelper.multipleTabsClosed(closingTabs);
+        int numClosingTabs = mStripLayoutHelper.getClosingTabsForTesting().size();
+        assertEquals("Should have two closing tabs.", 2, numClosingTabs);
+
+        // Notify group removal and verify state.
+        when(mTabGroupModelFilter.isTabInTabGroup(any())).thenReturn(false);
+        mStripLayoutHelper
+                .getTabGroupModelFilterObserverForTesting()
+                .didRemoveTabGroup(
+                        Tab.INVALID_TAB_ID, TAB_GROUP_ID_1, DidRemoveTabGroupReason.CLOSE);
+        int numClosingGroupTitles = mStripLayoutHelper.getClosingGroupTitlesForTesting().size();
+        assertEquals("Should have one closing group title.", 1, numClosingGroupTitles);
+
+        // Verify no animations have started yet.
+        assertNull(
+                "Animations should not yet be started.",
+                mStripLayoutHelper.getRunningAnimatorForTesting());
+
+        // Update layout. Verify the queued animations have been started, and the views have not yet
+        // been removed.
+        mStripLayoutHelper.updateLayout(TIMESTAMP);
+        assertNotNull(
+                "Animations should now be started.",
+                mStripLayoutHelper.getRunningAnimatorForTesting());
+        assertEquals(
+                "Closed views should still be present while the animations are running.",
+                6,
+                mStripLayoutHelper.getStripLayoutViewsForTesting().length);
+
+        // Finish animations, then verify the closing views have been removed.
+        mStripLayoutHelper.finishAnimations();
+        assertEquals(
+                "Closed views should no longer be present.",
+                3,
+                mStripLayoutHelper.getStripLayoutViewsForTesting().length);
+    }
+
+    @Test
     @Feature("Pinned Tabs")
     public void testTabSelected_Pinned_HideCloseBtn() {
         initializeTest(false, true, 3);
@@ -2605,14 +2655,13 @@
                 "MultiStepAnimations should still be running.",
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
-        // Act: Set animation time forward by 250ms for next set of animations.
-        mStripLayoutHelper.getRunningAnimatorForTesting().end();
-
         // Act: End the animations to apply final values.
+        mStripLayoutHelper.finishAnimations();
+
+        // Act: Fake the tab closure and end the animation, so the tab is removed from the model.
         Tab closingTab = mModel.getTabAt(2);
-        Animator runningAnimator = mStripLayoutHelper.getRunningAnimatorForTesting();
-        runningAnimator.end();
         mStripLayoutHelper.tabClosed(closingTab);
+        mStripLayoutHelper.finishAnimations();
 
         // availableSize = width(800) - NTB(32) - endPadding(8) - offsetXLeft(10) - offsetXRight(20)
         // - groupTitleWidth(46) - titleOverlapWidth(4) = 680.
@@ -3604,6 +3653,7 @@
     public void testTabClosed() {
         // Initialize with 10 tabs.
         int tabCount = 10;
+        setupForAnimations();
         initializeTest(false, false, 0, tabCount);
         mStripLayoutHelper.onSizeChanged(
                 SCREEN_WIDTH, SCREEN_HEIGHT, false, TIMESTAMP, PADDING_LEFT, PADDING_RIGHT, 0f);
@@ -3622,12 +3672,13 @@
         // Trigger update and verify the tab strip matches the tab model.
         expectedNumTabs = 9;
         mStripLayoutHelper.tabClosed(tab);
+        mStripLayoutHelper.finishAnimations();
         assertEquals(
                 "Tab strip should match tab model.",
                 expectedNumTabs,
                 mStripLayoutHelper.getStripLayoutTabsForTesting().length);
-        verify(mUpdateHost, times(5)).requestUpdate();
-        verify(mUpdateHost, times(3)).requestUpdate(any());
+        verify(mUpdateHost, times(9)).requestUpdate();
+        verify(mUpdateHost, times(4)).requestUpdate(any());
     }
 
     @Test
@@ -3689,7 +3740,7 @@
 
         // Act
         mStripLayoutHelper.handleCloseButtonClick(tabs[selectedTabIndex], motionEventButtonState);
-        mStripLayoutHelper.getRunningAnimatorForTesting().end(); // end the closing animation
+        mStripLayoutHelper.finishAnimations(); // end the closing animation
 
         // Assert
         TestTabRemover testTabRemover = (TestTabRemover) mModel.getTabRemover();
@@ -3721,10 +3772,9 @@
                 "MultiStepAnimations should have started.",
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
-        // Act: End the tab closing animations to apply final values.
+        // Act: Only end the first animation, so the multi-step animations are still running.
         Tab closingTab = mModel.getTabAt(14);
-        Animator runningAnimator = mStripLayoutHelper.getRunningAnimatorForTesting();
-        runningAnimator.end();
+        mStripLayoutHelper.getRunningAnimatorForTesting().end();
         mStripLayoutHelper.tabClosed(closingTab);
 
         // Assert: Tab is closed and animations are still running.
@@ -3738,7 +3788,7 @@
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
         // Act: End next set of animations to apply final values.
-        mStripLayoutHelper.getRunningAnimatorForTesting().end();
+        mStripLayoutHelper.finishAnimations();
 
         // Assert: Animations completed. The tab width is not resized and drawX does not change.
         // stripRightBound = width(800) - offsetXRight(20) = 780;
@@ -3780,10 +3830,9 @@
                 "MultiStepAnimations should have started.",
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
-        // Act: End the animations to apply final values.
+        // Act: Only end the first animation, so the multi-step animations are still running.
         Tab closingTab = mModel.getTabAt(2);
-        Animator runningAnimator = mStripLayoutHelper.getRunningAnimatorForTesting();
-        runningAnimator.end();
+        mStripLayoutHelper.getRunningAnimatorForTesting().end();
         mStripLayoutHelper.tabClosed(closingTab);
 
         // Assert: Tab is closed and animations are still running.
@@ -3793,8 +3842,8 @@
                 "MultiStepAnimations should still be running.",
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
-        // Act: Set animation time forward by 250ms for next set of animations.
-        mStripLayoutHelper.getRunningAnimatorForTesting().end();
+        // Act: Finish the remaining animations.
+        mStripLayoutHelper.finishAnimations();
 
         // Assert: Animations completed. The tab width is resized, tab.drawX is changed and
         // newTabButton.drawX is also changed.
@@ -3832,8 +3881,7 @@
                 tabs[2], MotionEventUtils.MOTION_EVENT_BUTTON_NONE);
 
         // End the tab closure animation.
-        var runningAnimator = mStripLayoutHelper.getRunningAnimatorForTesting();
-        runningAnimator.end();
+        mStripLayoutHelper.finishAnimations();
 
         verify(mTabHoverCardView).hide();
     }
@@ -3863,11 +3911,13 @@
     @EnableFeatures(ChromeFeatureList.TAB_STRIP_MOUSE_CLOSE_RESIZE_DELAY)
     public void testPendingMouseTabClosure_ClearOnTabClosure() {
         // Initialize and mark a pending a mouse tab closure.
+        setupForAnimations();
         initializeTest(/* tabIndex= */ 0);
         mStripLayoutHelper.setPendingMouseTabClosureForTesting(true);
 
         // Fake a tab closure.
         mStripLayoutHelper.tabClosed(mModel.getTabAt(0));
+        mStripLayoutHelper.finishAnimations();
 
         // Verify state is cleared.
         verifyPendingMouseTabClosure(/* expectedPendingMouseTabClosure= */ false);
@@ -4573,9 +4623,7 @@
 
         mStripLayoutHelper.updateGroupTextAndSharedState(tabGroupId);
         mStripLayoutHelper.rebuildStripViews();
-        if (mStripLayoutHelper.getRunningAnimatorForTesting() != null) {
-            mStripLayoutHelper.getRunningAnimatorForTesting().end();
-        }
+        mStripLayoutHelper.finishAnimations();
     }
 
     private void setTabStripDragHandlerMock() {
@@ -5986,11 +6034,9 @@
                 "MultiStepAnimations should not have started.",
                 mStripLayoutHelper.isMultiStepCloseAnimationsRunningForTesting());
 
-        // Act: End the tab closing animations to apply final values.
+        // Act: Fake the tab closure and end the animation, so the tab is removed from the model.
         Tab closingTab = mModel.getTabAt(9);
-        Animator runningAnimator = mStripLayoutHelper.getRunningAnimatorForTesting();
-        assertNotNull(runningAnimator);
-        runningAnimator.end();
+        mStripLayoutHelper.finishAnimations();
         mStripLayoutHelper.tabClosed(closingTab);
 
         // Assert: Tab is closed.
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
index 12ffa71..7efebb6 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/features/toolbar/CustomTabToolbarUnitTest.java
@@ -577,30 +577,14 @@
     }
 
     @Test
-    @DisableFeatures({
-        ChromeFeatureList.CCT_REVAMPED_BRANDING,
-        ChromeFeatureList.CCT_NESTED_SECURITY_ICON
-    })
-    public void testSecurityIconVisibility() {
-        assertEquals(View.INVISIBLE, mSecurityButton.getVisibility());
-        assertEquals(View.GONE, mSecurityIcon.getVisibility());
-    }
-
-    @Test
-    @EnableFeatures({
-        ChromeFeatureList.CCT_REVAMPED_BRANDING,
-        ChromeFeatureList.CCT_NESTED_SECURITY_ICON
-    })
+    @EnableFeatures({ChromeFeatureList.CCT_NESTED_SECURITY_ICON})
     public void testSecurityIconVisibility_nestedIcon() {
         assertEquals(View.GONE, mSecurityButton.getVisibility());
         assertEquals(View.INVISIBLE, mSecurityIcon.getVisibility());
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.CCT_REVAMPED_BRANDING,
-        ChromeFeatureList.CCT_NESTED_SECURITY_ICON
-    })
+    @EnableFeatures({ChromeFeatureList.CCT_NESTED_SECURITY_ICON})
     public void testSecurityIconHidden() {
         when(mLocationBarModel.getSecurityIconResource(anyBoolean()))
                 .thenReturn(R.drawable.omnibox_https_valid_page_info);
@@ -612,10 +596,7 @@
     }
 
     @Test
-    @EnableFeatures({
-        ChromeFeatureList.CCT_REVAMPED_BRANDING,
-        ChromeFeatureList.CCT_NESTED_SECURITY_ICON
-    })
+    @EnableFeatures({ChromeFeatureList.CCT_NESTED_SECURITY_ICON})
     public void testSecurityIconShown() {
         when(mLocationBarModel.getSecurityIconResource(anyBoolean()))
                 .thenReturn(R.drawable.omnibox_not_secure_warning);
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 321eff4..b8f9d89 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1192,7 +1192,6 @@
 
 const FeatureEntry::FeatureParam kPageActionsMigrationParams[] = {
     {"autofill_address", "true"},
-    {"cookie_controls", "true"},
     {"click_to_call", "true"},
     {"collaboration_messaging", "true"},
     {"discounts", "true"},
@@ -6542,6 +6541,10 @@
      flag_descriptions::kAndroidGrammarCheckName,
      flag_descriptions::kAndroidGrammarCheckDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(spellcheck::kAndroidGrammarCheck)},
+    {"enable-android-media-insertion",
+     flag_descriptions::kAndroidMediaInsertionName,
+     flag_descriptions::kAndroidMediaInsertionDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kAndroidMediaInsertion)},
     {"enable-android-spellcheck-native-ui",
      flag_descriptions::kAndroidSpellcheckNativeUiName,
      flag_descriptions::kAndroidSpellcheckNativeUiDescription, kOsAndroid,
@@ -8263,9 +8266,6 @@
     {"cct-navigation-metrics", flag_descriptions::kCCTNavigationMetricsName,
      flag_descriptions::kCCTNavigationMetricsDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kCCTNavigationMetrics)},
-    {"cct-revamped-branding", flag_descriptions::kCCTRevampedBrandingName,
-     flag_descriptions::kCCTRevampedBrandingDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::kCCTRevampedBranding)},
     {"cct-nested-security-icon", flag_descriptions::kCCTNestedSecurityIconName,
      flag_descriptions::kCCTNestedSecurityIconDescription, kOsAndroid,
      FEATURE_VALUE_TYPE(chrome::android::kCCTNestedSecurityIcon)},
diff --git a/chrome/browser/ai/ai_rewriter.cc b/chrome/browser/ai/ai_rewriter.cc
index 2dfa8c7..eedaa00 100644
--- a/chrome/browser/ai/ai_rewriter.cc
+++ b/chrome/browser/ai/ai_rewriter.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ai/ai_rewriter.h"
 
+#include "base/containers/fixed_flat_set.h"
 #include "base/functional/bind.h"
 #include "base/notimplemented.h"
 #include "base/strings/string_util.h"
diff --git a/chrome/browser/ai/ai_summarizer.h b/chrome/browser/ai/ai_summarizer.h
index 37d18c7..ef2c8c4 100644
--- a/chrome/browser/ai/ai_summarizer.h
+++ b/chrome/browser/ai/ai_summarizer.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_AI_AI_SUMMARIZER_H_
 #define CHROME_BROWSER_AI_AI_SUMMARIZER_H_
 
-#include "base/containers/fixed_flat_set.h"
+#include "base/containers/flat_set.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/ai/ai_context_bound_object.h"
 #include "chrome/browser/ai/ai_on_device_session.h"
diff --git a/chrome/browser/ai/ai_utils.h b/chrome/browser/ai/ai_utils.h
index 5389406b..79d9bfb 100644
--- a/chrome/browser/ai/ai_utils.h
+++ b/chrome/browser/ai/ai_utils.h
@@ -5,7 +5,7 @@
 #ifndef CHROME_BROWSER_AI_AI_UTILS_H_
 #define CHROME_BROWSER_AI_AI_UTILS_H_
 
-#include "base/containers/fixed_flat_set.h"
+#include "base/containers/flat_set.h"
 #include "base/metrics/field_trial_params.h"
 #include "components/optimization_guide/core/model_execution/optimization_guide_model_execution_error.h"
 #include "mojo/public/cpp/bindings/remote_set.h"
diff --git a/chrome/browser/ai/ai_writer.cc b/chrome/browser/ai/ai_writer.cc
index 1b4c4dc6..c4228f5 100644
--- a/chrome/browser/ai/ai_writer.cc
+++ b/chrome/browser/ai/ai_writer.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/ai/ai_writer.h"
 
+#include "base/containers/fixed_flat_set.h"
 #include "base/functional/bind.h"
 #include "base/strings/strcat.h"
 #include "base/strings/utf_string_conversions.h"
diff --git a/chrome/browser/ash/app_mode/test/BUILD.gn b/chrome/browser/ash/app_mode/test/BUILD.gn
index 7a58187..88730eb 100644
--- a/chrome/browser/ash/app_mode/test/BUILD.gn
+++ b/chrome/browser/ash/app_mode/test/BUILD.gn
@@ -105,6 +105,7 @@
     "//chrome/test:test_support_ui",
     "//chromeos/ash/components/network:test_support",
     "//chromeos/ash/components/policy/device_local_account",
+    "//chromeos/ash/experiences/settings_ui",
     "//components/web_package",
   ]
 }
diff --git a/chrome/browser/ash/app_mode/test/kiosk_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_browsertest.cc
index b661a61b..c4459d34 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_browsertest.cc
+++ b/chrome/browser/ash/app_mode/test/kiosk_browsertest.cc
@@ -31,6 +31,7 @@
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
+#include "components/user_manager/user_manager.h"
 #include "content/public/test/browser_test.h"
 #include "extensions/browser/app_window/app_window.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -119,14 +120,16 @@
 }
 
 IN_PROC_BROWSER_TEST_P(KioskTest, CanOpenA11ySettings) {
-  Browser* settings = OpenA11ySettings(CurrentProfile());
+  Browser* settings = OpenA11ySettings(
+      CHECK_DEREF(user_manager::UserManager::Get()->GetActiveUser()));
   ASSERT_NE(settings, nullptr);
   EXPECT_TRUE(settings->window()->IsActive());
   EXPECT_TRUE(settings->window()->IsVisible());
 }
 
 IN_PROC_BROWSER_TEST_P(KioskTest, ExitsIfOnlySettingsWindowRemainsOpen) {
-  Browser& settings = CHECK_DEREF(OpenA11ySettings(CurrentProfile()));
+  Browser& settings = CHECK_DEREF(OpenA11ySettings(
+      CHECK_DEREF(user_manager::UserManager::Get()->GetActiveUser())));
   EXPECT_GT(BrowserList::GetInstance()->size(), 0u);
 
   // Close the app window and verify the settings browser gets closed too.
@@ -139,7 +142,8 @@
 }
 
 IN_PROC_BROWSER_TEST_P(KioskTest, DoesNotExitWhenSettingsWindowCloses) {
-  Browser& settings = CHECK_DEREF(OpenA11ySettings(CurrentProfile()));
+  Browser& settings = CHECK_DEREF(OpenA11ySettings(
+      CHECK_DEREF(user_manager::UserManager::Get()->GetActiveUser())));
   EXPECT_EQ(GetLastActiveBrowserWindowInterfaceWithAnyProfile(), &settings);
 
   settings.window()->Close();
diff --git a/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc b/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc
index 6b5493e2..74e52d2a 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc
+++ b/chrome/browser/ash/app_mode/test/kiosk_test_utils.cc
@@ -39,13 +39,13 @@
 #include "chrome/browser/ui/browser_list.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/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #include "chrome/browser/ui/webui/ash/login/app_launch_splash_screen_handler.h"
 #include "chrome/browser/ui/webui/ash/login/error_screen_handler.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
 #include "chromeos/ash/components/dbus/session_manager/fake_session_manager_client.h"
 #include "chromeos/ash/components/policy/device_local_account/device_local_account_type.h"
+#include "chromeos/ash/experiences/settings_ui/settings_app_manager.h"
 #include "components/policy/core/common/cloud/cloud_policy_constants.h"
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "extensions/browser/app_window/app_window.h"
@@ -304,13 +304,13 @@
       LoginAcceleratorAction::kAppLaunchBailout);
 }
 
-Browser* OpenA11ySettings(Profile& profile) {
+Browser* OpenA11ySettings(const user_manager::User& user) {
   auto& session = CHECK_DEREF(KioskController::Get().GetKioskSystemSession());
-  auto& settings_manager =
-      CHECK_DEREF(chrome::SettingsWindowManager::GetInstance());
+  auto& settings_manager = CHECK_DEREF(ash::SettingsAppManager::Get());
 
-  settings_manager.ShowOSSettings(
-      &profile, chromeos::settings::mojom::kManageAccessibilitySubpagePath);
+  settings_manager.Open(
+      user,
+      {.sub_page = chromeos::settings::mojom::kManageAccessibilitySubpagePath});
 
   EXPECT_FALSE(DidKioskCloseNewWindow());
 
diff --git a/chrome/browser/ash/app_mode/test/kiosk_test_utils.h b/chrome/browser/ash/app_mode/test/kiosk_test_utils.h
index eb211c9..92af4134 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_test_utils.h
+++ b/chrome/browser/ash/app_mode/test/kiosk_test_utils.h
@@ -19,6 +19,10 @@
 #include "components/policy/core/common/cloud/test/policy_builder.h"
 #include "url/gurl.h"
 
+namespace user_manager {
+class User;
+}  // namespace user_manager
+
 namespace ash::kiosk::test {
 
 // Returns the auto launch Kiosk app configured in the system. Checks if there
@@ -108,7 +112,7 @@
 // does not close it, and returns the corresponding `Browser`.
 //
 // Checks if `KioskSystemSession` closes the browser, or if it is null.
-Browser* OpenA11ySettings(Profile& profile);
+Browser* OpenA11ySettings(const user_manager::User& user);
 
 // Waits for the next new browser window to be created and returns true if
 // `KioskSystemSession` decides to close it.
diff --git a/chrome/browser/ash/arc/auth/BUILD.gn b/chrome/browser/ash/arc/auth/BUILD.gn
index 528f26a..0166c2b9 100644
--- a/chrome/browser/ash/arc/auth/BUILD.gn
+++ b/chrome/browser/ash/arc/auth/BUILD.gn
@@ -36,7 +36,9 @@
     "//chrome/browser/signin",
     "//chrome/common",
     "//chromeos/ash/components/account_manager",
+    "//chromeos/ash/components/browser_context_helper",
     "//chromeos/ash/experiences/arc",
+    "//chromeos/ash/experiences/settings_ui",
     "//components/account_manager_core",
     "//components/prefs",
     "//components/user_manager",
diff --git a/chrome/browser/ash/arc/auth/arc_auth_service.cc b/chrome/browser/ash/arc/auth/arc_auth_service.cc
index 2b798374..6c86b534 100644
--- a/chrome/browser/ash/arc/auth/arc_auth_service.cc
+++ b/chrome/browser/ash/arc/auth/arc_auth_service.cc
@@ -10,6 +10,7 @@
 
 #include "ash/constants/ash_switches.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "base/check_deref.h"
 #include "base/command_line.h"
 #include "base/containers/flat_set.h"
 #include "base/functional/bind.h"
@@ -33,10 +34,10 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/signin/signin_ui_util.h"
-#include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/ui/webui/signin/ash/inline_login_dialog.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chromeos/ash/components/account_manager/account_manager_factory.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "chromeos/ash/experiences/arc/arc_browser_context_keyed_service_factory_base.h"
 #include "chromeos/ash/experiences/arc/arc_features.h"
 #include "chromeos/ash/experiences/arc/arc_prefs.h"
@@ -45,6 +46,7 @@
 #include "chromeos/ash/experiences/arc/session/arc_bridge_service.h"
 #include "chromeos/ash/experiences/arc/session/arc_management_transition.h"
 #include "chromeos/ash/experiences/arc/session/arc_service_manager.h"
+#include "chromeos/ash/experiences/settings_ui/settings_app_manager.h"
 #include "components/account_manager_core/account_manager_facade.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/base/consent_level.h"
@@ -516,8 +518,10 @@
 void ArcAuthService::HandleRemoveAccountRequest(const std::string& email) {
   DCHECK(ash::IsAccountManagerAvailable(profile_));
 
-  chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-      profile_, chromeos::settings::mojom::kPeopleSectionPath);
+  ash::SettingsAppManager::Get()->Open(
+      CHECK_DEREF(
+          ash::BrowserContextHelper::Get()->GetUserByBrowserContext(profile_)),
+      {.sub_page = chromeos::settings::mojom::kPeopleSectionPath});
 }
 
 void ArcAuthService::HandleUpdateCredentialsRequest(const std::string& email) {
diff --git a/chrome/browser/ash/arc/nearby_share/BUILD.gn b/chrome/browser/ash/arc/nearby_share/BUILD.gn
index 5c1eea4a..5bb6ee0 100644
--- a/chrome/browser/ash/arc/nearby_share/BUILD.gn
+++ b/chrome/browser/ash/arc/nearby_share/BUILD.gn
@@ -38,9 +38,11 @@
     "//chrome/browser/profiles:profile",
     "//chrome/browser/webshare:storage",
     "//chrome/common",
+    "//chromeos/ash/components/browser_context_helper",
     "//chromeos/ash/experiences/arc",
     "//chromeos/ash/experiences/arc/intent_helper",
     "//chromeos/ash/experiences/arc/mojom",
+    "//chromeos/ash/experiences/settings_ui",
     "//chromeos/components/sharesheet:constants",
     "//components/exo",
     "//components/keyed_service/core",
diff --git a/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl.cc b/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl.cc
index d873d2ed..7985acd 100644
--- a/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl.cc
+++ b/chrome/browser/ash/arc/nearby_share/nearby_share_session_impl.cc
@@ -10,6 +10,7 @@
 
 #include "ash/public/cpp/app_types_util.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "base/check_deref.h"
 #include "base/feature_list.h"
 #include "base/files/file_util.h"
 #include "base/functional/bind.h"
@@ -37,11 +38,12 @@
 #include "chrome/browser/sharesheet/sharesheet_service.h"
 #include "chrome/browser/sharesheet/sharesheet_service_factory.h"
 #include "chrome/browser/sharesheet/sharesheet_types.h"
-#include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/browser/webshare/prepare_directory_task.h"
 #include "chrome/common/chrome_paths_internal.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "chromeos/ash/experiences/arc/arc_features.h"
 #include "chromeos/ash/experiences/arc/arc_util.h"
+#include "chromeos/ash/experiences/settings_ui/settings_app_manager.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
 #include "content/public/browser/browser_thread.h"
@@ -545,8 +547,10 @@
 void NearbyShareSessionImpl::OnLowStorageDialogClosed(
     bool should_open_storage_settings) {
   if (should_open_storage_settings) {
-    chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-        profile_, chromeos::settings::mojom::kStorageSubpagePath);
+    ash::SettingsAppManager::Get()->Open(
+        CHECK_DEREF(ash::BrowserContextHelper::Get()->GetUserByBrowserContext(
+            profile_)),
+        {.sub_page = chromeos::settings::mojom::kStorageSubpagePath});
   }
   CleanupSession(/*should_cleanup_files=*/true);
 }
diff --git a/chrome/browser/ash/arc/notification/BUILD.gn b/chrome/browser/ash/arc/notification/BUILD.gn
index d68223f3..e7f7267 100644
--- a/chrome/browser/ash/arc/notification/BUILD.gn
+++ b/chrome/browser/ash/arc/notification/BUILD.gn
@@ -36,9 +36,11 @@
     "//chrome/browser/notifications",
     "//chrome/browser/profiles:profile",
     "//chrome/common",
+    "//chromeos/ash/components/browser_context_helper",
     "//chromeos/ash/components/demo_mode",
     "//chromeos/ash/experiences/arc",
     "//chromeos/ash/experiences/arc/vm_data_migration",
+    "//chromeos/ash/experiences/settings_ui",
     "//chromeos/components/mgs",
     "//chromeos/ui/vector_icons",
     "//components/account_id",
diff --git a/chrome/browser/ash/arc/notification/arc_boot_error_notification.cc b/chrome/browser/ash/arc/notification/arc_boot_error_notification.cc
index c543ef2..baf14f9 100644
--- a/chrome/browser/ash/arc/notification/arc_boot_error_notification.cc
+++ b/chrome/browser/ash/arc/notification/arc_boot_error_notification.cc
@@ -9,8 +9,10 @@
 
 #include "ash/public/cpp/notification_utils.h"
 #include "ash/webui/settings/public/constants/routes.mojom.h"
+#include "base/check_deref.h"
 #include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/memory/singleton.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/app/vector_icons/vector_icons.h"
 #include "chrome/browser/ash/arc/session/arc_session_manager.h"
@@ -20,11 +22,12 @@
 #include "chrome/browser/notifications/notification_display_service.h"
 #include "chrome/browser/notifications/notification_display_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/settings_window_manager_chromeos.h"
 #include "chrome/common/webui_url_constants.h"
 #include "chrome/grit/generated_resources.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "chromeos/ash/components/demo_mode/utils/demo_session_utils.h"
 #include "chromeos/ash/experiences/arc/arc_browser_context_keyed_service_factory_base.h"
+#include "chromeos/ash/experiences/settings_ui/settings_app_manager.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/browser_thread.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -67,11 +70,11 @@
   message_center::NotifierId notifier_id(
       message_center::NotifierType::SYSTEM_COMPONENT, kNotifierId,
       ash::NotificationCatalogName::kArcBootError);
-  const AccountId& account_id =
-      user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId();
-  notifier_id.profile_id = account_id.GetUserEmail();
+  const user_manager::User* user =
+      ash::BrowserContextHelper::Get()->GetUserByBrowserContext(context);
+  CHECK(user);
+  notifier_id.profile_id = user->GetAccountId().GetUserEmail();
 
-  Profile* profile = Profile::FromBrowserContext(context);
   message_center::Notification notification = ash::CreateSystemNotification(
       message_center::NOTIFICATION_TYPE_SIMPLE, kLowDiskSpaceId,
       l10n_util::GetStringUTF16(IDS_ARC_CRITICALLY_LOW_DISK_NOTIFICATION_TITLE),
@@ -81,16 +84,21 @@
       notifier_id, optional_fields,
       base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
           base::BindRepeating(
-              [](Profile* profile, std::optional<int> button_index) {
+              [](const user_manager::User* user,
+                 std::optional<int> button_index) {
                 if (button_index) {
                   DCHECK_EQ(0, *button_index);
-                  chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(
-                      profile, chromeos::settings::mojom::kStorageSubpagePath);
+                  ash::SettingsAppManager::Get()->Open(
+                      CHECK_DEREF(user),
+                      {.sub_page =
+                           chromeos::settings::mojom::kStorageSubpagePath});
                 }
               },
-              profile)),
+              user)),
       kNotificationStorageFullIcon,
       message_center::SystemNotificationWarningLevel::CRITICAL_WARNING);
+
+  Profile* profile = Profile::FromBrowserContext(context);
   NotificationDisplayServiceFactory::GetForProfile(profile)->Display(
       NotificationHandler::Type::TRANSIENT, notification,
       /*metadata=*/nullptr);
diff --git a/chrome/browser/ash/guest_os/guest_os_terminal.h b/chrome/browser/ash/guest_os/guest_os_terminal.h
index 3c920ef..579af421 100644
--- a/chrome/browser/ash/guest_os/guest_os_terminal.h
+++ b/chrome/browser/ash/guest_os/guest_os_terminal.h
@@ -7,7 +7,7 @@
 
 #include <vector>
 
-#include "base/containers/fixed_flat_map.h"
+#include "base/containers/flat_map.h"
 #include "base/functional/callback.h"
 #include "base/values.h"
 #include "components/services/app_service/public/cpp/intent.h"
diff --git a/chrome/browser/ash/input_method/japanese/japanese_legacy_config.h b/chrome/browser/ash/input_method/japanese/japanese_legacy_config.h
index 87ddea1d..5c3bde4 100644
--- a/chrome/browser/ash/input_method/japanese/japanese_legacy_config.h
+++ b/chrome/browser/ash/input_method/japanese/japanese_legacy_config.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_ASH_INPUT_METHOD_JAPANESE_JAPANESE_LEGACY_CONFIG_H_
 #define CHROME_BROWSER_ASH_INPUT_METHOD_JAPANESE_JAPANESE_LEGACY_CONFIG_H_
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/values.h"
 #include "chromeos/ash/services/ime/public/mojom/user_data_japanese_legacy_config.mojom.h"
 
diff --git a/chrome/browser/ash/input_method/japanese/japanese_prefs.h b/chrome/browser/ash/input_method/japanese/japanese_prefs.h
index c2959c9..ae39bf3 100644
--- a/chrome/browser/ash/input_method/japanese/japanese_prefs.h
+++ b/chrome/browser/ash/input_method/japanese/japanese_prefs.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_ASH_INPUT_METHOD_JAPANESE_JAPANESE_PREFS_H_
 #define CHROME_BROWSER_ASH_INPUT_METHOD_JAPANESE_JAPANESE_PREFS_H_
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/values.h"
 #include "components/prefs/pref_service.h"
 
diff --git a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
index 3c22f75..4fef028 100644
--- a/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
+++ b/chrome/browser/ash/input_method/longpress_diacritics_suggester.h
@@ -9,7 +9,6 @@
 #include <string>
 #include <string_view>
 
-#include "base/containers/fixed_flat_map.h"
 #include "chrome/browser/ash/input_method/longpress_suggester.h"
 #include "chrome/browser/ash/input_method/suggestion_enums.h"
 #include "ui/events/event.h"
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java
index 3099d14c..4018cb5 100644
--- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java
+++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkManagerMediator.java
@@ -1576,7 +1576,7 @@
         ModelList listItems =
                 createListMenuModelList(entry, model.get(BookmarkManagerProperties.LOCATION));
         ListMenu.Delegate delegate =
-                item -> {
+                (item, view) -> {
                     int textId = item.get(ListMenuItemProperties.TITLE_ID);
                     if (textId == R.string.bookmark_item_select) {
                         mSelectionDelegate.toggleSelectionForItem(bookmarkId);
diff --git a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java
index b4078b7..07039d6 100644
--- a/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java
+++ b/chrome/browser/bookmarks/android/java/src/org/chromium/chrome/browser/bookmarks/bar/BookmarkBarMediator.java
@@ -444,11 +444,11 @@
                 BrowserUiListMenuUtils.getBasicListMenu(
                         mActivity,
                         bookmarkItems,
-                        (model) -> {
+                        (model, view) -> {
                             View.OnClickListener clickListener =
                                     model.get(ListMenuItemProperties.CLICK_LISTENER);
                             if (clickListener != null) {
-                                clickListener.onClick(null);
+                                clickListener.onClick(view);
                             }
                         });
 
diff --git a/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowRenderTest.java b/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowRenderTest.java
index e5316d08..5ef0a4cd 100644
--- a/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowRenderTest.java
+++ b/chrome/browser/bookmarks/android/javatests/src/org/chromium/chrome/browser/bookmarks/ImprovedBookmarkRowRenderTest.java
@@ -183,7 +183,7 @@
         listItems.add(buildSimpleMenuItem(R.string.bookmark_item_edit));
         listItems.add(buildSimpleMenuItem(R.string.bookmark_item_move));
 
-        ListMenu.Delegate delegate = item -> {};
+        ListMenu.Delegate delegate = (item, view) -> {};
         return BrowserUiListMenuUtils.getBasicListMenu(
                 mActivityTestRule.getActivity(), listItems, delegate);
     }
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index 0c72a26..0a96ff7 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -35,7 +35,7 @@
              base::FEATURE_DISABLED_BY_DEFAULT);
 
 // This flag is used for enabling BookmarkBar triggered preconnect.
-BASE_FEATURE(kBookmarkTriggerForPreconnect, base::FEATURE_DISABLED_BY_DEFAULT);
+BASE_FEATURE(kBookmarkTriggerForPreconnect, base::FEATURE_ENABLED_BY_DEFAULT);
 
 // This flag is used for enabling BookmarkBar triggered prefetch.  See
 // crbug.com/413259638 for more details of Bookmark triggered prefetching.
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/ui/recent_activity/RecentActivityListCoordinator.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/ui/recent_activity/RecentActivityListCoordinator.java
index af778b0e..f635788d 100644
--- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/ui/recent_activity/RecentActivityListCoordinator.java
+++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/ui/recent_activity/RecentActivityListCoordinator.java
@@ -164,7 +164,7 @@
                             .withMenuId(R.id.see_full_activity)
                             .build());
             ListMenu.Delegate delegate =
-                    (model) -> {
+                    (model, unusedView) -> {
                         int textId = model.get(ListMenuItemProperties.TITLE_ID);
                         if (textId == R.string.data_sharing_shared_tab_groups_activity) {
                             mShowFullActivityRunnable.run();
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
index c69212a..063b828f 100644
--- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
+++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/list/holder/OfflineItemViewHolder.java
@@ -194,7 +194,7 @@
             listItems.add(buildSimpleMenuItem(R.string.delete));
         }
         ListMenu.Delegate delegate =
-                (model) -> {
+                (model, view) -> {
                     int textId = model.get(ListMenuItemProperties.TITLE_ID);
                     if (textId == R.string.share) {
                         if (mShareCallback != null) mShareCallback.run();
diff --git a/chrome/browser/extensions/api/terminal/terminal_private_api.cc b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
index 66b2163..a63272a 100644
--- a/chrome/browser/extensions/api/terminal/terminal_private_api.cc
+++ b/chrome/browser/extensions/api/terminal/terminal_private_api.cc
@@ -15,6 +15,7 @@
 #include "ash/webui/settings/public/constants/routes.mojom.h"
 #include "base/command_line.h"
 #include "base/containers/contains.h"
+#include "base/containers/fixed_flat_map.h"
 #include "base/containers/fixed_flat_set.h"
 #include "base/containers/flat_set.h"
 #include "base/containers/span.h"
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
index 5de61a5..37aa6f6 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context.cc
@@ -892,6 +892,24 @@
     auto* request_manager =
         FileSystemAccessPermissionRequestManager::FromWebContents(web_contents);
     if (!request_manager) {
+      // Extension contexts (popup, side panel) may not have a permission
+      // request manager attached. Since the user already explicitly selected a
+      // file/folder via the file picker dialog (which is a strong user
+      // gesture), we can auto-grant the permission for extensions without
+      // showing an additional prompt.
+      bool is_extension =
+          rfh->GetLastCommittedOrigin().scheme() == "chrome-extension";
+      if (is_extension) {
+        PermissionRequestOutcome outcome =
+            PermissionRequestOutcome::kUserGranted;
+        RecordPermissionRequestOutcome(outcome);
+        // May destroy `this`.
+        SetStatus(PermissionStatus::GRANTED,
+                  PersistedPermissionOptions::kUpdatePersistedPermission);
+        std::move(callback).Run(outcome);
+        return;
+      }
+
       RunCallbackAndRecordPermissionRequestOutcome(
           std::move(callback), PermissionRequestOutcome::kRequestAborted);
       return;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index f2e565c..1f6409e7 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2907,6 +2907,14 @@
     "expiry_milestone": 150
   },
   {
+    "name": "enable-android-media-insertion",
+    "owners": [
+      "hdchuong@google.com",
+      "essential-inputs-team@google.com"
+    ],
+    "expiry_milestone": 140
+  },
+  {
     "name": "enable-android-mininal-ui-large-screen",
     "owners": [
       "vkorotkevich@google.com",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 103ad4f..7f96b2b6 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -4730,6 +4730,10 @@
     "When typing, allows spellcheckers to highlight grammar errors and suggest "
     "corrections on browser text input.";
 
+const char kAndroidMediaInsertionName[] = "Enable IME media insertion";
+const char kAndroidMediaInsertionDescription[] =
+    "Enables IMEs to insert media content such as images, gifs and stickers.";
+
 const char kAndroidSpellcheckNativeUiName[] =
     "Enable native-like spellcheck underline UI";
 const char kAndroidSpellcheckNativeUiDescription[] =
@@ -4950,10 +4954,6 @@
 const char kCCTResizableForThirdPartiesDescription[] =
     "Enable bottom sheet Custom Tabs for third party apps.";
 
-const char kCCTRevampedBrandingName[] = "Revamped CCT toolbar branding.";
-const char kCCTRevampedBrandingDescription[] =
-    "Enables a revamped branding animation on the CCT toolbar.";
-
 const char kCCTToolbarRefactorName[] = "CCT Toolbar Refactor";
 const char kCCTToolbarRefactorDescription[] = "CCT Toolbar Refactor";
 
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 87cbb26..5f78cd5 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -135,6 +135,8 @@
 #if BUILDFLAG(IS_ANDROID)
 extern const char kAndroidGrammarCheckName[];
 extern const char kAndroidGrammarCheckDescription[];
+extern const char kAndroidMediaInsertionName[];
+extern const char kAndroidMediaInsertionDescription[];
 extern const char kAndroidSpellcheckNativeUiName[];
 extern const char kAndroidSpellcheckNativeUiDescription[];
 extern const char kAndroidSpellcheckFullApiBlinkName[];
@@ -2863,9 +2865,6 @@
 extern const char kCCTResizableForThirdPartiesName[];
 extern const char kCCTResizableForThirdPartiesDescription[];
 
-extern const char kCCTRevampedBrandingName[];
-extern const char kCCTRevampedBrandingDescription[];
-
 extern const char kCCTToolbarRefactorName[];
 extern const char kCCTToolbarRefactorDescription[];
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index c41f8ffb..885a0e9 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -214,6 +214,7 @@
     &kAndroidElegantTextHeight,
     &kAndroidFirstRunLaunchBounds,
     &kAndroidLogoViewRefactor,
+    &kAndroidMediaInsertion,
     &kAndroidProgressBarVisualUpdate,
     &kAndroidNoVisibleHintForDifferentTLD,
     &kAndroidOmniboxFocusedNewTabPage,
@@ -288,7 +289,6 @@
     &kCCTReportParallelRequestStatus,
     &kCCTReportPrerenderEvents,
     &kCCTResizableForThirdParties,
-    &kCCTRevampedBranding,
     &kCCTShowTabFix,
     &kCCTTabModalDialog,
     &kCCTToolbarRefactor,
@@ -510,6 +510,7 @@
     &webapps::features::kWebApkInstallFailureNotification,
     &webapps::features::kAndroidMinimalUiLargeScreen,
     &webapps::features::kAndroidWebAppMenuButton,
+    &base::features::kLowEndMemoryExperiment,
     &base::features::kPostGetMyMemoryStateToBackground,
 };
 
@@ -572,6 +573,8 @@
 
 BASE_FEATURE(kAndroidLogoViewRefactor, base::FEATURE_ENABLED_BY_DEFAULT);
 
+BASE_FEATURE(kAndroidMediaInsertion, base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kAndroidProgressBarVisualUpdate,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
@@ -767,8 +770,6 @@
 
 BASE_FEATURE(kCCTResizableForThirdParties, base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kCCTRevampedBranding, base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kCCTShowTabFix, base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kCCTTabModalDialog, base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index e6f8956e..e2a3411 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -35,6 +35,7 @@
 BASE_DECLARE_FEATURE(kAndroidElegantTextHeight);
 BASE_DECLARE_FEATURE(kAndroidFirstRunLaunchBounds);
 BASE_DECLARE_FEATURE(kAndroidLogoViewRefactor);
+BASE_DECLARE_FEATURE(kAndroidMediaInsertion);
 BASE_DECLARE_FEATURE(kAndroidProgressBarVisualUpdate);
 BASE_DECLARE_FEATURE(kAndroidNoVisibleHintForDifferentTLD);
 BASE_DECLARE_FEATURE(kAndroidOmniboxFocusedNewTabPage);
@@ -114,7 +115,6 @@
 BASE_DECLARE_FEATURE(kCCTReportPrerenderEvents);
 BASE_DECLARE_FEATURE(kCCTResizableForThirdParties);
 BASE_DECLARE_FEATURE(kCCTRetainingStateInMemory);
-BASE_DECLARE_FEATURE(kCCTRevampedBranding);
 BASE_DECLARE_FEATURE(kCCTShowTabFix);
 BASE_DECLARE_FEATURE(kCCTTabModalDialog);
 BASE_DECLARE_FEATURE(kCCTToolbarRefactor);
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 3a324a0..e4b9c5df 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
@@ -186,6 +186,7 @@
     public static final String ANDROID_ELEGANT_TEXT_HEIGHT = "AndroidElegantTextHeight";
     public static final String ANDROID_FIRST_RUN_LAUNCH_BOUNDS = "AndroidFirstRunLaunchBounds";
     public static final String ANDROID_LOGO_VIEW_REFACTOR = "AndroidLogoViewRefactor";
+    public static final String ANDROID_MEDIA_INSERTION = "AndroidMediaInsertion";
     public static final String ANDROID_MINIMAL_UI_LARGE_SCREEN = "AndroidMinimalUiLargeScreen";
     public static final String ANDROID_NO_VISIBLE_HINT_FOR_DIFFERENT_TLD =
             "AndroidNoVisibleHintForDifferentTLD";
@@ -346,7 +347,6 @@
     public static final String CCT_REPORT_PRERENDER_EVENTS = "CCTReportPrerenderEvents";
     public static final String CCT_RESET_TIMEOUT_ENABLED = "CCTResetTimeoutEnabled";
     public static final String CCT_RESIZABLE_FOR_THIRD_PARTIES = "CCTResizableForThirdParties";
-    public static final String CCT_REVAMPED_BRANDING = "CCTRevampedBranding";
     public static final String CCT_SHOW_TAB_FIX = "CCTShowTabFix";
     public static final String CCT_TAB_MODAL_DIALOG = "CCTTabModalDialog";
     public static final String CCT_TOOLBAR_REFACTOR = "CCTToolbarRefactor";
@@ -478,6 +478,7 @@
             "LockTopControlsOnLargeTabletsV2";
     public static final String LOOKALIKE_NAVIGATION_URL_SUGGESTIONS_UI =
             "LookalikeUrlNavigationSuggestionsUI";
+    public static final String LOW_END_MEMORY_EXPERIMENT = BaseFeatures.LOW_END_MEMORY_EXPERIMENT;
     public static final String MAGIC_STACK_ANDROID = "MagicStackAndroid";
     public static final String MALICIOUS_APK_DOWNLOAD_CHECK = "MaliciousApkDownloadCheck";
     public static final String MAYLAUNCHURL_USES_SEPARATE_STORAGE_PARTITION =
@@ -862,8 +863,6 @@
             newCachedFlag(CCT_RESET_TIMEOUT_ENABLED, false);
     public static final CachedFlag sCctResizableForThirdParties =
             newCachedFlag(CCT_RESIZABLE_FOR_THIRD_PARTIES, true);
-    public static final CachedFlag sCctRevampedBranding =
-            newCachedFlag(CCT_REVAMPED_BRANDING, true);
     public static final CachedFlag sCctTabModalDialog = newCachedFlag(CCT_TAB_MODAL_DIALOG, true);
     public static final CachedFlag sCctToolbarRefactor =
             newCachedFlag(CCT_TOOLBAR_REFACTOR, false, true);
@@ -1165,7 +1164,6 @@
                     sCctRealtimeEngagementEventsInBackground,
                     sCctResetTimeoutEnabled,
                     sCctResizableForThirdParties,
-                    sCctRevampedBranding,
                     sCctTabModalDialog,
                     sCctToolbarRefactor,
                     sChromeItemPickerUi,
@@ -1403,6 +1401,8 @@
             newBooleanCachedFeatureParam(CCT_ADAPTIVE_BUTTON, "contextual_only", false);
     public static final IntCachedFeatureParam sCctAdaptiveButtonDefaultVariant =
             newIntCachedFeatureParam(CCT_ADAPTIVE_BUTTON, "default_variant", 0);
+    public static final IntCachedFeatureParam sLowMemoryDeviceThresholdMb =
+            newIntCachedFeatureParam(LOW_END_MEMORY_EXPERIMENT, "LowMemoryDeviceThresholdMB", 1024);
     public static final BooleanCachedFeatureParam sAndroidAppIntegrationModuleForceCardShow =
             newBooleanCachedFeatureParam(ANDROID_APP_INTEGRATION_MODULE, "force_card_shown", false);
 
@@ -1800,6 +1800,7 @@
                     sEdgeToEdgeUseBackupNavbarInsetsOemMinVersions,
                     sEdgeToEdgeUseBackupNavbarInsetsUseGestures,
                     sLoadNativeEarlyConcurrentLoad,
+                    sLowMemoryDeviceThresholdMb,
                     sMagicStackAndroidShowAllModules,
                     sMaliciousApkDownloadCheckTelemetryOnly,
                     sMaxLegacyTabStateFilesCleanedUpPerSession,
diff --git a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthMenuDelegate.java b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthMenuDelegate.java
index 01d99a20..b95a6003 100644
--- a/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthMenuDelegate.java
+++ b/chrome/browser/incognito/android/java/src/org/chromium/chrome/browser/incognito/reauth/IncognitoReauthMenuDelegate.java
@@ -7,6 +7,7 @@
 import static org.chromium.build.NullUtil.assumeNonNull;
 
 import android.content.Context;
+import android.view.View;
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.IdRes;
@@ -62,7 +63,7 @@
      * with the menu items.
      */
     @Override
-    public void onItemSelected(PropertyModel item) {
+    public void onItemSelected(PropertyModel item, View view) {
         int textId = item.get(ListMenuItemProperties.TITLE_ID);
         if (textId == R.string.menu_close_all_incognito_tabs) {
             onCloseAllIncognitoTabsMenuItemClicked();
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
index 525ebc9..77cf499 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/ContentLanguagesPreference.java
@@ -106,7 +106,7 @@
             }
 
             ListMenu.Delegate delegate =
-                    (model) -> {
+                    (model, view) -> {
                         int textId = model.get(ListMenuItemProperties.TITLE_ID);
                         if (textId == R.string.languages_item_option_offer_to_translate) {
                             // Toggle current blocked state of this language.
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemListFragment.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemListFragment.java
index 492fb69..b5089fd 100644
--- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemListFragment.java
+++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/LanguageItemListFragment.java
@@ -82,7 +82,7 @@
 
             // ListMenu.Delegate handles return from three dot menu.
             ListMenu.Delegate delegate =
-                    (model) -> {
+                    (model, view) -> {
                         int textId = model.get(ListMenuItemProperties.TITLE_ID);
                         if (textId == R.string.remove) {
                             onLanguageRemoved(currentLanguageItem.getCode());
diff --git a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesContextMenuManager.java b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesContextMenuManager.java
index e936f0db..6c143c4 100644
--- a/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesContextMenuManager.java
+++ b/chrome/browser/magic_stack/android/java/src/org/chromium/chrome/browser/magic_stack/HomeModulesContextMenuManager.java
@@ -135,7 +135,7 @@
         if (!hasItems) return null;
 
         ListMenu.Delegate delegate =
-                (model) -> {
+                (model, unusedView) -> {
                     switch (model.get(ListMenuItemProperties.MENU_ITEM_ID)) {
                         case ContextMenuItemId.HIDE_MODULE:
                             moduleDelegate.removeModuleAndDisable(moduleProvider.getModuleType());
diff --git a/chrome/browser/resources/new_tab_page/action_chips.css b/chrome/browser/resources/new_tab_page/action_chips.css
new file mode 100644
index 0000000..6c604af
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/action_chips.css
@@ -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. */
+
+/* #css_wrapper_metadata_start
+ * #type=style-lit
+ * #import=chrome://resources/cr_elements/cr_shared_style_lit.css.js
+ * #import=chrome://resources/cr_elements/cr_icons_lit.css.js
+ * #scheme=relative
+ * #include=cr-shared-style-lit cr-icons-lit
+ * #css_wrapper_metadata_end */
+
+p {
+  color: blue;
+}
diff --git a/chrome/browser/resources/new_tab_page/action_chips.html b/chrome/browser/resources/new_tab_page/action_chips.html
new file mode 100644
index 0000000..2ce3324e
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/action_chips.html
@@ -0,0 +1 @@
+<p>Action Chips</p>
\ No newline at end of file
diff --git a/chrome/browser/resources/new_tab_page/action_chips.ts b/chrome/browser/resources/new_tab_page/action_chips.ts
new file mode 100644
index 0000000..ac3bca7
--- /dev/null
+++ b/chrome/browser/resources/new_tab_page/action_chips.ts
@@ -0,0 +1,37 @@
+// 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 {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js';
+
+import {getCss} from './action_chips.css.js';
+import {getHtml} from './action_chips.html.js';
+
+/**
+ * The element for displaying Action Chips.
+ */
+export class ActionChipsElement extends CrLitElement {
+  static get is() {
+    return 'ntp-action-chips';
+  }
+
+  static override get styles() {
+    return getCss();
+  }
+
+  override render() {
+    return getHtml.bind(this)();
+  }
+
+  static override get properties() {
+    return {};
+  }
+}
+
+declare global {
+  interface HTMLElementTagNameMap {
+    'ntp-action-chips': ActionChipsElement;
+  }
+}
+
+customElements.define(ActionChipsElement.is, ActionChipsElement);
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html
index d9c2a6e..5bc50bc4 100644
--- a/chrome/browser/resources/new_tab_page/app.html
+++ b/chrome/browser/resources/new_tab_page/app.html
@@ -45,6 +45,9 @@
       </ntp-lens-upload-dialog>
     ` : ''}
   </div>
+  ${this.lazyRender_ && this.ntpNextFeaturesEnabled_ ? html`
+    <ntp-action-chips></ntp-action-chips>
+  ` : ''}
   ${this.lazyRender_ ? html`
     <cr-toast id="webstoreToast" duration="10000" hidden>
       <div>$i18n{webstoreThemesToastMessage}</div>
diff --git a/chrome/browser/resources/new_tab_page/app.ts b/chrome/browser/resources/new_tab_page/app.ts
index 44023a6..bd073f08 100644
--- a/chrome/browser/resources/new_tab_page/app.ts
+++ b/chrome/browser/resources/new_tab_page/app.ts
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import './action_chips.js';
 import './iframe.js';
 import './logo.js';
 import '/strings.m.js';
@@ -296,6 +297,8 @@
        * Whether the composebox has been opened at least once.
        */
       wasComposeboxOpened_: {type: Boolean},
+
+      ntpNextFeaturesEnabled_: {type: Boolean},
     };
   }
 
@@ -367,6 +370,8 @@
       loadTimeData.getString('realboxLayoutMode');
   protected accessor searchboxCyclingPlaceholders_: boolean =
       loadTimeData.getBoolean('searchboxCyclingPlaceholders');
+  protected accessor ntpNextFeaturesEnabled_: boolean =
+      loadTimeData.getBoolean('ntpNextFeaturesEnabled');
 
   private callbackRouter_: PageCallbackRouter;
   private pageHandler_: PageHandlerRemote;
diff --git a/chrome/browser/resources/new_tab_page/lazy_load.ts b/chrome/browser/resources/new_tab_page/lazy_load.ts
index 872c946..1a7fdcb8 100644
--- a/chrome/browser/resources/new_tab_page/lazy_load.ts
+++ b/chrome/browser/resources/new_tab_page/lazy_load.ts
@@ -26,6 +26,7 @@
 export {ComposeboxFileThumbnailElement} from 'chrome://resources/cr_components/composebox/file_thumbnail.js';
 export {PageImageServiceBrowserProxy} from 'chrome://resources/cr_components/page_image_service/browser_proxy.js';
 export {PluralStringProxyImpl as NTPPluralStringProxyImpl} from 'chrome://resources/js/plural_string_proxy.js';
+export {ActionChipsElement} from './action_chips.js';
 export {LensErrorType, LensFormElement, LensSubmitType} from './lens_form.js';
 export {LensUploadDialogAction, LensUploadDialogElement, LensUploadDialogError} from './lens_upload_dialog.js';
 export {MiddleSlotPromoElement, PromoDismissAction} from './middle_slot_promo.js';
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page.gni b/chrome/browser/resources/new_tab_page/new_tab_page.gni
index a424e1c..bf4b4544 100644
--- a/chrome/browser/resources/new_tab_page/new_tab_page.gni
+++ b/chrome/browser/resources/new_tab_page/new_tab_page.gni
@@ -24,6 +24,7 @@
 
 # Files holding a Polymer element definition and have an equivalent .html file.
 all_web_component_files = [
+                            "action_chips.ts",
                             "app.ts",
                             "doodle_share_dialog.ts",
                             "iframe.ts",
@@ -35,6 +36,7 @@
                           ] + modules_web_component_files
 
 all_css_files = [
+                  "action_chips.css",
                   "app.css",
                   "doodle_share_dialog.css",
                   "iframe.css",
diff --git a/chrome/browser/resources/omnibox_popup/full_app.css b/chrome/browser/resources/omnibox_popup/full_app.css
index 16743840..c61e8a3 100644
--- a/chrome/browser/resources/omnibox_popup/full_app.css
+++ b/chrome/browser/resources/omnibox_popup/full_app.css
@@ -7,6 +7,13 @@
  * #scheme=relative
  * #css_wrapper_metadata_end */
 
-cr-searchbox::part(searchbox-dropdown) {
-  position: initial;
+cr-searchbox {
+  --cr-searchbox-height: 36px;
+  --cr-searchbox-icon-left-position: 12px;
+  --cr-searchbox-icon-top-position: 0;
+  display: block;
+}
+
+cr-searchbox::part(dropdown-content) {
+  border-radius: 0;
 }
diff --git a/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html b/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html
index 23517b7..06390d2 100644
--- a/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html
+++ b/chrome/browser/resources/omnibox_popup/omnibox_popup_full.html
@@ -19,7 +19,6 @@
       background-color: var(--color-omnibox-results-background);
       height: auto;
       margin: 0;
-      overflow: hidden;
     }
   </style>
 </head>
diff --git a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubNotificationsPreference.java b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubNotificationsPreference.java
index 96c8d3c1..94f0af7e 100644
--- a/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubNotificationsPreference.java
+++ b/chrome/browser/safety_hub/android/java/src/org/chromium/chrome/browser/safety_hub/SafetyHubNotificationsPreference.java
@@ -6,6 +6,7 @@
 
 import android.content.Context;
 import android.graphics.drawable.Drawable;
+import android.view.View;
 import android.widget.ImageView;
 
 import androidx.preference.PreferenceViewHolder;
@@ -87,7 +88,7 @@
     }
 
     @Override
-    public void onItemSelected(PropertyModel item) {
+    public void onItemSelected(PropertyModel item, View view) {
         if (mMenuClickListener == null) {
             return;
         }
diff --git a/chrome/browser/sessions/tab_loader.cc b/chrome/browser/sessions/tab_loader.cc
index f2a74b5..fedfe969 100644
--- a/chrome/browser/sessions/tab_loader.cc
+++ b/chrome/browser/sessions/tab_loader.cc
@@ -21,7 +21,8 @@
 #include "chrome/browser/sessions/session_restore.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
+#include "chrome/browser/ui/tabs/tab_strip_model.h"
 #include "components/favicon/content/content_favicon_driver.h"
 #include "content/public/browser/navigation_controller.h"
 #include "content/public/browser/web_contents.h"
@@ -55,18 +56,9 @@
 base::RepeatingCallback<void(TabLoader*)>* g_construction_callback = nullptr;
 
 // Determines if the given browser (can be null) is closing.
-bool IsBrowserClosing(Browser* browser) {
-  if (g_browser_process->IsShuttingDown())
-    return true;
-  if (!browser)
-    return true;
-  if (browser->tab_strip_model()->closing_all())
-    return true;
-  const auto& closing_browsers =
-      BrowserList::GetInstance()->currently_closing_browsers();
-  if (base::Contains(closing_browsers, browser))
-    return true;
-  return false;
+bool IsBrowserClosing(BrowserWindowInterface* browser) {
+  return g_browser_process->IsShuttingDown() || !browser ||
+         browser->GetTabStripModel()->closing_all();
 }
 
 }  // namespace
@@ -660,13 +652,13 @@
 
   // Get the browser associated with this contents and determine if its in the
   // process of being closed.
-  Browser* browser = chrome::FindBrowserWithTab(contents);
+  BrowserWindowInterface* const browser = chrome::FindBrowserWithTab(contents);
   if (IsBrowserClosing(browser)) {
     RemoveTab(contents);
     StartTimerIfNeeded();
     return;
   }
-  DCHECK(browser);
+  CHECK(browser);
 
   MarkTabAsLoadInitiated(contents);
   StartTimerIfNeeded();
@@ -674,7 +666,7 @@
   // This is done last as the calls out of us can be reentrant. To make life
   // easier we ensure the timer invariant is valid before calling out.
   contents->GetController().LoadIfNecessary();
-  if (browser->tab_strip_model()->GetActiveWebContents() != contents) {
+  if (browser->GetTabStripModel()->GetActiveWebContents() != contents) {
     // By default tabs are marked as visible. As only the active tab is
     // visible we need to explicitly tell non-active tabs they are hidden.
     // Without this call non-active tabs are not marked as backgrounded.
diff --git a/chrome/browser/themes/theme_service_test_utils.cc b/chrome/browser/themes/theme_service_test_utils.cc
index 95e9dd3..450fb6e 100644
--- a/chrome/browser/themes/theme_service_test_utils.cc
+++ b/chrome/browser/themes/theme_service_test_utils.cc
@@ -4,6 +4,7 @@
 
 #include "chrome/browser/themes/theme_service_test_utils.h"
 
+#include "base/containers/fixed_flat_map.h"
 #include "base/strings/string_util.h"
 #include "base/strings/stringprintf.h"
 #include "base/test/scoped_feature_list.h"
diff --git a/chrome/browser/themes/theme_service_test_utils.h b/chrome/browser/themes/theme_service_test_utils.h
index 7b513cd..00ef1e4c6 100644
--- a/chrome/browser/themes/theme_service_test_utils.h
+++ b/chrome/browser/themes/theme_service_test_utils.h
@@ -8,7 +8,6 @@
 #include <ostream>
 #include <string>
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/memory/scoped_refptr.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "components/sync/model/sync_change.h"
diff --git a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
index a33da792..0d549ee3 100644
--- a/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
+++ b/chrome/browser/ui/android/multiwindow/java/src/org/chromium/chrome/browser/multiwindow/InstanceSwitcherCoordinator.java
@@ -486,7 +486,7 @@
         }
 
         ListMenu.Delegate moreMenuDelegate =
-                (model) -> {
+                (model, view) -> {
                     int textId = model.get(ListMenuItemProperties.TITLE_ID);
                     if (textId == R.string.instance_switcher_close_window
                             || textId == R.string.close) {
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
index 348b5f1a..d05072df 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/ToolbarLongPressMenuHandler.java
@@ -175,7 +175,7 @@
                 BrowserUiListMenuUtils.getBasicListMenu(
                         view.getContext(),
                         buildMenuItems(onTop),
-                        (model) -> {
+                        (model, unusedView) -> {
                             handleMenuClick(model.get(ListMenuItemProperties.MENU_ITEM_ID));
                             assumeNonNull(mPopupMenu);
                             mPopupMenu.dismiss();
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
index eac0506..9f9ba4d 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/adaptive/AdaptiveButtonActionMenuCoordinator.java
@@ -96,7 +96,7 @@
                 BrowserUiListMenuUtils.getBasicListMenu(
                         context,
                         listItems,
-                        (model) -> {
+                        (model, view) -> {
                             onItemClicked.onResult(model.get(ListMenuItemProperties.MENU_ITEM_ID));
                         });
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionContextMenuUtils.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionContextMenuUtils.java
index b4bfb51..beda18c1 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionContextMenuUtils.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionActionContextMenuUtils.java
@@ -53,11 +53,11 @@
         ListMenu.Delegate buttonDelegate =
                 new ListMenu.Delegate() {
                     @Override
-                    public void onItemSelected(PropertyModel model) {
+                    public void onItemSelected(PropertyModel model, View view) {
                         View.OnClickListener listener = model.get(CLICK_LISTENER);
 
                         if (listener != null) {
-                            listener.onClick(null);
+                            listener.onClick(view);
                         }
                     }
                 };
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
index 9f409bb..4ca8376 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java
@@ -93,7 +93,7 @@
                     BrowserUiListMenuUtils.getBasicListMenu(
                             mContext,
                             mMenuList,
-                            (model) -> mOnMenuClickCallback.onResult(mContext));
+                            (model, unusedView) -> mOnMenuClickCallback.onResult(mContext));
             mListMenuDelegate =
                     new ListMenuDelegate() {
                         @Override
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_page_button/HomePageButtonsMediator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_page_button/HomePageButtonsMediator.java
index 36be26c..0b6698d2 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_page_button/HomePageButtonsMediator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/home_page_button/HomePageButtonsMediator.java
@@ -150,7 +150,8 @@
                     BrowserUiListMenuUtils.getBasicListMenu(
                             mContext,
                             mHomeButtonMenuList,
-                            (model) -> mOnHomeButtonMenuClickCallback.onResult(mContext));
+                            (model, unusedView) ->
+                                    mOnHomeButtonMenuClickCallback.onResult(mContext));
             mHomeButtonListMenuDelegate =
                     new ListMenuDelegate() {
                         @Override
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
index 50bf83a..ce125a4e 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/top/TabSwitcherActionMenuCoordinator.java
@@ -167,7 +167,7 @@
                 BrowserUiListMenuUtils.getBasicListMenu(
                         context,
                         listItems,
-                        (model) -> {
+                        (model, view) -> {
                             onItemClicked.onResult(model.get(ListMenuItemProperties.MENU_ITEM_ID));
                         });
 
diff --git a/chrome/browser/ui/browser_actions.cc b/chrome/browser/ui/browser_actions.cc
index c65d870b..f859505c2 100644
--- a/chrome/browser/ui/browser_actions.cc
+++ b/chrome/browser/ui/browser_actions.cc
@@ -56,7 +56,6 @@
 #include "chrome/browser/ui/views/file_system_access/file_system_access_bubble_controller.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/cookie_controls/cookie_controls_page_action_controller.h"
 #include "chrome/browser/ui/views/media_router/cast_browser_controller.h"
 #include "chrome/browser/ui/views/page_info/page_info_view_factory.h"
 #include "chrome/browser/ui/views/send_tab_to_self/send_tab_to_self_toolbar_bubble_controller.h"
@@ -607,24 +606,6 @@
           .Build());
 
   root_action_item_->AddChild(
-      actions::ActionItem::Builder(
-          base::BindRepeating(
-              [](BrowserWindowInterface* bwi, actions::ActionItem* item,
-                 actions::ActionInvocationContext context) {
-                tabs::TabInterface& tab =
-                    CHECK_DEREF(bwi->GetActiveTabInterface());
-                auto* controller =
-                    CookieControlsPageActionController::From(tab);
-                CHECK(controller);
-                controller->ExecutePageAction(bwi->GetBrowserForMigrationOnly()
-                                                  ->GetBrowserView()
-                                                  .toolbar_button_provider());
-              },
-              bwi))
-          .SetActionId(kActionShowCookieControls)
-          .Build());
-
-  root_action_item_->AddChild(
       ChromeMenuAction(
           base::BindRepeating(
               [](BrowserWindowInterface* bwi, actions::ActionItem* item,
diff --git a/chrome/browser/ui/browser_list.cc b/chrome/browser/ui/browser_list.cc
index edc3232..67fb3b5 100644
--- a/chrome/browser/ui/browser_list.cc
+++ b/chrome/browser/ui/browser_list.cc
@@ -75,28 +75,6 @@
   return nullptr;
 }
 
-void BrowserList::ForEachCurrentBrowser(
-    base::FunctionRef<void(Browser*)> on_browser) {
-  // Make a copy of the BrowserList to simplify the case where we need to
-  // add or remove a Browser during the loop.
-  constexpr bool kEnumerateNewBrowser = false;
-  BrowserListEnumerator browser_list_copy(kEnumerateNewBrowser);
-  while (!browser_list_copy.empty()) {
-    on_browser(browser_list_copy.Next());
-  }
-}
-
-void BrowserList::ForEachCurrentAndNewBrowser(
-    base::FunctionRef<void(Browser*)> on_browser) {
-  // Make a copy of the BrowserList to simplify the case where we need to
-  // add or remove a Browser during the loop.
-  constexpr bool kEnumerateNewBrowser = true;
-  BrowserListEnumerator browser_list_copy(kEnumerateNewBrowser);
-  while (!browser_list_copy.empty()) {
-    on_browser(browser_list_copy.Next());
-  }
-}
-
 // static
 BrowserList* BrowserList::GetInstance() {
   BrowserList** list = &instance_;
diff --git a/chrome/browser/ui/browser_list.h b/chrome/browser/ui/browser_list.h
index adc73d3..5b60ed3 100644
--- a/chrome/browser/ui/browser_list.h
+++ b/chrome/browser/ui/browser_list.h
@@ -56,13 +56,6 @@
   bool empty() const { return browsers_.empty(); }
   size_t size() const { return browsers_.size(); }
 
-  // Enumerate the current browser and the new browser in-order.
-  void ForEachCurrentAndNewBrowser(
-      base::FunctionRef<void(Browser*)> on_browser);
-
-  // Enumerate the current browser in-order.
-  void ForEachCurrentBrowser(base::FunctionRef<void(Browser*)> on_browser);
-
   // Returns iterated access to list of open browsers ordered by activation. The
   // underlying data structure is a vector and we push_back on recent access so
   // a reverse iterator gives the latest accessed browser first.
diff --git a/chrome/browser/ui/tabs/BUILD.gn b/chrome/browser/ui/tabs/BUILD.gn
index b34f583..81bce50 100644
--- a/chrome/browser/ui/tabs/BUILD.gn
+++ b/chrome/browser/ui/tabs/BUILD.gn
@@ -527,7 +527,6 @@
       "//chrome/browser/ui/user_education",
       "//chrome/browser/ui/views/intent_picker:intent_picker_page_action",
       "//chrome/browser/ui/views/location_bar",
-      "//chrome/browser/ui/views/location_bar/cookie_controls",
       "//chrome/browser/ui/views/page_action",
       "//chrome/browser/ui/views/page_info",
       "//chrome/browser/ui/views/side_panel",
diff --git a/chrome/browser/ui/tabs/public/tab_features.h b/chrome/browser/ui/tabs/public/tab_features.h
index ce1500f..b00abcd 100644
--- a/chrome/browser/ui/tabs/public/tab_features.h
+++ b/chrome/browser/ui/tabs/public/tab_features.h
@@ -15,7 +15,6 @@
 
 class AskBeforeHttpDialogController;
 class CollaborationMessagingPageActionController;
-class CookieControlsPageActionController;
 class FileSystemAccessPageActionController;
 class FromGWSNavigationAndKeepAliveRequestObserver;
 class IntentPickerViewPageActionController;
@@ -415,10 +414,6 @@
   std::unique_ptr<CollaborationMessagingPageActionController>
       collaboration_messaging_page_action_controller_;
 
-  // Manages the Cookie Controls page action.
-  std::unique_ptr<CookieControlsPageActionController>
-      cookie_controls_page_action_controller_;
-
 #if BUILDFLAG(ENABLE_GLIC)
   std::unique_ptr<glic::GlicInstanceHelper> glic_instance_helper_;
   std::unique_ptr<glic::GlicTabIndicatorHelper> glic_tab_indicator_helper_;
diff --git a/chrome/browser/ui/tabs/tab_features.cc b/chrome/browser/ui/tabs/tab_features.cc
index 5b60236f..7d53c8ee 100644
--- a/chrome/browser/ui/tabs/tab_features.cc
+++ b/chrome/browser/ui/tabs/tab_features.cc
@@ -69,7 +69,6 @@
 #include "chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h"
 #include "chrome/browser/ui/views/file_system_access/file_system_access_page_action_controller.h"
 #include "chrome/browser/ui/views/intent_picker/intent_picker_view_page_action_controller.h"
-#include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.h"
 #include "chrome/browser/ui/views/page_action/action_ids.h"
 #include "chrome/browser/ui/views/page_action/page_action_controller.h"
 #include "chrome/browser/ui/views/page_action/page_action_properties_provider.h"
@@ -216,14 +215,6 @@
           std::make_unique<ManagePasswordsPageActionController>(
               *page_action_controller_);
     }
-
-    if (IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-      cookie_controls_page_action_controller_ =
-          GetUserDataFactory()
-              .CreateInstance<CookieControlsPageActionController>(
-                  tab, tab, *profile, *page_action_controller_);
-      cookie_controls_page_action_controller_->Init();
-    }
   }
 
   // Features that are only enabled for normal browser windows. By default most
diff --git a/chrome/browser/ui/views/frame/contents_container_view.cc b/chrome/browser/ui/views/frame/contents_container_view.cc
index 4fc1fac..3f542505 100644
--- a/chrome/browser/ui/views/frame/contents_container_view.cc
+++ b/chrome/browser/ui/views/frame/contents_container_view.cc
@@ -447,6 +447,12 @@
   int height = size_bounds.height().value();
   int width = size_bounds.width().value();
 
+  if (width == 0 || height == 0) {
+    // On Wayland we receive a resize to 0 width first before the actual
+    // size bounds. Ignore such requests.
+    return layouts;
+  }
+
   gfx::Rect full_contents_bounds = GetContentsBounds();
   gfx::Rect devtools_bounds;
   // The area contents excluding devtools is drawn (ie |contents_view_|,
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.cc
index 297ea48..e370aea 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.cc
@@ -4,13 +4,11 @@
 
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_coordinator.h"
 
-#include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "chrome/browser/ui/views/frame/toolbar_button_provider.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_controller.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_impl.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 "ui/views/bubble/bubble_dialog_delegate_view.h"
 
 namespace content {
@@ -48,8 +46,8 @@
   bubble_view_ = bubble_view.get();
   bubble_view_->View::AddObserver(this);
 
-  auto* icon_view =
-      toolbar_button_provider->GetPageActionView(kActionShowCookieControls);
+  auto* icon_view = toolbar_button_provider->GetPageActionIconView(
+      PageActionIconType::kCookieControls);
   CHECK(icon_view);
   bubble_view_->SetHighlightedButton(icon_view);
 
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_pixel_test.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_pixel_test.cc
index 878a4e8..d186d8a 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_pixel_test.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view_pixel_test.cc
@@ -10,10 +10,8 @@
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
 #include "chrome/browser/privacy_sandbox/tracking_protection_settings_factory.h"
 #include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/location_bar/location_bar.h"
-#include "chrome/browser/ui/page_action/page_action_icon_type.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/toolbar_button_provider.h"
@@ -91,9 +89,10 @@
     content::SetupCrossSiteRedirector(https_test_server());
     ASSERT_TRUE(https_test_server()->Start());
 
-    cookie_controls_icon_ = BrowserView::GetBrowserViewForBrowser(browser())
-                                ->toolbar_button_provider()
-                                ->GetPageActionView(kActionShowCookieControls);
+    cookie_controls_icon_ = static_cast<CookieControlsIconView*>(
+        BrowserView::GetBrowserViewForBrowser(browser())
+            ->toolbar_button_provider()
+            ->GetPageActionIconView(PageActionIconType::kCookieControls));
     ASSERT_TRUE(cookie_controls_icon_);
 
     controller_ = std::make_unique<content_settings::CookieControlsController>(
@@ -113,7 +112,7 @@
             /*is_incognito_profile=*/true);
 
     cookie_controls_coordinator_ =
-        CookieControlsBubbleCoordinator::From(browser());
+        &cookie_controls_icon_->GetCoordinatorForTesting();
     cookie_controls_coordinator_->SetDisplayNameForTesting(u"example.com");
   }
 
@@ -144,7 +143,9 @@
                                        "/third_party_partitioned_cookies.html");
   }
 
-  IconLabelBubbleView* cookie_controls_icon() { return cookie_controls_icon_; }
+  CookieControlsIconView* cookie_controls_icon() {
+    return cookie_controls_icon_;
+  }
   net::EmbeddedTestServer* https_test_server() { return https_server_.get(); }
 
   CookieControlsBubbleViewController* view_controller() {
@@ -169,7 +170,7 @@
   std::unique_ptr<net::EmbeddedTestServer> https_server_;
   content::ContentMockCertVerifier mock_cert_verifier_;
   base::test::ScopedFeatureList scoped_feature_list_;
-  raw_ptr<IconLabelBubbleView> cookie_controls_icon_;
+  raw_ptr<CookieControlsIconView> cookie_controls_icon_;
   std::unique_ptr<content_settings::CookieControlsController> controller_;
   std::unique_ptr<content_settings::CookieControlsController>
       incognito_controller_;
@@ -218,10 +219,7 @@
     // needed for this test.
     view_controller()->OnStatusChanged(controls_state, enforcement,
                                        blocking_status, expiration);
-    if (!IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-      static_cast<CookieControlsIconView*>(cookie_controls_icon())
-          ->ExecuteForTesting();
-    }
+    cookie_controls_icon()->DisableUpdatesForTesting();
   }
 
   void ShowUi(const std::string& name_with_param_suffix) override {
@@ -230,15 +228,7 @@
     ASSERT_TRUE(cookie_controls_icon()->GetVisible());
     views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                          "CookieControlsBubbleViewImpl");
-    if (IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-      actions::ActionManager::Get()
-          .FindAction(kActionShowCookieControls)
-          ->InvokeAction();
-    } else {
-      static_cast<CookieControlsIconView*>(cookie_controls_icon())
-          ->ExecuteForTesting();
-    }
-
+    cookie_controls_icon()->ExecuteForTesting();
     SetStatus(controls_state_, enforcement_, GetParam(), days_to_expiration_);
     waiter.WaitIfNeededAndGet();
 
@@ -342,14 +332,7 @@
     ASSERT_TRUE(cookie_controls_icon()->GetVisible());
     views::NamedWidgetShownWaiter waiter(views::test::AnyWidgetTestPasskey{},
                                          "CookieControlsBubbleViewImpl");
-    if (IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-      actions::ActionManager::Get()
-          .FindAction(kActionShowCookieControls)
-          ->InvokeAction();
-    } else {
-      static_cast<CookieControlsIconView*>(cookie_controls_icon())
-          ->ExecuteForTesting();
-    }
+    cookie_controls_icon()->ExecuteForTesting();
     SetStatus(controls_state_, enforcement_);
     waiter.WaitIfNeededAndGet();
   }
@@ -369,10 +352,7 @@
     view_controller()->OnStatusChanged(controls_state, enforcement,
                                        CookieBlocking3pcdStatus::kNotIn3pcd,
                                        base::Time());
-    if (!IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-      static_cast<CookieControlsIconView*>(cookie_controls_icon())
-          ->ExecuteForTesting();
-    }
+    cookie_controls_icon()->DisableUpdatesForTesting();
   }
 
  protected:
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
index 085fb3e6..2689825 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_interactive_uitest.cc
@@ -20,7 +20,6 @@
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_bubble_view.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_content_view.h"
 #include "chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_icon_view.h"
-#include "chrome/browser/ui/views/location_bar/icon_label_bubble_view.h"
 #include "chrome/browser/ui/webui/feedback/feedback_dialog.h"
 #include "chrome/grit/generated_resources.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -398,7 +397,7 @@
       PressButton(CookieControlsContentView::kToggleButton),
       CheckFeedbackButtonVisible(false),
       CheckViewProperty(kCookieControlsIconElementId,
-                        &IconLabelBubbleView::is_animating_label, false),
+                        &CookieControlsIconView::is_animating_label, false),
       CheckStateForNoException());
 }
 
@@ -411,7 +410,7 @@
       InstrumentTab(kWebContentsElementId),
       NavigateWebContents(kWebContentsElementId, third_party_cookie_page_url()),
       CheckViewProperty(kCookieControlsIconElementId,
-                        &IconLabelBubbleView::is_animating_label, true));
+                        &CookieControlsIconView::is_animating_label, true));
 }
 
 // Need a separate fixture to override the enabled feature list.
@@ -423,16 +422,8 @@
   ~CookieControlsWithIphUiTest() override = default;
 };
 
-// TODO(crbug.com/409272227): IPH tests are flaky on Linux.
-#if BUILDFLAG(IS_LINUX) && defined(NDEBUG)
-#define MAYBE_ShowAndDismissIphOnHighSiteEngagement \
-  DISABLED_ShowAndDismissIphOnHighSiteEngagement
-#else
-#define MAYBE_ShowAndDismissIphOnHighSiteEngagement \
-  ShowAndDismissIphOnHighSiteEngagement
-#endif
 IN_PROC_BROWSER_TEST_F(CookieControlsWithIphUiTest,
-                       MAYBE_ShowAndDismissIphOnHighSiteEngagement) {
+                       ShowAndDismissIphOnHighSiteEngagement) {
   BlockThirdPartyCookies();
   SetHighSiteEngagement();
   RunTestSequence(
@@ -440,7 +431,7 @@
       NavigateWebContents(kWebContentsElementId, third_party_cookie_page_url()),
       // Check that label doesn't animate.
       CheckViewProperty(kCookieControlsIconElementId,
-                        &IconLabelBubbleView::is_animating_label, false),
+                        &CookieControlsIconView::is_animating_label, false),
       // Check that IPH shows, then dismiss it.
       InAnyContext(WaitForShow(
           user_education::HelpBubbleView::kHelpBubbleElementIdForTesting)),
@@ -785,7 +776,7 @@
       PressButton(CookieControlsContentView::kToggleButton),
       CheckFeedbackButtonVisible(false),
       CheckViewProperty(kCookieControlsIconElementId,
-                        &IconLabelBubbleView::is_animating_label, false),
+                        &CookieControlsIconView::is_animating_label, false),
       CheckUserBypassBlockedState());
 }
 
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.cc
index 2731184d..1510cdd 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.cc
@@ -124,8 +124,6 @@
 }
 }  // namespace
 
-DEFINE_USER_DATA(CookieControlsPageActionController);
-
 CookieControlsPageActionController::CookieControlsPageActionController(
     tabs::TabInterface& tab_interface,
     Profile& profile,
@@ -142,8 +140,7 @@
               HostContentSettingsMapFactory::GetForProfile(&profile),
               TrackingProtectionSettingsFactory::GetForProfile(&profile),
               profile.IsIncognitoProfile())),
-      bubble_delegate_(std::make_unique<BubbleDelegateImpl>(tab_interface)),
-      scoped_unowned_user_data_(tab_interface.GetUnownedUserDataHost(), *this) {
+      bubble_delegate_(std::make_unique<BubbleDelegateImpl>(tab_interface)) {
   CHECK(IsPageActionMigrated(PageActionIconType::kCookieControls));
   RegisterAsPageActionObserver(page_action_controller_.get());
 }
@@ -151,12 +148,6 @@
 CookieControlsPageActionController::~CookieControlsPageActionController() =
     default;
 
-// static
-CookieControlsPageActionController* CookieControlsPageActionController::From(
-    tabs::TabInterface& tab) {
-  return Get(tab.GetUnownedUserDataHost());
-}
-
 void CookieControlsPageActionController::Init() {
   controller_observation_.Observe(cookie_controls_controller_.get());
 
@@ -173,17 +164,7 @@
           [](content_settings::CookieControlsController& cookies_controller,
              tabs::TabInterface* tab, content::WebContents* old_contents,
              content::WebContents* new_contents) {
-            if (new_contents) {
-              cookies_controller.Update(new_contents);
-            }
-          },
-          std::ref(*cookie_controls_controller_)));
-
-  tab_deactivation_subscription_ =
-      tab_->RegisterWillDeactivate(base::BindRepeating(
-          [](content_settings::CookieControlsController& cookies_controller,
-             tabs::TabInterface* tab) {
-            cookies_controller.OnBubbleCloseTriggered();
+            cookies_controller.Update(new_contents);
           },
           std::ref(*cookie_controls_controller_)));
 }
@@ -237,8 +218,7 @@
   }
 
   if (!icon_status_.icon_visible || !icon_status_.should_highlight ||
-      icon_status_.controls_state != CookieControlsState::kBlocked3pc ||
-      bubble_delegate_->HasBubble()) {
+      icon_status_.controls_state != CookieControlsState::kBlocked3pc) {
     return;
   }
   if (icon_status_.blocking_status == CookieBlocking3pcdStatus::kNotIn3pcd) {
@@ -246,7 +226,7 @@
             tab_->GetBrowserWindowInterface())) {
       MaybeShowIPH(*user_education);
     }
-  } else if (!IsManagedIPHActive()) {
+  } else if (!bubble_delegate_->HasBubble() && !IsManagedIPHActive()) {
     page_action_controller_->OverrideText(
         kActionShowCookieControls,
         l10n_util::GetStringUTF16(
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.h b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.h
index 6722f23..da88008 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.h
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller.h
@@ -36,8 +36,6 @@
     : public content_settings::CookieControlsObserver,
       public page_actions::PageActionObserver {
  public:
-  DECLARE_USER_DATA(CookieControlsPageActionController);
-
   // An interface for interacting with the Cookie Controls bubble.
   class BubbleDelegate {
    public:
@@ -61,8 +59,6 @@
       const CookieControlsPageActionController&) = delete;
   ~CookieControlsPageActionController() override;
 
-  static CookieControlsPageActionController* From(tabs::TabInterface& tab);
-
   void Init();
 
   // PageActionObserver
@@ -116,8 +112,6 @@
   CookieControlsIconStatus icon_status_;
 
   base::CallbackListSubscription will_discard_contents_subscription_;
-  base::CallbackListSubscription tab_deactivation_subscription_;
-
   base::ScopedObservation<content_settings::CookieControlsController,
                           content_settings::CookieControlsObserver>
       controller_observation_{this};
@@ -125,9 +119,6 @@
   // Timer used to collapse from the chip state after some time.
   base::OneShotTimer hide_chip_timer_;
 
-  ui::ScopedUnownedUserData<CookieControlsPageActionController>
-      scoped_unowned_user_data_;
-
   base::WeakPtrFactory<CookieControlsPageActionController> weak_ptr_factory_{
       this};
 };
diff --git a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller_unittest.cc b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller_unittest.cc
index 7fa4e58c..dfce0b0e 100644
--- a/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller_unittest.cc
+++ b/chrome/browser/ui/views/location_bar/cookie_controls/cookie_controls_page_action_controller_unittest.cc
@@ -112,8 +112,14 @@
          {privacy_sandbox::kActUserBypassUx, {}}},
         {});
 
+    cookie_controls_page_action_controller_ =
+        std::make_unique<CookieControlsPageActionController>(
+            mock_tab_interface_, profile_, page_action_controller_);
+
     auto mock_bubble_delegate = std::make_unique<MockBubbleDelegate>();
     mock_bubble_delegate_ = mock_bubble_delegate.get();
+    controller().set_bubble_delegate_for_testing(
+        std::move(mock_bubble_delegate));
 
     web_contents_ =
         content::WebContentsTester::CreateTestWebContents(&profile_, nullptr);
@@ -121,8 +127,6 @@
         .WillByDefault(Return(web_contents_.get()));
     ON_CALL(mock_tab_interface_, GetBrowserWindowInterface())
         .WillByDefault(Return(&mock_browser_window_interface_));
-    ON_CALL(mock_tab_interface_, GetUnownedUserDataHost())
-        .WillByDefault(ReturnRef(user_data_host_));
     ON_CALL(mock_browser_window_interface_, GetUnownedUserDataHost())
         .WillByDefault(ReturnRef(user_data_host_));
     user_education_.emplace(&mock_browser_window_interface_);
@@ -142,12 +146,6 @@
     ON_CALL(*mock_bubble_delegate_, IsReloading()).WillByDefault(Return(false));
     ON_CALL(*mock_bubble_delegate_, HasBubble()).WillByDefault(Return(false));
 
-    cookie_controls_page_action_controller_ =
-        std::make_unique<CookieControlsPageActionController>(
-            mock_tab_interface_, profile_, page_action_controller_);
-    controller().set_bubble_delegate_for_testing(
-        std::move(mock_bubble_delegate));
-
     controller().Init();
   }
 
diff --git a/chrome/browser/ui/views/page_action/action_ids.h b/chrome/browser/ui/views/page_action/action_ids.h
index 3b86fce3..4884fa4 100644
--- a/chrome/browser/ui/views/page_action/action_ids.h
+++ b/chrome/browser/ui/views/page_action/action_ids.h
@@ -15,7 +15,7 @@
 // All ActionIds associated with a page action.
 // For now, the order of the page actions will be based on their position in
 // the array.
-inline constexpr std::array<actions::ActionId, 16> kActionIds = {
+inline constexpr std::array<actions::ActionId, 15> kActionIds = {
     kActionSidePanelShowLensOverlayResults,
     kActionShowTranslate,
     kActionShowMemorySaverChip,
@@ -31,7 +31,6 @@
     kActionAutofillMandatoryReauth,
     kActionFind,
     kActionAiMode,
-    kActionShowCookieControls,
 };
 
 }  // namespace page_actions
diff --git a/chrome/browser/ui/views/page_action/page_action_properties_provider.cc b/chrome/browser/ui/views/page_action/page_action_properties_provider.cc
index 0dc3daa..2e48dae 100644
--- a/chrome/browser/ui/views/page_action/page_action_properties_provider.cc
+++ b/chrome/browser/ui/views/page_action/page_action_properties_provider.cc
@@ -135,14 +135,6 @@
                 .element_identifier = FindBarIcon::kElementId,
             },
         },
-        {
-            kActionShowCookieControls,
-            {
-                .histogram_name = "CookieControls",
-                .type = PageActionIconType::kCookieControls,
-                .element_identifier = kCookieControlsIconElementId,
-            },
-        },
     });
 
 constexpr bool CheckIgnoreFlagUsage() {
diff --git a/chrome/browser/ui/views/permissions/embedded_permission_prompt.h b/chrome/browser/ui/views/permissions/embedded_permission_prompt.h
index 4aa9d76..7d730c9 100644
--- a/chrome/browser/ui/views/permissions/embedded_permission_prompt.h
+++ b/chrome/browser/ui/views/permissions/embedded_permission_prompt.h
@@ -7,7 +7,6 @@
 
 #include <optional>
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
 #include "chrome/browser/permissions/system/system_permission_settings.h"
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
index bdc23dc..992f063 100644
--- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc
+++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -23,14 +23,12 @@
 #include "chrome/browser/search/search.h"
 #include "chrome/browser/ui/actions/chrome_action_id.h"
 #include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_actions.h"
 #include "chrome/browser/ui/browser_element_identifiers.h"
 #include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/browser_navigator.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_features.h"
 #include "chrome/browser/ui/chrome_pages.h"
 #include "chrome/browser/ui/feature_first_run/autofill_ai_first_run_dialog.h"
-#include "chrome/browser/ui/page_action/page_action_icon_type.h"
 #include "chrome/browser/ui/performance_controls/performance_controls_metrics.h"
 #include "chrome/browser/ui/singleton_tabs.h"
 #include "chrome/browser/ui/tabs/saved_tab_groups/most_recent_shared_tab_update_store.h"
@@ -906,21 +904,13 @@
           base::BindRepeating(
               [](ContextPtr ctx,
                  user_education::FeaturePromoHandle promo_handle) {
-                if (IsPageActionMigrated(PageActionIconType::kCookieControls)) {
-                  actions::ActionManager::Get()
-                      .FindAction(
-                          kActionShowCookieControls,
-                          GetBrowser(ctx)->GetActions()->root_action_item())
-                      ->InvokeAction();
-                } else {
-                  auto* cookie_controls_icon_view =
-                      views::ElementTrackerViews::GetInstance()
-                          ->GetFirstMatchingViewAs<CookieControlsIconView>(
-                              kCookieControlsIconElementId,
-                              ctx->GetElementContext());
-                  if (cookie_controls_icon_view != nullptr) {
-                    cookie_controls_icon_view->ShowCookieControlsBubble();
-                  }
+                auto* cookie_controls_icon_view =
+                    views::ElementTrackerViews::GetInstance()
+                        ->GetFirstMatchingViewAs<CookieControlsIconView>(
+                            kCookieControlsIconElementId,
+                            ctx->GetElementContext());
+                if (cookie_controls_icon_view != nullptr) {
+                  cookie_controls_icon_view->ShowCookieControlsBubble();
                 }
               }))
           .SetBubbleTitleText(IDS_COOKIE_CONTROLS_PROMO_TITLE)
diff --git a/chrome/browser/ui/web_applications/app_browser_controller.cc b/chrome/browser/ui/web_applications/app_browser_controller.cc
index d16f9ccc..e3d036a 100644
--- a/chrome/browser/ui/web_applications/app_browser_controller.cc
+++ b/chrome/browser/ui/web_applications/app_browser_controller.cc
@@ -380,12 +380,8 @@
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
   std::vector<actions::ActionId> types_enabled = {
-      kActionFind,
-      kActionShowPasswordsBubbleOrPage,
-      kActionShowTranslate,
-      kActionZoomNormal,
-      kActionShowFileSystemAccess,
-      kActionShowCookieControls,
+      kActionFind,       kActionShowPasswordsBubbleOrPage, kActionShowTranslate,
+      kActionZoomNormal, kActionShowFileSystemAccess,
   };
 
 #if DCHECK_IS_ON()
diff --git a/chrome/browser/ui/webui/tabs/tabs_mojom_traits.h b/chrome/browser/ui/webui/tabs/tabs_mojom_traits.h
index 7f0cefe..592236c 100644
--- a/chrome/browser/ui/webui/tabs/tabs_mojom_traits.h
+++ b/chrome/browser/ui/webui/tabs/tabs_mojom_traits.h
@@ -5,7 +5,6 @@
 #ifndef CHROME_BROWSER_UI_WEBUI_TABS_TABS_MOJOM_TRAITS_H_
 #define CHROME_BROWSER_UI_WEBUI_TABS_TABS_MOJOM_TRAITS_H_
 
-#include "base/containers/fixed_flat_map.h"
 #include "chrome/browser/ui/tabs/alert/tab_alert.h"
 #include "chrome/browser/ui/tabs/tab_network_state.h"
 #include "chrome/browser/ui/webui/tabs/tabs.mojom.h"
diff --git a/chrome/browser/web_applications/commands/clear_browsing_data_command_unittest.cc b/chrome/browser/web_applications/commands/clear_browsing_data_command_unittest.cc
index 409cba0..16c49ae 100644
--- a/chrome/browser/web_applications/commands/clear_browsing_data_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/clear_browsing_data_command_unittest.cc
@@ -20,20 +20,14 @@
  protected:
   void SetUp() override {
     WebAppTest::SetUp();
-    web_app_provider_ = FakeWebAppProvider::Get(profile());
-    web_app_provider_->StartWithSubsystems();
+    fake_provider().StartWithSubsystems();
   }
 
   void Init() {
     base::RunLoop run_loop;
-    provider()->on_registry_ready().Post(FROM_HERE, run_loop.QuitClosure());
+    fake_provider().on_registry_ready().Post(FROM_HERE, run_loop.QuitClosure());
     run_loop.Run();
   }
-
-  FakeWebAppProvider* provider() { return web_app_provider_; }
-
- private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> web_app_provider_ = nullptr;
 };
 
 TEST_F(ClearBrowsingDataCommandTest, ClearLastLaunchTimeForAllTimes) {
@@ -55,30 +49,30 @@
 
   {
     ScopedRegistryUpdate update =
-        provider()->sync_bridge_unsafe().BeginUpdate();
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     update->CreateApp(std::move(web_app1));
     update->CreateApp(std::move(web_app2));
     update->CreateApp(std::move(web_app3));
   }
 
-  EXPECT_EQ(3UL, provider()->registrar_unsafe().GetAppIds().size());
+  EXPECT_EQ(3UL, fake_provider().registrar_unsafe().GetAppIds().size());
   EXPECT_EQ(launch_time1,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id1));
   EXPECT_EQ(launch_time2,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id2));
   EXPECT_EQ(launch_time3,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id3));
 
   base::test::TestFuture<void> future;
-  provider()->scheduler().ClearWebAppBrowsingData(
+  fake_provider().scheduler().ClearWebAppBrowsingData(
       base::Time(), base::Time::Now(), future.GetCallback());
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id1));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id2));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id3));
 }
 
 TEST_F(ClearBrowsingDataCommandTest, ClearLastLaunchTimeForSpecificTimeRange) {
@@ -100,37 +94,37 @@
 
   {
     ScopedRegistryUpdate update =
-        provider()->sync_bridge_unsafe().BeginUpdate();
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     update->CreateApp(std::move(web_app1));
     update->CreateApp(std::move(web_app2));
     update->CreateApp(std::move(web_app3));
   }
 
-  EXPECT_EQ(3UL, provider()->registrar_unsafe().GetAppIds().size());
+  EXPECT_EQ(3UL, fake_provider().registrar_unsafe().GetAppIds().size());
   EXPECT_EQ(launch_time1,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id1));
   EXPECT_EQ(launch_time2,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id2));
   EXPECT_EQ(launch_time3,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id3));
 
   base::test::TestFuture<void> future;
-  provider()->scheduler().ClearWebAppBrowsingData(
+  fake_provider().scheduler().ClearWebAppBrowsingData(
       base::Time() + base::Seconds(5), base::Time() + base::Seconds(15),
       future.GetCallback());
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(launch_time1,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id1));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id2));
   EXPECT_EQ(launch_time3,
-            provider()->registrar_unsafe().GetAppLastLaunchTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastLaunchTime(app_id3));
 }
 
 TEST_F(ClearBrowsingDataCommandTest,
        ClearLastLaunchTimeCalledBeforeWebAppProviderIsReady) {
   base::test::TestFuture<void> future;
-  provider()->scheduler().ClearWebAppBrowsingData(
+  fake_provider().scheduler().ClearWebAppBrowsingData(
       base::Time(), base::Time::Now(), future.GetCallback());
   Init();
   EXPECT_TRUE(future.Wait());
@@ -155,31 +149,31 @@
 
   {
     ScopedRegistryUpdate update =
-        provider()->sync_bridge_unsafe().BeginUpdate();
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     update->CreateApp(std::move(web_app1));
     update->CreateApp(std::move(web_app2));
     update->CreateApp(std::move(web_app3));
   }
 
-  EXPECT_EQ(3UL, provider()->registrar_unsafe().GetAppIds().size());
+  EXPECT_EQ(3UL, fake_provider().registrar_unsafe().GetAppIds().size());
   EXPECT_EQ(badging_time1,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id1));
   EXPECT_EQ(badging_time2,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id2));
   EXPECT_EQ(badging_time3,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id3));
 
   base::test::TestFuture<void> future;
-  provider()->scheduler().ClearWebAppBrowsingData(
+  fake_provider().scheduler().ClearWebAppBrowsingData(
       base::Time(), base::Time::Now(), future.GetCallback());
 
   EXPECT_TRUE(future.Wait());
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id1));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id2));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id3));
 }
 
 TEST_F(ClearBrowsingDataCommandTest, ClearLastBadgingTimeForSpecificTimeRange) {
@@ -201,32 +195,32 @@
 
   {
     ScopedRegistryUpdate update =
-        provider()->sync_bridge_unsafe().BeginUpdate();
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     update->CreateApp(std::move(web_app1));
     update->CreateApp(std::move(web_app2));
     update->CreateApp(std::move(web_app3));
   }
 
-  EXPECT_EQ(3UL, provider()->registrar_unsafe().GetAppIds().size());
+  EXPECT_EQ(3UL, fake_provider().registrar_unsafe().GetAppIds().size());
   EXPECT_EQ(badging_time1,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id1));
   EXPECT_EQ(badging_time2,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id2));
   EXPECT_EQ(badging_time3,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id3));
 
   base::test::TestFuture<void> future;
-  provider()->scheduler().ClearWebAppBrowsingData(
+  fake_provider().scheduler().ClearWebAppBrowsingData(
       base::Time() + base::Seconds(5), base::Time() + base::Seconds(15),
       future.GetCallback());
   EXPECT_TRUE(future.Wait());
 
   EXPECT_EQ(badging_time1,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id1));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id1));
   EXPECT_EQ(base::Time(),
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id2));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id2));
   EXPECT_EQ(badging_time3,
-            provider()->registrar_unsafe().GetAppLastBadgingTime(app_id3));
+            fake_provider().registrar_unsafe().GetAppLastBadgingTime(app_id3));
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc b/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
index a5b37ce9..bd325d0d 100644
--- a/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/install_app_locally_command_unittest.cc
@@ -50,7 +50,6 @@
       base::ScopedAllowBlockingForTesting allow_blocking;
       test_override_ = OsIntegrationTestOverrideImpl::OverrideForTesting();
     }
-    provider_ = FakeWebAppProvider::Get(profile());
 
     auto file_handler_manager =
         std::make_unique<WebAppFileHandlerManager>(profile());
@@ -60,7 +59,7 @@
         profile(), std::move(file_handler_manager),
         std::move(protocol_handler_manager));
 
-    provider_->SetOsIntegrationManager(std::move(os_integration_manager));
+    fake_provider().SetOsIntegrationManager(std::move(os_integration_manager));
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
@@ -92,7 +91,7 @@
     params.add_to_quick_launch_bar = false;
     params.add_to_search = false;
     // InstallFromInfo does not trigger OS integration.
-    provider().scheduler().InstallFromInfoWithParams(
+    fake_provider().scheduler().InstallFromInfoWithParams(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         result.GetCallback(), params);
@@ -116,7 +115,6 @@
   }
 
  protected:
-  WebAppProvider& provider() { return *provider_; }
   SkBitmap CreateSolidColorIcon(int size, SkColor color) {
     SkBitmap bitmap;
     bitmap.allocN32Pixels(size, size);
@@ -161,7 +159,6 @@
   }
 
  private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
   std::unique_ptr<OsIntegrationTestOverrideImpl::BlockingRegistration>
       test_override_;
 };
@@ -179,7 +176,8 @@
       InstallNonLocallyInstalledAppWithIcons(std::move(icon_map));
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
@@ -190,32 +188,34 @@
 
   // Install app locally.
   base::test::TestFuture<void> test_future;
-  provider().scheduler().InstallAppLocally(app_id, test_future.GetCallback());
+  fake_provider().scheduler().InstallAppLocally(app_id,
+                                                test_future.GetCallback());
   EXPECT_TRUE(test_future.Wait());
 
   auto updated_state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(updated_state.has_value());
   const proto::os_state::WebAppOsIntegration& updated_os_states =
       updated_state.value();
   ASSERT_TRUE(updated_os_states.has_shortcut());
 
   EXPECT_TRUE(
-      provider().registrar_unsafe().GetAppById(app_id)->GetSources().Has(
+      fake_provider().registrar_unsafe().GetAppById(app_id)->GetSources().Has(
           WebAppManagement::kUserInstalled));
 
   // OS integration should be triggered now.
   if (HasShortcutsOsIntegration()) {
     ASSERT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
 
     // On all desktop platforms, the shortcut icon that is used for the
     // launcher is icon_size::k128, which should be GREEN as per the icon_map
     // being used above.
     ASSERT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorGREEN));
   }
 }
@@ -224,9 +224,10 @@
   const webapps::AppId app_id = "abcde";
 
   base::test::TestFuture<void> test_future;
-  provider().scheduler().InstallAppLocally(app_id, test_future.GetCallback());
+  fake_provider().scheduler().InstallAppLocally(app_id,
+                                                test_future.GetCallback());
   EXPECT_TRUE(test_future.Wait());
-  EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(app_id));
+  EXPECT_FALSE(fake_provider().registrar_unsafe().IsInRegistrar(app_id));
 }
 
 }  // namespace
diff --git a/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc b/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
index b975eff..9331470 100644
--- a/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
+++ b/chrome/browser/web_applications/commands/os_integration_synchronize_command_unittest.cc
@@ -60,7 +60,6 @@
       test_override_ = OsIntegrationTestOverrideImpl::OverrideForTesting();
     }
 
-    provider_ = FakeWebAppProvider::Get(profile());
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
@@ -79,7 +78,7 @@
           webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON) {
     base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         result;
-    provider()->scheduler().InstallFromInfoWithParams(
+    fake_provider().scheduler().InstallFromInfoWithParams(
         std::move(install_info), /*overwrite_existing_manifest_fields=*/true,
         source, result.GetCallback(), WebAppInstallParams());
     bool success = result.Wait();
@@ -94,21 +93,19 @@
 
   void RunSynchronizeCommand(const webapps::AppId& app_id) {
     base::test::TestFuture<void> synchronize_future;
-    provider()->scheduler().SynchronizeOsIntegration(
+    fake_provider().scheduler().SynchronizeOsIntegration(
         app_id, synchronize_future.GetCallback());
     EXPECT_TRUE(synchronize_future.Wait());
   }
 
   bool EnableRunOnOsLoginMode(const webapps::AppId& app_id) {
     base::test::TestFuture<void> future;
-    provider()->scheduler().SetRunOnOsLoginMode(
+    fake_provider().scheduler().SetRunOnOsLoginMode(
         app_id, RunOnOsLoginMode::kWindowed, future.GetCallback());
     return future.Wait();
   }
 
  protected:
-  WebAppProvider* provider() { return provider_; }
-
   ShortcutsMenuIconBitmaps MakeIconBitmaps(
       const std::vector<GeneratedIconsInfo>& icons_info,
       int num_menu_items) {
@@ -182,7 +179,6 @@
   }
 
  private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
   std::unique_ptr<OsIntegrationTestOverrideImpl::BlockingRegistration>
       test_override_;
 };
@@ -205,7 +201,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> state =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
@@ -227,7 +224,7 @@
   // that synchronize picks this up.
   {
     ScopedRegistryUpdate update =
-        provider()->sync_bridge_unsafe().BeginUpdate();
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     WebApp* app = update->UpdateApp(app_id);
     std::vector<apps::ProtocolHandlerInfo> protocol_handlers =
         app->protocol_handlers();
@@ -236,8 +233,8 @@
   }
   RunSynchronizeCommand(app_id);
 
-  state =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+  state = fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+      app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& new_os_integration_state =
       state.value();
@@ -276,7 +273,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> state =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
@@ -302,7 +300,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> current_states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(current_states.has_value());
   ASSERT_TRUE(current_states.value().has_run_on_os_login());
   const proto::os_state::RunOnOsLogin& pre_run_on_os_login =
@@ -313,7 +312,8 @@
   EnableRunOnOsLoginMode(app_id);
 
   std::optional<proto::os_state::WebAppOsIntegration> states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(states.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       states.value();
@@ -342,7 +342,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(states.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       states.value();
@@ -391,7 +392,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(states.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       states.value();
@@ -416,7 +418,8 @@
   const webapps::AppId& app_id = InstallWebApp(std::move(install_info));
 
   std::optional<proto::os_state::WebAppOsIntegration> states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(states.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       states.value();
@@ -444,7 +447,7 @@
 
   base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
       result;
-  provider()->scheduler().InstallFromInfoWithParams(
+  fake_provider().scheduler().InstallFromInfoWithParams(
       std::move(install_info), /*overwrite_existing_manifest_fields=*/true,
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON, result.GetCallback(),
       params);
@@ -454,20 +457,21 @@
 
   const webapps::AppId& app_id = result.Get<webapps::AppId>();
   std::optional<proto::os_state::WebAppOsIntegration> states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(states.has_value());
   EXPECT_FALSE(states->has_shortcut());
 
   base::test::TestFuture<void> done;
   SynchronizeOsOptions options;
   options.add_shortcut_to_desktop = true;
-  provider()->scheduler().SynchronizeOsIntegration(
+  fake_provider().scheduler().SynchronizeOsIntegration(
       app_id, done.GetCallback(), options,
       /*upgrade_to_fully_installed_if_installed=*/true);
   ASSERT_TRUE(done.Wait());
 
-  states =
-      provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+  states = fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+      app_id);
   ASSERT_TRUE(states.has_value());
   EXPECT_TRUE(states->has_shortcut());
 }
@@ -477,7 +481,7 @@
   base::test::TestFuture<void> done;
   SynchronizeOsOptions options;
   options.add_shortcut_to_desktop = true;
-  provider()->scheduler().SynchronizeOsIntegration(
+  fake_provider().scheduler().SynchronizeOsIntegration(
       "non-existent-app-id", done.GetCallback(), options,
       /*upgrade_to_fully_installed_if_installed=*/true);
   ASSERT_TRUE(done.Wait());
diff --git a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
index 21cebbb..2d55aacf 100644
--- a/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
+++ b/chrome/browser/web_applications/externally_managed_app_manager_unittest.cc
@@ -81,11 +81,10 @@
  protected:
   void SetUp() override {
     WebAppTest::SetUp();
-    provider_ = web_app::FakeWebAppProvider::Get(profile());
     web_app::test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
-  void ForceSystemShutdown() { provider_->Shutdown(); }
+  void ForceSystemShutdown() { fake_provider().Shutdown(); }
 
   void Sync(const std::vector<GURL>& urls, bool include_duplicates = false) {
     ResetCounts();
@@ -99,7 +98,7 @@
     }
 
     base::RunLoop run_loop;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         std::move(install_options_list),
         ExternalInstallSource::kInternalDefault,
         base::BindLambdaForTesting(
@@ -138,15 +137,13 @@
     uninstall_count_ = 0;
   }
 
-  WebAppProvider& provider() { return *provider_; }
-
-  WebAppRegistrar& app_registrar() { return provider().registrar_unsafe(); }
+  WebAppRegistrar& app_registrar() {
+    return fake_provider().registrar_unsafe();
+  }
 
  private:
   int install_count_ = 0;
   int uninstall_count_ = 0;
-
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
 };
 
 // Test that destroying ExternallyManagedAppManager during a synchronize call
@@ -161,7 +158,7 @@
                                     mojom::UserDisplayMode::kStandalone,
                                     ExternalInstallSource::kInternalDefault);
 
-  provider().externally_managed_app_manager().SynchronizeInstalledApps(
+  fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
       std::move(install_options_list), ExternalInstallSource::kInternalDefault,
       // ExternallyManagedAppManager gives no guarantees about whether its
       // pending callbacks will be run or not when it gets destroyed.
@@ -181,7 +178,7 @@
                                       mojom::UserDisplayMode::kStandalone,
                                       ExternalInstallSource::kInternalDefault);
     base::RunLoop run_loop;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         std::move(install_options_list),
         ExternalInstallSource::kInternalDefault,
         base::BindLambdaForTesting(
@@ -192,7 +189,7 @@
     run_loop.Run();
   }
 
-  provider().externally_managed_app_manager().SynchronizeInstalledApps(
+  fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
       std::vector<ExternalInstallOptions>(),
       ExternalInstallSource::kInternalDefault,
       // ExternallyManagedAppManager gives no guarantees about whether its
@@ -210,7 +207,8 @@
   GURL e("https://e.example.com/");
 
   FakeWebContentsManager& web_contents_manager =
-      static_cast<FakeWebContentsManager&>(provider().web_contents_manager());
+      static_cast<FakeWebContentsManager&>(
+          fake_provider().web_contents_manager());
   web_contents_manager.CreateBasicInstallPageState(a, a, a);
   web_contents_manager.CreateBasicInstallPageState(b, b, b);
   web_contents_manager.CreateBasicInstallPageState(c, c, c);
@@ -320,17 +318,17 @@
     return options;
   }
 
-  WebAppProvider& provider() { return *WebAppProvider::GetForTest(profile()); }
-
-  WebAppRegistrar& app_registrar() { return provider().registrar_unsafe(); }
+  WebAppRegistrar& app_registrar() {
+    return fake_provider().registrar_unsafe();
+  }
 
   ExternallyManagedAppManager& external_manager() {
-    return provider().externally_managed_app_manager();
+    return fake_provider().externally_managed_app_manager();
   }
 
   FakeWebContentsManager& web_contents_manager() {
     return static_cast<FakeWebContentsManager&>(
-        provider().web_contents_manager());
+        fake_provider().web_contents_manager());
   }
 };
 
@@ -705,7 +703,7 @@
           ExternallyManagedAppManager::InstallResult(
               webapps::InstallResultCode::kSuccessNewInstall, app_id))));
 
-  const WebApp* app = provider().registrar_unsafe().GetAppById(app_id);
+  const WebApp* app = fake_provider().registrar_unsafe().GetAppById(app_id);
 
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
@@ -784,7 +782,7 @@
   // Synchronize with 2 install URLs.
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl1, kInstallUrl2},
             ExternalInstallSource::kExternalPolicy),
@@ -822,7 +820,7 @@
   // Synchronize with 1 install URL.
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl1}, ExternalInstallSource::kExternalPolicy),
         ExternalInstallSource::kExternalPolicy, result.GetCallback());
@@ -856,7 +854,7 @@
   // Synchronize with 0 install URLs.
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {}, ExternalInstallSource::kExternalPolicy),
         ExternalInstallSource::kExternalPolicy, result.GetCallback());
@@ -933,7 +931,7 @@
                     kInstallUrl, webapps::UninstallResultCode::kAppRemoved)));
   }
 
-  const WebApp* app = provider().registrar_unsafe().GetAppById(app_id);
+  const WebApp* app = fake_provider().registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
               ElementsAre(std::make_pair(WebAppManagement::kPolicy,
@@ -981,7 +979,7 @@
         u"Test policy app";
 
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kExternalPolicy),
         ExternalInstallSource::kExternalPolicy, result.GetCallback());
@@ -1027,7 +1025,7 @@
           ExternallyManagedAppManager::InstallResult(
               webapps::InstallResultCode::kSuccessNewInstall, app_id))));
 
-  const WebApp* app = provider().registrar_unsafe().GetAppById(app_id);
+  const WebApp* app = fake_provider().registrar_unsafe().GetAppById(app_id);
 
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
@@ -1074,7 +1072,7 @@
           ExternallyManagedAppManager::InstallResult(
               webapps::InstallResultCode::kSuccessNewInstall, app_id))));
 
-  const WebApp* app = provider().registrar_unsafe().GetAppById(app_id);
+  const WebApp* app = fake_provider().registrar_unsafe().GetAppById(app_id);
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
               ElementsAre(std::make_pair(WebAppManagement::kPolicy,
@@ -1100,7 +1098,7 @@
   page_state.redirection_url = kRedirectToUrl;
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kExternalPolicy,
             template_options),
@@ -1111,7 +1109,7 @@
   webapps::AppId placeholder_app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, kInstallUrl);
 
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(placeholder_app_id));
 
   // Replace the redirect with an app that resolves.
@@ -1121,7 +1119,7 @@
   // The placeholder app should be uninstalled & the real one installed.
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kExternalPolicy,
             template_options),
@@ -1129,7 +1127,7 @@
     ASSERT_TRUE(result.Wait());
   }
 
-  app_ids = provider().registrar_unsafe().GetAppIds();
+  app_ids = fake_provider().registrar_unsafe().GetAppIds();
 
   EXPECT_THAT(app_ids, ElementsAre(app_id));
 }
@@ -1150,7 +1148,7 @@
   page_state.redirection_url = kRedirectToUrl;
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kExternalPolicy,
             template_options),
@@ -1161,7 +1159,7 @@
   webapps::AppId placeholder_app_id =
       GenerateAppId(/*manifest_id=*/std::nullopt, kInstallUrl);
 
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(placeholder_app_id));
 
   // Replace the redirect with an app that resolves.
@@ -1173,11 +1171,11 @@
   options.placeholder_resolution_behavior =
       PlaceholderResolutionBehavior::kClose;
   InstallNowFuture install_future;
-  provider().externally_managed_app_manager().InstallNow(
+  fake_provider().externally_managed_app_manager().InstallNow(
       std::move(options), install_future.GetCallback());
   ASSERT_TRUE(install_future.Wait());
 
-  app_ids = provider().registrar_unsafe().GetAppIds();
+  app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id));
 }
 
@@ -1201,12 +1199,12 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
   }
 
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
   webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
@@ -1216,14 +1214,14 @@
     ExternalInstallOptions options = template_options;
     options.install_url = kInstallUrl;
     InstallNowFuture install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
   }
 
   // TODO(crbug.com/40264854): This keeps the original app, but perhaps
   // should install app_id2.
-  app_ids = provider().registrar_unsafe().GetAppIds();
+  app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 }
 
@@ -1247,12 +1245,12 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
   }
 
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
   webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
@@ -1263,14 +1261,14 @@
     options.install_url = kInstallUrl;
     options.install_source = ExternalInstallSource::kInternalDefault;
     InstallNowFuture install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
   }
 
   // TODO(crbug.com/40264854): Currently, this keeps the original app,
   // but we should eventually resolve all apps to app_id2.
-  app_ids = provider().registrar_unsafe().GetAppIds();
+  app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 }
 
@@ -1290,7 +1288,7 @@
 
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kExternalPolicy,
             template_options),
@@ -1298,7 +1296,7 @@
     ASSERT_TRUE(result.Wait());
   }
 
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, ElementsAre(app_id1));
 
   webapps::AppId app_id2 = web_contents_manager().CreateBasicInstallPageState(
@@ -1306,7 +1304,7 @@
 
   {
     SynchronizeFuture result;
-    provider().externally_managed_app_manager().SynchronizeInstalledApps(
+    fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
         CreateExternalInstallOptionsFromTemplate(
             {kInstallUrl}, ExternalInstallSource::kInternalDefault,
             template_options),
@@ -1316,7 +1314,7 @@
 
   // TODO(crbug.com/40264854): Currently this resolves to app_id1, but
   // should probably eventually resolve to app_id2.
-  app_ids = provider().registrar_unsafe().GetAppIds();
+  app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids, UnorderedElementsAre(app_id1));
 }
 
@@ -1347,7 +1345,7 @@
     ExternalInstallOptions options = template_options;
     options.install_url = kInstallUrl1;
     InstallNowFuture install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
     EXPECT_THAT(
@@ -1364,7 +1362,7 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
     EXPECT_THAT(
@@ -1382,7 +1380,7 @@
   // sources, which will (correctly?) evaluate the manifest served by the
   // install url of the first install, which could be a different app identity.
   const WebApp* app =
-      provider().registrar_unsafe().GetAppById(app_at_install_url);
+      fake_provider().registrar_unsafe().GetAppById(app_at_install_url);
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
               ElementsAre(std::make_pair(
@@ -1418,7 +1416,7 @@
           kInstallUrl2, kManifestUrl, /*start_url=*/kInstallUrl1);
 
   SynchronizeFuture result;
-  provider().externally_managed_app_manager().SynchronizeInstalledApps(
+  fake_provider().externally_managed_app_manager().SynchronizeInstalledApps(
       CreateExternalInstallOptionsFromTemplate(
           {kInstallUrl1, kInstallUrl2}, ExternalInstallSource::kExternalPolicy,
           template_options),
@@ -1444,7 +1442,7 @@
   // when the second install succeeds, it overrides the `is_placeholder` to
   // `false`, and thus the first install is considered fully installed now too.
   const WebApp* app =
-      provider().registrar_unsafe().GetAppById(app_at_install_url);
+      fake_provider().registrar_unsafe().GetAppById(app_at_install_url);
   ASSERT_TRUE(app);
   EXPECT_THAT(app->management_to_external_config_map(),
               ElementsAre(std::make_pair(
@@ -1496,7 +1494,7 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
     EXPECT_THAT(
@@ -1514,7 +1512,7 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
     EXPECT_THAT(
@@ -1526,7 +1524,7 @@
   }
 
   const WebApp* app =
-      provider().registrar_unsafe().GetAppById(app_at_install_url);
+      fake_provider().registrar_unsafe().GetAppById(app_at_install_url);
   ASSERT_TRUE(app);
   EXPECT_THAT(
       app->management_to_external_config_map(),
@@ -1551,7 +1549,7 @@
     base::test::TestFuture<const GURL&,
                            ExternallyManagedAppManager::InstallResult>
         install_future;
-    provider().externally_managed_app_manager().InstallNow(
+    fake_provider().externally_managed_app_manager().InstallNow(
         std::move(options), install_future.GetCallback());
     ASSERT_TRUE(install_future.Wait());
 
@@ -1565,7 +1563,7 @@
 
   // This is the current behavior, but it could change if we decide that
   // 'placeholder' is a per-app state instead of a per-app-and-source state.
-  auto app_ids = provider().registrar_unsafe().GetAppIds();
+  auto app_ids = fake_provider().registrar_unsafe().GetAppIds();
   EXPECT_THAT(app_ids,
               UnorderedElementsAre(app_at_install_url, app_at_start_url));
 }
diff --git a/chrome/browser/web_applications/os_integration/mac/shortcuts_versioning_mac_unittest.cc b/chrome/browser/web_applications/os_integration/mac/shortcuts_versioning_mac_unittest.cc
index 868115b..c69a1f6 100644
--- a/chrome/browser/web_applications/os_integration/mac/shortcuts_versioning_mac_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/mac/shortcuts_versioning_mac_unittest.cc
@@ -48,17 +48,16 @@
     override_registration_ =
         OsIntegrationTestOverrideImpl::OverrideForTesting();
 
-    provider_ = FakeWebAppProvider::Get(profile());
-
     // These tests require a real OsIntegrationManager, rather than the
     // FakeOsIntegrationManager that is created by default.
     auto file_handler_manager =
         std::make_unique<WebAppFileHandlerManager>(profile());
     auto protocol_handler_manager =
         std::make_unique<WebAppProtocolHandlerManager>(profile());
-    provider_->SetOsIntegrationManager(std::make_unique<OsIntegrationManager>(
-        profile(), std::move(file_handler_manager),
-        std::move(protocol_handler_manager)));
+    fake_provider().SetOsIntegrationManager(
+        std::make_unique<OsIntegrationManager>(
+            profile(), std::move(file_handler_manager),
+            std::move(protocol_handler_manager)));
 
     // Do not yet start WebAppProvider here in SetUp, as tests verify behavior
     // that happens during and is triggered by start. As such individual tests
@@ -93,8 +92,6 @@
  private:
   std::unique_ptr<OsIntegrationTestOverrideImpl::BlockingRegistration>
       override_registration_;
-
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
 };
 
 TEST_F(ShortcutsVersioningMacTest, InitialVersionIsStored) {
diff --git a/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
index d7afcd40..b9e7ebf 100644
--- a/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/shortcut_sub_manager_unittest.cc
@@ -54,8 +54,6 @@
       base::ScopedAllowBlockingForTesting allow_blocking;
       test_override_ = OsIntegrationTestOverrideImpl::OverrideForTesting();
     }
-    provider_ = FakeWebAppProvider::Get(profile());
-
     auto file_handler_manager =
         std::make_unique<WebAppFileHandlerManager>(profile());
     auto protocol_handler_manager =
@@ -64,7 +62,7 @@
         profile(), std::move(file_handler_manager),
         std::move(protocol_handler_manager));
 
-    provider_->SetOsIntegrationManager(std::move(os_integration_manager));
+    fake_provider().SetOsIntegrationManager(std::move(os_integration_manager));
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
@@ -92,7 +90,7 @@
     }
     base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         result;
-    provider().scheduler().InstallFromInfoWithParams(
+    fake_provider().scheduler().InstallFromInfoWithParams(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         result.GetCallback(), WebAppInstallParams());
@@ -107,7 +105,6 @@
   }
 
  protected:
-  WebAppProvider& provider() { return *provider_; }
   SkBitmap CreateSolidColorIcon(int size, SkColor color) {
     SkBitmap bitmap;
     bitmap.allocN32Pixels(size, size);
@@ -116,7 +113,6 @@
   }
 
  private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
   std::unique_ptr<OsIntegrationTestOverrideImpl::BlockingRegistration>
       test_override_;
 };
@@ -148,7 +144,8 @@
   const webapps::AppId& app_id = InstallWebAppWithShortcuts(icon_map);
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   ASSERT_THAT(state.value().shortcut().title(), testing::Eq("Test App"));
@@ -175,7 +172,8 @@
       InstallWebAppWithShortcuts(icon_map, /*skip_trusted_icons=*/true);
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   // Instead of the specific trusted icons of 2 sizes being used, the test will
@@ -205,7 +203,8 @@
 
   test::UninstallAllWebApps(profile());
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_FALSE(state.has_value());
 }
 
@@ -282,8 +281,8 @@
 
     base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         update_future;
-    provider().install_finalizer().FinalizeUpdate(*updated_info,
-                                                  update_future.GetCallback());
+    fake_provider().install_finalizer().FinalizeUpdate(
+        *updated_info, update_future.GetCallback());
     bool success = update_future.Wait();
     if (!success) {
       return webapps::AppId();
@@ -305,7 +304,7 @@
     base::test::TestFuture<const webapps::AppId&, webapps::InstallResultCode>
         result;
     // InstallFromInfoNoIntegrationForTesting() does not trigger OS integration.
-    provider().scheduler().InstallFromInfoNoIntegrationForTesting(
+    fake_provider().scheduler().InstallFromInfoNoIntegrationForTesting(
         std::move(info), /*overwrite_existing_manifest_fields=*/true,
         webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
         result.GetCallback());
@@ -333,20 +332,21 @@
       InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   if (HasShortcutsOsIntegration()) {
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
 
     // On all desktop platforms, the shortcut icon that is used for the
     // launcher is icon_size::k128, which should be GREEN as per the icon_map
     // being used above.
     EXPECT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorGREEN));
   }
 }
@@ -360,16 +360,17 @@
       InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   if (HasShortcutsOsIntegration()) {
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
     EXPECT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorYELLOW));
   }
 
@@ -381,7 +382,7 @@
   EXPECT_EQ(updated_app_id, app_id);
 
   auto updated_state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
           updated_app_id);
   ASSERT_TRUE(updated_state.has_value());
 
@@ -392,10 +393,10 @@
 #if !BUILDFLAG(IS_MAC)
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
     EXPECT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorBLUE));
 #endif  // !BUILDFLAG(IS_MAC)
   }
@@ -409,14 +410,16 @@
   const webapps::AppId& app_id =
       InstallWebAppNoIntegration(std::move(icon_map));
 
-  std::string app_name = provider().registrar_unsafe().GetAppShortName(app_id);
+  std::string app_name =
+      fake_provider().registrar_unsafe().GetAppShortName(app_id);
 
   // Call synchronize with empty options to set up the current_states, but
   // without any shortcut locations defined.
   test::SynchronizeOsIntegration(profile(), app_id, SynchronizeOsOptions());
 
   auto os_integration_state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(os_integration_state.has_value());
   EXPECT_FALSE(os_integration_state->has_shortcut());
 
@@ -431,12 +434,13 @@
 
   // This should trigger the application to become fully installed.
   base::test::TestFuture<void> future;
-  provider().scheduler().SetUserDisplayMode(
+  fake_provider().scheduler().SetUserDisplayMode(
       app_id, mojom::UserDisplayMode::kStandalone, future.GetCallback());
   ASSERT_TRUE(future.Wait());
 
   os_integration_state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(os_integration_state.has_value());
   EXPECT_TRUE(os_integration_state->has_shortcut());
 
@@ -447,8 +451,8 @@
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id, app_name));
     EXPECT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorRED));
 #endif
   }
@@ -463,7 +467,7 @@
   ASSERT_EQ(expected_app_id, app_id);
 
   os_integration_state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
           expected_app_id);
   ASSERT_TRUE(os_integration_state.has_value());
 
@@ -477,7 +481,7 @@
 #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN)
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), expected_app_id,
-        provider().registrar_unsafe().GetAppShortName(expected_app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(expected_app_id)));
     EXPECT_THAT(GetShortcutColor(expected_app_id, app_name),
                 testing::Eq(SK_ColorYELLOW));
 #endif
@@ -494,16 +498,17 @@
       InstallWebAppWithShortcuts(std::move(icon_map));
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   if (HasShortcutsOsIntegration()) {
     EXPECT_TRUE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
     EXPECT_THAT(
-        GetShortcutColor(app_id,
-                         provider().registrar_unsafe().GetAppShortName(app_id)),
+        GetShortcutColor(
+            app_id, fake_provider().registrar_unsafe().GetAppShortName(app_id)),
         testing::Eq(SK_ColorRED));
   }
 
@@ -511,7 +516,7 @@
   if (HasShortcutsOsIntegration()) {
     EXPECT_FALSE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id,
-        provider().registrar_unsafe().GetAppShortName(app_id)));
+        fake_provider().registrar_unsafe().GetAppShortName(app_id)));
   }
 }
 
@@ -524,10 +529,11 @@
   const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map));
   const std::string& app_name =
-      provider().registrar_unsafe().GetAppShortName(app_id);
+      fake_provider().registrar_unsafe().GetAppShortName(app_id);
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   if (HasShortcutsOsIntegration()) {
@@ -554,10 +560,11 @@
   const webapps::AppId& app_id =
       InstallWebAppWithShortcuts(std::move(icon_map));
   const std::string& app_name =
-      provider().registrar_unsafe().GetAppShortName(app_id);
+      fake_provider().registrar_unsafe().GetAppShortName(app_id);
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
 
   if (HasShortcutsOsIntegration()) {
@@ -570,7 +577,7 @@
     EXPECT_FALSE(OsIntegrationTestOverrideImpl::Get()->IsShortcutCreated(
         profile(), app_id, app_name));
   }
-  EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(app_id));
+  EXPECT_FALSE(fake_provider().registrar_unsafe().IsInRegistrar(app_id));
 
   // Force unregister shouldn't change anything.
   SynchronizeOsOptions options;
diff --git a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
index fc4d9c4..8a92043 100644
--- a/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/uninstallation_via_os_settings_sub_manager_unittest.cc
@@ -45,7 +45,6 @@
 
   void SetUp() override {
     WebAppTest::SetUp();
-    provider_ = FakeWebAppProvider::Get(profile());
 
     auto file_handler_manager =
         std::make_unique<WebAppFileHandlerManager>(profile());
@@ -55,7 +54,7 @@
         profile(), std::move(file_handler_manager),
         std::move(protocol_handler_manager));
 
-    provider_->SetOsIntegrationManager(std::move(os_integration_manager));
+    fake_provider().SetOsIntegrationManager(std::move(os_integration_manager));
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
@@ -74,7 +73,7 @@
         result;
     // InstallFromInfoWithParams is used instead of InstallFromInfo, because
     // InstallFromInfo doesn't register OS integration.
-    provider().scheduler().InstallFromInfoWithParams(
+    fake_provider().scheduler().InstallFromInfoWithParams(
         std::move(info), /*overwrite_existing_manifest_fields=*/true, source,
         result.GetCallback(), WebAppInstallParams());
     bool success = result.Wait();
@@ -86,12 +85,6 @@
               webapps::InstallResultCode::kSuccessNewInstall);
     return result.Get<webapps::AppId>();
   }
-
- protected:
-  WebAppProvider& provider() { return *provider_; }
-
- private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
 };
 
 bool IsOsUninstallationSupported() {
@@ -116,7 +109,8 @@
 #endif  // BUILDFLAG(IS_WIN)
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
@@ -137,7 +131,8 @@
       InstallWebApp(webapps::WebappInstallSource::EXTERNAL_POLICY);
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
@@ -164,7 +159,8 @@
   base::HistogramTester histogram_tester;
   test::UninstallAllWebApps(profile());
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_FALSE(state.has_value());
   base::expected<bool, std::string> install_result =
       fake_os_integration().IsUninstallRegisteredWithOs(app_id, "Test App",
@@ -197,7 +193,8 @@
 #endif  // BUILDFLAG(IS_WIN)
 
   auto state =
-      provider().registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
+      fake_provider().registrar_unsafe().GetAppCurrentOsIntegrationState(
+          app_id);
   ASSERT_TRUE(state.has_value());
   const proto::os_state::WebAppOsIntegration& os_integration_state =
       state.value();
diff --git a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
index 9606c16..67426e71 100644
--- a/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
+++ b/chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager_unittest.cc
@@ -25,8 +25,7 @@
   void SetUp() override {
     WebAppTest::SetUp();
 
-    provider_ = FakeWebAppProvider::Get(profile());
-    provider_->SetOsIntegrationManager(
+    fake_provider().SetOsIntegrationManager(
         std::make_unique<FakeOsIntegrationManager>(
             profile(),
             /*file_handler_manager=*/nullptr,
@@ -35,14 +34,14 @@
   }
 
   WebAppProtocolHandlerManager& protocol_handler_manager() {
-    return provider()
+    return fake_provider()
         .os_integration_manager()
         .protocol_handler_manager_for_testing();
   }
 
-  WebAppProvider& provider() { return *provider_; }
-
-  WebAppRegistrar& app_registrar() { return provider().registrar_unsafe(); }
+  WebAppRegistrar& app_registrar() {
+    return fake_provider().registrar_unsafe();
+  }
 
   webapps::AppId CreateWebAppWithProtocolHandlers(
       const GURL& start_url,
@@ -56,7 +55,7 @@
     web_app->SetDisallowedLaunchProtocols(disallowed_launch_protocols);
     {
       ScopedRegistryUpdate update =
-          provider().sync_bridge_unsafe().BeginUpdate();
+          fake_provider().sync_bridge_unsafe().BeginUpdate();
       update->CreateApp(std::move(web_app));
     }
     return app_id;
@@ -77,9 +76,6 @@
             CreateProtocolHandlerInfo("web+test2",
                                       GURL("http://example.com/test2=%s"))};
   }
-
- private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
 };
 
 TEST_F(WebAppProtocolHandlerManagerTest, GetAppProtocolHandlerInfos) {
@@ -94,7 +90,8 @@
       protocol_handler_manager().GetAppProtocolHandlerInfos(app_id).size(), 0U);
 
   {
-    ScopedRegistryUpdate update = provider().sync_bridge_unsafe().BeginUpdate();
+    ScopedRegistryUpdate update =
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
     update->CreateApp(std::move(web_app));
   }
 
diff --git a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
index 022474c..2d1ae88 100644
--- a/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/policy/web_app_policy_manager_unittest.cc
@@ -248,19 +248,19 @@
 #endif
     auto web_app_policy_manager =
         std::make_unique<WebAppPolicyManager>(profile());
-    web_app_policy_manager_ = web_app_policy_manager.get();
-    provider_->SetWebAppPolicyManager(std::move(web_app_policy_manager));
-
 #if BUILDFLAG(IS_CHROMEOS)
-    web_app_policy_manager_->SetSystemWebAppDelegateMap(
+    web_app_policy_manager->SetSystemWebAppDelegateMap(
         &system_app_manager().system_app_delegates());
 #endif
+    provider_->SetWebAppPolicyManager(std::move(web_app_policy_manager));
 
     test::AwaitStartWebAppProviderAndSubsystems(profile());
   }
 
   void TearDown() override {
     provider_->Shutdown();
+    // Reset to prevent dangling.
+    provider_ = nullptr;
 #if BUILDFLAG(IS_CHROMEOS)
     test_system_app_manager_.reset();
 #endif
@@ -361,9 +361,7 @@
   data_decoder::test::InProcessDataDecoder data_decoder_;
 
  private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
-  raw_ptr<WebAppPolicyManager, DanglingUntriaged> web_app_policy_manager_ =
-      nullptr;
+  raw_ptr<FakeWebAppProvider> provider_ = nullptr;
 
 #if BUILDFLAG(IS_WIN)
   // This is used to prevent creating shortcuts in the start menu dir.
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/vids.cc b/chrome/browser/web_applications/preinstalled_web_apps/vids.cc
index 7d624cf..a577348 100644
--- a/chrome/browser/web_applications/preinstalled_web_apps/vids.cc
+++ b/chrome/browser/web_applications/preinstalled_web_apps/vids.cc
@@ -24,10 +24,9 @@
 
 namespace {
 
-blink::Manifest::TabStrip HomeTabPathnames(
+blink::Manifest::HomeTabParams HomeTabPathnames(
     std::vector<std::string_view> pathnames) {
-  blink::Manifest::TabStrip tab_strip;
-  auto& home_tab = tab_strip.home_tab.emplace<blink::Manifest::HomeTabParams>();
+  blink::Manifest::HomeTabParams home_tab;
 
   for (const std::string_view pathname : pathnames) {
     base::expected<liburlpattern::Pattern, absl::Status> parse_result =
@@ -44,7 +43,7 @@
     home_tab.scope_patterns.push_back(std::move(url_pattern));
   }
 
-  return tab_strip;
+  return home_tab;
 }
 
 }  // namespace
@@ -68,10 +67,15 @@
     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->tab_strip.emplace();
+    info->tab_strip->new_tab_button.url =
+        GURL("https://docs.google.com/videos/u/0/create?usp=webapp_tab_strip");
+    info->tab_strip->home_tab = HomeTabPathnames({
+        "/videos/", "/videos/u/:index", "/videos/u/:index/",
+        // The manifest officially includes the following pathnames however they
+        // are not in scope and would be ignored by blink::ManifestParser.
+        // "/a/:domain/videos",
+        // "/a/:domain/videos/",
     });
     info->icon_bitmaps.any =
         LoadBundledIcons({IDR_PREINSTALLED_WEB_APPS_VIDS_ICON_144_PNG});
diff --git a/chrome/browser/web_applications/test/web_app_test.cc b/chrome/browser/web_applications/test/web_app_test.cc
index 4f301dcc..bbecb6a 100644
--- a/chrome/browser/web_applications/test/web_app_test.cc
+++ b/chrome/browser/web_applications/test/web_app_test.cc
@@ -44,6 +44,8 @@
   // Make sure that we flush any messages related to WebContentsImpl
   // destruction before we destroy the profiles.
   base::RunLoop().RunUntilIdle();
+  // Reset `profile_` to prevent dangling.
+  profile_ = nullptr;
   testing_profile_manager_.DeleteAllTestingProfiles();
   content::RenderViewHostTestHarness::TearDown();
 }
diff --git a/chrome/browser/web_applications/test/web_app_test.h b/chrome/browser/web_applications/test/web_app_test.h
index 5f6e6c70..464c7539 100644
--- a/chrome/browser/web_applications/test/web_app_test.h
+++ b/chrome/browser/web_applications/test/web_app_test.h
@@ -93,7 +93,7 @@
 
   TestingProfileManager testing_profile_manager_{
       TestingBrowserProcess::GetGlobal()};
-  raw_ptr<TestingProfile, DanglingUntriaged> profile_ = nullptr;
+  raw_ptr<TestingProfile> profile_ = nullptr;
 };
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_TEST_WEB_APP_TEST_H_
diff --git a/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc b/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
index 4870d24..5775fef 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler_unittest.cc
@@ -21,20 +21,13 @@
 
 class WebAppCommandSchedulerTest : public WebAppTest {
  public:
-  void SetUp() override {
-    WebAppTest::SetUp();
-    provider_ = FakeWebAppProvider::Get(profile());
-  }
-
-  FakeWebAppProvider* provider() { return provider_; }
-
   bool IsCommandQueued(std::string_view command_name) {
     // Note: Accessing & using the debug value for tests is poor practice and
     // should not be done, given how easily the format can be changed.
     // TODO(b/318858671): Update logic to not read command errors from debug
     // log.
     base::Value::Dict log =
-        provider()->command_manager().ToDebugValue().TakeDict();
+        fake_provider().command_manager().ToDebugValue().TakeDict();
     for (const base::Value& command : *log.FindList("command_queue")) {
       if (*command.GetDict().FindDict("!metadata")->FindString("name") ==
           command_name) {
@@ -43,47 +36,44 @@
     }
     return false;
   }
-
- private:
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
 };
 
 TEST_F(WebAppCommandSchedulerTest, FetchManifestAndInstall) {
-  EXPECT_FALSE(provider()->is_registry_ready());
-  provider()->scheduler().FetchManifestAndInstall(
+  EXPECT_FALSE(fake_provider().is_registry_ready());
+  fake_provider().scheduler().FetchManifestAndInstall(
       webapps::WebappInstallSource::OMNIBOX_INSTALL_ICON,
       web_contents()->GetWeakPtr(), base::DoNothing(), base::DoNothing(),
       FallbackBehavior::kCraftedManifestOnly);
 
-  provider()->StartWithSubsystems();
-  EXPECT_EQ(provider()->command_manager().GetStartedCommandCountForTesting(),
-            0);
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 1u);
+  fake_provider().StartWithSubsystems();
+  EXPECT_EQ(
+      fake_provider().command_manager().GetStartedCommandCountForTesting(), 0);
+  EXPECT_EQ(fake_provider().command_manager().GetCommandCountForTesting(), 1u);
 
   EXPECT_TRUE(IsCommandQueued("FetchManifestAndInstallCommand"));
 }
 
 TEST_F(WebAppCommandSchedulerTest, PersistFileHandlersUserChoice) {
-  EXPECT_FALSE(provider()->is_registry_ready());
-  provider()->scheduler().PersistFileHandlersUserChoice(
+  EXPECT_FALSE(fake_provider().is_registry_ready());
+  fake_provider().scheduler().PersistFileHandlersUserChoice(
       "app id", /*allowed=*/true, base::DoNothing());
 
-  provider()->StartWithSubsystems();
-  EXPECT_EQ(provider()->command_manager().GetStartedCommandCountForTesting(),
-            0);
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 1u);
+  fake_provider().StartWithSubsystems();
+  EXPECT_EQ(
+      fake_provider().command_manager().GetStartedCommandCountForTesting(), 0);
+  EXPECT_EQ(fake_provider().command_manager().GetCommandCountForTesting(), 1u);
 
   EXPECT_TRUE(IsCommandQueued("UpdateFileHandlerCommand"));
 
-  test::WaitUntilReady(provider());
-  provider()->command_manager().AwaitAllCommandsCompleteForTesting();
+  test::WaitUntilReady(&fake_provider());
+  fake_provider().command_manager().AwaitAllCommandsCompleteForTesting();
   EXPECT_FALSE(IsCommandQueued("UpdateFileHandlerCommand"));
 
-  provider()->Shutdown();
+  fake_provider().Shutdown();
   base::test::TestFuture<void> after_shutdown;
-  provider()->scheduler().PersistFileHandlersUserChoice(
+  fake_provider().scheduler().PersistFileHandlersUserChoice(
       "app id", /*allowed=*/true, after_shutdown.GetCallback());
-  EXPECT_EQ(provider()->command_manager().GetCommandCountForTesting(), 0u);
+  EXPECT_EQ(fake_provider().command_manager().GetCommandCountForTesting(), 0u);
   ASSERT_TRUE(after_shutdown.Wait());
 }
 
diff --git a/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc b/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
index 43a55237..ff401e5 100644
--- a/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
+++ b/chrome/browser/web_applications/web_app_run_on_os_login_manager_unittest.cc
@@ -63,12 +63,11 @@
   void SetUp() override {
     WebAppTest::SetUp();
 
-    provider_ = FakeWebAppProvider::Get(profile());
-
     // Set up policy before managers are started.
     SetWebAppSettingsPref();
 
-    ui_manager_ = static_cast<FakeWebAppUiManager*>(&provider_->GetUiManager());
+    ui_manager_ =
+        static_cast<FakeWebAppUiManager*>(&fake_provider().GetUiManager());
     ui_manager_->SetOnLaunchWebAppCallback(base::BindLambdaForTesting(
         [this](apps::AppLaunchParams params,
                LaunchWebAppWindowSetting launch_setting) {
@@ -99,7 +98,7 @@
 
   void TearDown() override {
     ui_manager_ = nullptr;
-    provider_->Shutdown();
+    fake_provider().Shutdown();
     WebAppTest::TearDown();
   }
 
@@ -107,7 +106,7 @@
   virtual void SetWebAppSettingsPref() = 0;
 
   void AwaitAllCommandsComplete() {
-    provider_->command_manager().AwaitAllCommandsCompleteForTesting();
+    fake_provider().command_manager().AwaitAllCommandsCompleteForTesting();
   }
 
   const std::vector<apps::AppLaunchParams>& launched_apps() {
@@ -119,7 +118,6 @@
   raw_ptr<FakeWebAppUiManager> ui_manager_ = nullptr;
   std::unique_ptr<NotificationDisplayServiceTester> tester_;
   std::vector<apps::AppLaunchParams> launched_apps_;
-  raw_ptr<FakeWebAppProvider, DanglingUntriaged> provider_ = nullptr;
   std::unique_ptr<base::AutoReset<bool>> skip_run_on_os_login_startup_;
   base::test::ScopedFeatureList scoped_feature_list_{
       features::kDesktopPWAsRunOnOsLogin};
@@ -160,7 +158,7 @@
 
     ui_manager_->SetNumWindowsForApp(web_app->app_id(), 0);
 
-    WebAppSyncBridge& sync_bridge = provider_->sync_bridge_unsafe();
+    WebAppSyncBridge& sync_bridge = fake_provider().sync_bridge_unsafe();
     ScopedRegistryUpdate update = sync_bridge.BeginUpdate();
     update->CreateApp(std::move(web_app));
   }
@@ -199,7 +197,7 @@
 
     ui_manager_->SetNumWindowsForApp(app_id_, 0);
 
-    WebAppSyncBridge& sync_bridge = provider_->sync_bridge_unsafe();
+    WebAppSyncBridge& sync_bridge = fake_provider().sync_bridge_unsafe();
     ScopedRegistryUpdate update = sync_bridge.BeginUpdate();
     update->CreateApp(std::move(web_app));
   }
@@ -212,7 +210,7 @@
 
 TEST_F(WebAppRunOnOsLoginManagerSimpleSettingsTest, SimpleAppStarted) {
   InstallWebApp();
-  provider_->run_on_os_login_manager().RunAppsOnOsLoginForTesting();
+  fake_provider().run_on_os_login_manager().RunAppsOnOsLoginForTesting();
 
   AwaitAllCommandsComplete();
 
@@ -224,7 +222,7 @@
 TEST_F(WebAppRunOnOsLoginManagerSimpleSettingsTest, NoDuplicateAppStarted) {
   InstallWebApp();
   OpenWindowForTestApp();
-  provider_->run_on_os_login_manager().RunAppsOnOsLoginForTesting();
+  fake_provider().run_on_os_login_manager().RunAppsOnOsLoginForTesting();
 
   AwaitAllCommandsComplete();
 
@@ -236,7 +234,7 @@
 TEST_P(WebAppRunOnOsLoginManagerParameterizedTest, WebAppRunOnOsLogin) {
   // Arrange: Install PWA, then perform ROOL
   InstallWebApp();
-  provider_->run_on_os_login_manager().RunAppsOnOsLoginForTesting();
+  fake_provider().run_on_os_login_manager().RunAppsOnOsLoginForTesting();
 
   bool launch_by_policy = GetPolicyRunOnOsLoginValue() == "run_windowed";
   bool launch_by_user_mode =
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 8f0eaf5..af045ddd 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1760032697-30e12b5477ff27391444b5405e88ee2ecef4deed-5ebac065273ad576443305529c9fabd9674b3194.profdata
+chrome-android32-main-1760075958-5dac83d69a23d2667fae7f2a759a7e980cc078d3-f113a07b377f1e0945860e94c5af9162ae19d88c.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index c1c957d..9df7039 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1760041576-9ad91a75912eed908e9f5e1f55d1ca56c5ea9587-bb0c86a4501202e6c1ffe8d66e410e8caaecc695.profdata
+chrome-android64-main-1760074521-fd8e4c1bfa8c2e623822d14559cb63be799d90b0-0e358e86a57e35309ec254024d75f1a42c761b78.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index 1855b1c0..fd1d31c 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1760032697-83b54e91c7dc491aae9c14c742e31943ff0f1e14-5ebac065273ad576443305529c9fabd9674b3194.profdata
+chrome-android-desktop-x64-main-1760075958-70cf24307c4c8472426999e975894982332cb6af-f113a07b377f1e0945860e94c5af9162ae19d88c.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 2b873e4c..58b6d76 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1760032697-fdf90bdf25df11e0a6bc09d8193e245c386d91a6-5ebac065273ad576443305529c9fabd9674b3194.profdata
+chrome-linux-main-1760054239-fc35d37eb8a999678a16c165b3d984a3e4370d72-624f65c8ade90ee5cec765b255bfa0c22cd90260.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index a05db2be..b0b8ffc 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1760046645-b04f533ed728ece02f1e28b61411d5ee88c70210-b33e2e50b7b970fb2115a9e6bbdd24d97ab37094.profdata
+chrome-mac-arm-main-1760075958-292d196fe7b0fcde9a39311e92c5ec8ce51a0e65-f113a07b377f1e0945860e94c5af9162ae19d88c.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 518a3b4..5d7467e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1760021978-cfb8a1b5473e67384497b631fb956cdbce345e5c-5c566706e4cbe7325df6e7d459ab259dd4fd5bb3.profdata
+chrome-win32-main-1760054239-0fd31437c9d9382dd8d125be47b179cec7a1bdf3-624f65c8ade90ee5cec765b255bfa0c22cd90260.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 7fcb75c7b..4bea759f 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1760010767-42b5539635d81f27b5ba07fe899ec88a3a3a08dc-b6cf2846f815e220e0bca95894aa92177af24263.profdata
+chrome-win64-main-1760043579-2198d74d36b28ed3f72f3bc226841705af7d513e-1c7306de74076ca4be38de4fcaca89200675870a.profdata
diff --git a/chrome/common/extensions/api/tabs.json b/chrome/common/extensions/api/tabs.json
index 36ed715..c1a9758 100644
--- a/chrome/common/extensions/api/tabs.json
+++ b/chrome/common/extensions/api/tabs.json
@@ -55,7 +55,7 @@
           "splitViewId": {
             "type": "integer",
             "minimum": -1,
-            "optional": "true",
+            "optional": true,
             "description": "The ID of the Split View that the tab belongs to.",
             // TODO(crbug.com/433273595): Enable documentation when ready for launch.
             "nodoc": true
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn
index aab8c58..c20e8e92 100644
--- a/chrome/test/data/webui/new_tab_page/BUILD.gn
+++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -9,6 +9,7 @@
 
 build_webui_tests("build") {
   files = [
+            "action_chips_test.ts",
             "app_test.ts",
             "background_manager_test.ts",
             "doodle_share_dialog_focus_test.ts",
diff --git a/chrome/test/data/webui/new_tab_page/action_chips_test.ts b/chrome/test/data/webui/new_tab_page/action_chips_test.ts
new file mode 100644
index 0000000..769ca9a
--- /dev/null
+++ b/chrome/test/data/webui/new_tab_page/action_chips_test.ts
@@ -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.
+
+import type {ActionChipsElement} from 'chrome://new-tab-page/lazy_load.js';
+import {assertTrue} from 'chrome://webui-test/chai_assert.js';
+import {microtasksFinished} from 'chrome://webui-test/test_util.js';
+
+suite('NewTabPageActionChipsTest', () => {
+  let chips: ActionChipsElement;
+
+  setup(async () => {
+    document.body.innerHTML = window.trustedTypes!.emptyHTML;
+    chips = document.createElement('ntp-action-chips');
+    document.body.append(chips);
+    await microtasksFinished();
+  });
+
+  test('creates component', () => {
+    assertTrue(!!chips);
+  });
+});
diff --git a/chrome/test/data/webui/new_tab_page/app_test.ts b/chrome/test/data/webui/new_tab_page/app_test.ts
index 50ac7aa..764163e2 100644
--- a/chrome/test/data/webui/new_tab_page/app_test.ts
+++ b/chrome/test/data/webui/new_tab_page/app_test.ts
@@ -1827,4 +1827,20 @@
       assertTrue(!!$$(app, '#backgroundImageAttribution'));
     });
   });
+
+  suite('ActionChips', () => {
+    [true, false].forEach(
+        (ntpNextFeaturesEnabled) =>
+            suite(`actionChips rendered ${ntpNextFeaturesEnabled}`, () => {
+              suiteSetup(() => {
+                loadTimeData.overrideValues({ntpNextFeaturesEnabled});
+              });
+
+              test('Show iframe when appropriate', () => {
+                const chips = $$<HTMLElement>(app, 'ntp-action-chips');
+
+                assertEquals(!!chips, ntpNextFeaturesEnabled);
+              });
+            }));
+  });
 });
diff --git a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
index 48cee88c..b557e4d 100644
--- a/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
+++ b/chrome/test/data/webui/new_tab_page/new_tab_page_browsertest.cc
@@ -80,6 +80,10 @@
   RunTest("new_tab_page/composebox/file_thumbnail_test.js", "mocha.run()");
 }
 
+IN_PROC_BROWSER_TEST_F(NewTabPageTest, ActionChips) {
+  RunTest("new_tab_page/action_chips_test.js", "mocha.run()");
+}
+
 using NewTabPageNtpPromoTest = NewTabPageBrowserTest;
 
 IN_PROC_BROWSER_TEST_F(NewTabPageNtpPromoTest, IndividualPromosTest) {
@@ -239,6 +243,11 @@
           "runMochaSuite('NewTabPageAppTest ComposeEntryPoint')");
 }
 
+IN_PROC_BROWSER_TEST_F(NewTabPageAppTest, ActionChips) {
+  RunTest("new_tab_page/app_test.js",
+          "runMochaSuite('NewTabPageAppTest ActionChips')");
+}
+
 // TODO(crbug.com/448987783): Re-enable test
 #if BUILDFLAG(IS_LINUX)
 #define MAYBE_WallpaperSearch DISABLED_WallpaperSearch
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 7c1ce1a..45b0e94 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-16444.0.0-1072295
\ No newline at end of file
+16444.0.0-1072302
\ No newline at end of file
diff --git a/clank b/clank
index a1cdb51..9e4d283 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit a1cdb512a2766a95f6951d17383fe33866937534
+Subproject commit 9e4d283fad19a1dcbca60502aa223a944a0b567b
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
index 41fca837..e576569 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -1734,7 +1734,7 @@
         menuItems.add(ListItemBuilder.buildSimpleMenuItem(R.string.remove));
 
         ListMenu.Delegate delegate =
-                (model) -> {
+                (model, view) -> {
                     int textId = model.get(ListMenuItemProperties.TITLE_ID);
                     if (textId == R.string.edit) {
                         buildPreferenceDialog(websitePreference.site()).show();
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/BrowserUiListMenuUnitTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/BrowserUiListMenuUnitTest.java
index 39110b5f..5ec8b1f 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/BrowserUiListMenuUnitTest.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/BrowserUiListMenuUnitTest.java
@@ -104,7 +104,7 @@
 
     @Test
     public void testScrollHairline() {
-        mBasicListMenu = getBasicListMenu(mActivity, mData, item -> {});
+        mBasicListMenu = getBasicListMenu(mActivity, mData, (item, view) -> {});
         mContentView = Mockito.spy(setupListViewForSubmenuTesting());
         // Assert not showing before navigation
         View hairline = mView.findViewById(R.id.menu_header_bottom_hairline);
@@ -141,7 +141,7 @@
     @Test
     public void testScrollHairline_color() {
         int colorIntForTest = 10;
-        mBasicListMenu = getBasicListMenu(mActivity, mData, item -> {}, 0, colorIntForTest);
+        mBasicListMenu = getBasicListMenu(mActivity, mData, (item, view) -> {}, 0, colorIntForTest);
         setupListViewForSubmenuTesting();
         View hairline = mView.findViewById(R.id.menu_header_bottom_hairline);
         assertEquals(colorIntForTest, ((ColorDrawable) hairline.getBackground()).getColor());
@@ -149,7 +149,7 @@
 
     @Test
     public void testScroll_noHeader_noHairline() {
-        mBasicListMenu = getBasicListMenu(mActivity, mData, item -> {});
+        mBasicListMenu = getBasicListMenu(mActivity, mData, (item, view) -> {});
         ListView listView = setupListViewForSubmenuTesting();
         // Assert not showing before navigation
         View hairline = mView.findViewById(R.id.menu_header_bottom_hairline);
@@ -173,7 +173,7 @@
                                 .with(SUBMENU_ITEMS, submenuItems)
                                 .build());
         data.add(submenuParentItem);
-        mBasicListMenu = getBasicListMenu(mActivity, data, item -> {}, 0, colorIntForTest);
+        mBasicListMenu = getBasicListMenu(mActivity, data, (item, view) -> {}, 0, colorIntForTest);
         mBasicListMenu.setupCallbacksRecursively(
                 () -> {}, /* drillDownOverrideValue= */ null, /* flyoutController= */ null);
         mView = mBasicListMenu.getContentView();
@@ -199,7 +199,7 @@
 
     @Test
     public void testKeyboardNavigation() {
-        mBasicListMenu = getBasicListMenu(mActivity, mData, item -> {});
+        mBasicListMenu = getBasicListMenu(mActivity, mData, (item, view) -> {});
         View view = mBasicListMenu.getContentView();
         ListView headerView = view.findViewById(R.id.menu_header);
         ListView contentView = setupListViewForSubmenuTesting();
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java
index e473860..13501c8 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java
@@ -15,6 +15,7 @@
 import android.view.View;
 import android.view.View.OnDragListener;
 import android.view.View.OnLayoutChangeListener;
+import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
 import android.view.Window;
 import android.view.WindowManager;
@@ -31,6 +32,7 @@
 import org.chromium.ui.dragdrop.DragEventDispatchHelper;
 import org.chromium.ui.dragdrop.DragEventDispatchHelper.DragEventDispatchDestination;
 import org.chromium.ui.interpolators.Interpolators;
+import org.chromium.ui.listmenu.ListMenuUtils;
 import org.chromium.ui.util.ColorUtils;
 import org.chromium.ui.widget.AnchoredPopupWindow;
 import org.chromium.ui.widget.FlyoutPopupSpecCalculator;
@@ -402,4 +404,13 @@
     OnDragListener getOnDragListenerForTesting() {
         return mDragEventDispatchHelper;
     }
+
+    /**
+     * Set the focus state for this dialog's content view.
+     *
+     * @param hasFocus Whether this dialog's content should have focus.
+     */
+    public void setWindowFocus(boolean hasFocus) {
+        ListMenuUtils.setWindowFocus((ViewGroup) mContentView, hasFocus);
+    }
 }
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/BrowserUiListMenuRenderTest.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/BrowserUiListMenuRenderTest.java
index 2190fc6..cec26d86 100644
--- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/BrowserUiListMenuRenderTest.java
+++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/listmenu/BrowserUiListMenuRenderTest.java
@@ -95,7 +95,7 @@
         mRenderTestRule.setNightModeEnabled(nightMode);
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
-                    ListMenu.Delegate delegate = item -> {};
+                    ListMenu.Delegate delegate = (item, view) -> {};
                     BasicListMenu listMenu =
                             BrowserUiListMenuUtils.getBasicListMenu(activity, data, delegate);
                     listMenu.setupCallbacksRecursively(
diff --git a/components/memory_pressure/system_memory_pressure_evaluator_fuchsia_unittest.cc b/components/memory_pressure/system_memory_pressure_evaluator_fuchsia_unittest.cc
index 504a2de7..cf81f39 100644
--- a/components/memory_pressure/system_memory_pressure_evaluator_fuchsia_unittest.cc
+++ b/components/memory_pressure/system_memory_pressure_evaluator_fuchsia_unittest.cc
@@ -9,6 +9,7 @@
 
 #include "base/fuchsia/scoped_service_binding.h"
 #include "base/fuchsia/test_component_context_for_process.h"
+#include "base/memory/mock_memory_pressure_listener.h"
 #include "base/run_loop.h"
 #include "base/test/task_environment.h"
 #include "components/memory_pressure/multi_source_memory_pressure_monitor.h"
@@ -34,8 +35,6 @@
       delete;
   TestSystemMemoryPressureEvaluator& operator=(
       const TestSystemMemoryPressureEvaluator&) = delete;
-
-  MOCK_METHOD1(OnMemoryPressure, void(base::MemoryPressureLevel level));
 };
 
 }  // namespace
@@ -125,48 +124,40 @@
 
   MultiSourceMemoryPressureMonitor monitor;
 
-  testing::StrictMock<TestSystemMemoryPressureEvaluator> evaluator(
-      monitor.CreateVoter());
+  TestSystemMemoryPressureEvaluator evaluator(monitor.CreateVoter());
 
   // Spin the loop to ensure that RegisterWatcher() is processed.
   base::RunLoop().RunUntilIdle();
   ASSERT_TRUE(have_watcher());
 
-  base::MemoryPressureListenerRegistration listener(
-      FROM_HERE, base::MemoryPressureListenerTag::kTest,
-      base::BindRepeating(&TestSystemMemoryPressureEvaluator::OnMemoryPressure,
-                          base::Unretained(&evaluator)));
+  testing::StrictMock<base::RegisteredMockMemoryPressureListener> listener;
 
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
   SendPressureLevel(fuchsia::memorypressure::Level::WARNING);
   EXPECT_EQ(evaluator.current_vote(), base::MEMORY_PRESSURE_LEVEL_MODERATE);
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // Verify that MODERATE pressure level is reported periodically.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
   task_environment_.FastForwardBy(evaluator.kRenotifyVotePeriod);
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
   SendPressureLevel(fuchsia::memorypressure::Level::CRITICAL);
   EXPECT_EQ(evaluator.current_vote(), base::MEMORY_PRESSURE_LEVEL_CRITICAL);
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // Verify that CRITICAL pressure level is reported periodically.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
   task_environment_.FastForwardBy(evaluator.kRenotifyVotePeriod);
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   SendPressureLevel(fuchsia::memorypressure::Level::NORMAL);
   EXPECT_EQ(evaluator.current_vote(), base::MEMORY_PRESSURE_LEVEL_NONE);
 
   // Verify that NONE pressure level is not reported periodically.
   task_environment_.FastForwardBy(evaluator.kRenotifyVotePeriod);
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 }
 
 }  // namespace memory_pressure
diff --git a/components/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc b/components/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc
index c05fcfe..c4aa83b 100644
--- a/components/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc
+++ b/components/memory_pressure/system_memory_pressure_evaluator_win_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/byte_count.h"
 #include "base/functional/bind.h"
+#include "base/memory/mock_memory_pressure_listener.h"
 #include "base/run_loop.h"
 #include "base/test/bind.h"
 #include "base/test/metrics/histogram_tester.h"
@@ -73,8 +74,6 @@
   TestSystemMemoryPressureEvaluator& operator=(
       const TestSystemMemoryPressureEvaluator&) = delete;
 
-  MOCK_METHOD1(OnMemoryPressure, void(base::MemoryPressureLevel level));
-
   // Sets up the memory status to reflect the provided absolute memory left.
   void SetMemoryFree(base::ByteCount phys_left) {
     // ullTotalPhys is set in the constructor and not modified.
@@ -187,13 +186,9 @@
 TEST_F(WinSystemMemoryPressureEvaluatorTest, CheckMemoryPressure) {
   MultiSourceMemoryPressureMonitor monitor;
 
-  testing::StrictMock<TestSystemMemoryPressureEvaluator> evaluator(
-      monitor.CreateVoter());
+  TestSystemMemoryPressureEvaluator evaluator(monitor.CreateVoter());
 
-  base::MemoryPressureListenerRegistration listener(
-      FROM_HERE, base::MemoryPressureListenerTag::kTest,
-      base::BindRepeating(&TestSystemMemoryPressureEvaluator::OnMemoryPressure,
-                          base::Unretained(&evaluator)));
+  testing::StrictMock<base::RegisteredMockMemoryPressureListener> listener;
 
   // Checking the memory pressure at 0% load should not produce any
   // events.
@@ -203,13 +198,12 @@
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_NONE, evaluator.current_vote());
 
   // Setting the memory level to 80% should produce a moderate pressure level.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
   evaluator.SetModerate();
   evaluator.CheckMemoryPressure();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_MODERATE, evaluator.current_vote());
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // Check that the event gets reposted after a while.
   const int kModeratePressureCooldownCycles =
@@ -217,52 +211,49 @@
 
   for (int i = 0; i < kModeratePressureCooldownCycles; ++i) {
     if (i + 1 == kModeratePressureCooldownCycles) {
-      EXPECT_CALL(evaluator,
+      EXPECT_CALL(listener,
                   OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
     }
     evaluator.CheckMemoryPressure();
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_MODERATE, evaluator.current_vote());
-    testing::Mock::VerifyAndClearExpectations(&evaluator);
+    testing::Mock::VerifyAndClearExpectations(&listener);
   }
 
   // Setting the memory usage to 99% should produce critical levels.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
   evaluator.SetCritical();
   evaluator.CheckMemoryPressure();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_CRITICAL, evaluator.current_vote());
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // Calling it again should immediately produce a second call.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_CRITICAL));
   evaluator.CheckMemoryPressure();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_CRITICAL, evaluator.current_vote());
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // When lowering the pressure again there should be a notification and the
   // pressure should go back to moderate.
-  EXPECT_CALL(evaluator,
-              OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
+  EXPECT_CALL(listener, OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
   evaluator.SetModerate();
   evaluator.CheckMemoryPressure();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_MODERATE, evaluator.current_vote());
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 
   // Check that the event gets reposted after a while.
   for (int i = 0; i < kModeratePressureCooldownCycles; ++i) {
     if (i + 1 == kModeratePressureCooldownCycles) {
-      EXPECT_CALL(evaluator,
+      EXPECT_CALL(listener,
                   OnMemoryPressure(base::MEMORY_PRESSURE_LEVEL_MODERATE));
     }
     evaluator.CheckMemoryPressure();
     base::RunLoop().RunUntilIdle();
     EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_MODERATE, evaluator.current_vote());
-    testing::Mock::VerifyAndClearExpectations(&evaluator);
+    testing::Mock::VerifyAndClearExpectations(&listener);
   }
 
   // Going down to no pressure should not produce an notification.
@@ -270,7 +261,7 @@
   evaluator.CheckMemoryPressure();
   base::RunLoop().RunUntilIdle();
   EXPECT_EQ(base::MEMORY_PRESSURE_LEVEL_NONE, evaluator.current_vote());
-  testing::Mock::VerifyAndClearExpectations(&evaluator);
+  testing::Mock::VerifyAndClearExpectations(&listener);
 }
 
 // RecordCommitHistograms emits the correct histograms when
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
index 1ea69ba..6625c15 100644
--- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
+++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerView.java
@@ -446,7 +446,7 @@
         menuItems.add(listItem);
 
         ListMenu.Delegate listMenuDelegate =
-                (PropertyModel menuItem) -> {
+                (PropertyModel menuItem, View view) -> {
                     assert menuItem == listItem.model;
                     // There is only one menu item in the menu.
                     if (mSecondaryActionCallback != null) {
diff --git a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
index 972c5e11..2a201ae 100644
--- a/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
+++ b/components/messages/android/internal/java/src/org/chromium/components/messages/MessageBannerViewTest.java
@@ -320,7 +320,7 @@
                             BrowserUiListMenuUtils.getBasicListMenu(
                                     sActivity,
                                     menuItems,
-                                    (PropertyModel menuItem) -> {
+                                    (PropertyModel menuItem, View view) -> {
                                         assertThat(menuItem)
                                                 .isSameInstanceAs(menuItems.get(0).model);
                                         called.set(true);
diff --git a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java
index 14a43735..7df20583 100644
--- a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java
+++ b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapper.java
@@ -8,6 +8,7 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
+import android.view.View;
 
 import androidx.annotation.DrawableRes;
 import androidx.annotation.VisibleForTesting;
@@ -257,7 +258,7 @@
     }
 
     @Override
-    public void onItemSelected(PropertyModel item) {
+    public void onItemSelected(PropertyModel item, View view) {
         assert item.getAllSetProperties().contains(ListMenuItemProperties.MENU_ITEM_ID);
         int itemId = item.get(ListMenuItemProperties.MENU_ITEM_ID);
         MessageWrapperJni.get().handleSecondaryMenuItemSelected(mNativeMessageWrapper, itemId);
diff --git a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapperTest.java b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapperTest.java
index 49fb7d7b..6631059b 100644
--- a/components/messages/android/java/src/org/chromium/components/messages/MessageWrapperTest.java
+++ b/components/messages/android/java/src/org/chromium/components/messages/MessageWrapperTest.java
@@ -159,7 +159,7 @@
                 messageSecondaryMenuItems.mMenuItems.size());
 
         // Select a secondary menu item.
-        message.onItemSelected(item1);
+        message.onItemSelected(item1, null);
         Mockito.verify(mNativeMock).handleSecondaryMenuItemSelected(nativePtr, 1);
 
         // Clear the secondary menu.
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h
index f800800..769eb19 100644
--- a/components/omnibox/browser/autocomplete_controller.h
+++ b/components/omnibox/browser/autocomplete_controller.h
@@ -14,6 +14,7 @@
 #include "base/gtest_prod_util.h"
 #include "base/memory/raw_ptr.h"
 #include "base/memory/ref_counted.h"
+#include "base/memory/safety_checks.h"
 #include "base/observer_list.h"
 #include "base/observer_list_types.h"
 #include "base/task/cancelable_task_tracker.h"
@@ -83,6 +84,9 @@
 // matches from a series of providers into one AutocompleteResult.
 class AutocompleteController : public AutocompleteProviderListener,
                                public base::trace_event::MemoryDumpProvider {
+  // TODO(crbug.com/449894891): Remove this macro once it gets fixed.
+  ADVANCED_MEMORY_SAFETY_CHECKS();
+
  public:
   // Describes an autocomplete pass.
   enum class UpdateType {
diff --git a/components/omnibox/browser/autocomplete_result.h b/components/omnibox/browser/autocomplete_result.h
index bdea9cc..3693c88 100644
--- a/components/omnibox/browser/autocomplete_result.h
+++ b/components/omnibox/browser/autocomplete_result.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "base/gtest_prod_util.h"
+#include "base/memory/safety_checks.h"
 #include "build/build_config.h"
 #include "components/omnibox/browser/actions/omnibox_action.h"
 #include "components/omnibox/browser/autocomplete_match.h"
@@ -38,6 +39,9 @@
 // what the default match should be if the user doesn't manually select another
 // match.
 class AutocompleteResult {
+  // TODO(crbug.com/449894891): Remove this macro once it gets fixed.
+  ADVANCED_MEMORY_SAFETY_CHECKS();
+
  public:
   typedef ACMatches::const_iterator const_iterator;
   typedef ACMatches::iterator iterator;
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal
index 257e69c..1f7cf07 160000
--- a/components/optimization_guide/internal
+++ b/components/optimization_guide/internal
@@ -1 +1 @@
-Subproject commit 257e69c2cd8457dd9d8d180c96295ad7ea650b1e
+Subproject commit 1f7cf078657b763c3ac434cfde2cfb54ee648e5e
diff --git a/components/reporting/util/disconnectable_client.h b/components/reporting/util/disconnectable_client.h
index 3ca8b6a..a01a1fa 100644
--- a/components/reporting/util/disconnectable_client.h
+++ b/components/reporting/util/disconnectable_client.h
@@ -8,7 +8,7 @@
 #include <memory>
 #include <queue>
 
-#include "base/containers/fixed_flat_map.h"
+#include "base/containers/flat_map.h"
 #include "base/feature_list.h"
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
diff --git a/components/site_isolation/site_isolation_policy.cc b/components/site_isolation/site_isolation_policy.cc
index 5983e65..fda82da 100644
--- a/components/site_isolation/site_isolation_policy.cc
+++ b/components/site_isolation/site_isolation_policy.cc
@@ -107,10 +107,8 @@
   // restrictions in that case.
   return false;
 #else
-  // TODO(crbug.com/40259221): This value currently matches the default
-  // threshold for site isolation, but once more trial data is available it
-  // should be adjusted.
-  int default_memory_threshold_mb = 1077;
+  // This value matches the threshold in the origin isolation study.
+  int default_memory_threshold_mb = 4096;
   if (base::FeatureList::IsEnabled(features::kOriginIsolationMemoryThreshold)) {
     int memory_threshold_mb = base::GetFieldTrialParamByFeatureAsInt(
         features::kOriginIsolationMemoryThreshold,
diff --git a/content/browser/loader/keep_alive_url_browsertest.cc b/content/browser/loader/keep_alive_url_browsertest.cc
index 9da353dc..7b7177d 100644
--- a/content/browser/loader/keep_alive_url_browsertest.cc
+++ b/content/browser/loader/keep_alive_url_browsertest.cc
@@ -1432,6 +1432,56 @@
       /*retried_count=*/0);
 }
 
+// Tests that Request.retryOptions() returns null when retryOptions is not set.
+IN_PROC_BROWSER_TEST_P(KeepAliveFetchRetryBrowserTest, RetryOptionsNotSet) {
+  ASSERT_TRUE(server()->Start());
+  const auto beacon_url = server()->GetURL(kPrimaryHost, kKeepAliveEndpoint);
+  ASSERT_TRUE(NavigateToURL(web_contents(),
+                            server()->GetURL(kPrimaryHost, "/title1.html")));
+
+  EXPECT_EQ(true, EvalJs(web_contents(), JsReplace(R"((async function() {
+        const request = new Request($1, {keepalive: true});
+        return request.getRetryOptions() === null;
+    })())",
+                                                   beacon_url)));
+}
+
+// Tests that Request.retryOptions() returns the correct options when set.
+IN_PROC_BROWSER_TEST_P(KeepAliveFetchRetryBrowserTest, RetryOptionsSet) {
+  ASSERT_TRUE(server()->Start());
+  const auto beacon_url = server()->GetURL(kPrimaryHost, kKeepAliveEndpoint);
+  ASSERT_TRUE(NavigateToURL(web_contents(),
+                            server()->GetURL(kPrimaryHost, "/title1.html")));
+
+  EXPECT_EQ(true, EvalJs(web_contents(), JsReplace(R"((async function() {
+        const init = {
+          keepalive: true,
+          retryOptions: {
+            maxAttempts: 5,
+            initialDelay: 100,
+            backoffFactor: 2.5,
+            maxAge: 5000,
+            retryAfterUnload: true,
+            retryNonIdempotent: true,
+            retryOnlyIfServerUnreached: true,
+          }
+        };
+        const request = new Request($1, init);
+        const options = request.getRetryOptions();
+        if (!options) return false;
+        const inputOptions = init.retryOptions;
+        return options.maxAttempts === inputOptions.maxAttempts &&
+               options.initialDelay === inputOptions.initialDelay &&
+               options.backoffFactor === inputOptions.backoffFactor &&
+               options.maxAge === inputOptions.maxAge &&
+               options.retryAfterUnload === inputOptions.retryAfterUnload &&
+               options.retryNonIdempotent === inputOptions.retryNonIdempotent &&
+               (options.retryOnlyIfServerUnreached ===
+                    inputOptions.retryOnlyIfServerUnreached);
+    })())",
+                                                   beacon_url)));
+}
+
 // TODO(crbug.com/417930271): test unload, redirects, timeout, attribution.
 
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 82aac82..c894d13f4 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -7698,6 +7698,15 @@
             return nullptr;
           }
 
+          if (base::Contains(request.GetURL().GetQuery(), "redirect")) {
+            auto response =
+                std::make_unique<net::test_server::BasicHttpResponse>();
+            response->set_code(net::HTTP_TEMPORARY_REDIRECT);
+            response->AddCustomHeader(
+                "Location", request.GetURL().GetPath() + "?query=bar");
+            return response;
+          }
+
           const bool is_slow =
               base::Contains(request.GetURL().GetQuery(), "server_slow");
 
@@ -7995,4 +8004,23 @@
                      "Math.ceil(performance.getEntriesByType('navigation')[0]."
                      "responseStart) < 2000"));
 }
+
+IN_PROC_BROWSER_TEST_P(ServiceWorkerSyntheticResponseBrowserTest, Redirect) {
+  // TODO(crbug.com/450598950): Test is flaky only on the dry-run mode. With the
+  // dry-run mode, ServiceWorker doesn't handle actual network requests, so
+  // perhaps this is the issue in the navigation code?
+  if (IsDryRunMode()) {
+    return;
+  }
+
+  SetUpMockContentBrowserClient();
+  // For the fist navigation, it sends a network request, but the server
+  // delivers a redirect response. It successfully navigates to the redirected
+  // page.
+  GURL initial_url = https_server()->GetURL(
+      kHostname, base::StrCat({kTargetPath, "foo&redirect"}));
+  GURL redirected_url =
+      https_server()->GetURL(kHostname, base::StrCat({kTargetPath, "bar"}));
+  EXPECT_TRUE(NavigateToURL(shell(), initial_url, redirected_url));
+}
 }  // namespace content
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc
index cd9566b..3a1d8882 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader.cc
+++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -1110,6 +1110,9 @@
       base::BindRepeating(&ServiceWorkerMainResourceLoader::
                               OnReceiveResponseFromSyntheticNetworkRequest,
                           weak_factory_.GetWeakPtr()),
+      base::BindOnce(&ServiceWorkerMainResourceLoader::
+                         OnReceiveRedirectFromSyntheticNetworkRequest,
+                     weak_factory_.GetWeakPtr()),
       base::BindOnce(
           &ServiceWorkerMainResourceLoader::OnCompleteSyntheticNetworkRequest,
           weak_factory_.GetWeakPtr()));
@@ -1159,6 +1162,15 @@
   CommitResponseBody(response_head, std::move(body), std::nullopt);
 }
 
+void ServiceWorkerMainResourceLoader::
+    OnReceiveRedirectFromSyntheticNetworkRequest(
+        const net::RedirectInfo& redirect_info,
+        network::mojom::URLResponseHeadPtr response_head) {
+  CHECK(url_loader_client_.is_bound());
+  url_loader_client_->OnReceiveRedirect(redirect_info,
+                                        std::move(response_head));
+}
+
 void ServiceWorkerMainResourceLoader::OnCompleteSyntheticNetworkRequest(
     const network::URLLoaderCompletionStatus& status) {
   CHECK(synthetic_response_manager_);
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.h b/content/browser/service_worker/service_worker_main_resource_loader.h
index a9367b8..b8e7b56 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader.h
+++ b/content/browser/service_worker/service_worker_main_resource_loader.h
@@ -272,6 +272,10 @@
       network::mojom::URLResponseHeadPtr response_head,
       mojo::ScopedDataPipeConsumerHandle body);
 
+  void OnReceiveRedirectFromSyntheticNetworkRequest(
+      const net::RedirectInfo& redirect_info,
+      network::mojom::URLResponseHeadPtr response_head);
+
   void OnCompleteSyntheticNetworkRequest(
       const network::URLLoaderCompletionStatus& status);
 
diff --git a/content/browser/service_worker/service_worker_synthetic_response_manager.cc b/content/browser/service_worker/service_worker_synthetic_response_manager.cc
index c4302620..906912d 100644
--- a/content/browser/service_worker/service_worker_synthetic_response_manager.cc
+++ b/content/browser/service_worker/service_worker_synthetic_response_manager.cc
@@ -199,8 +199,10 @@
  public:
   SyntheticResponseURLLoaderClient(
       OnReceiveResponseCallback receive_response_callback,
+      OnReceiveRedirectCallback receive_redirect_callback,
       OnCompleteCallback complete_callback)
       : receive_response_callback_(std::move(receive_response_callback)),
+        receive_redirect_callback_(std::move(receive_redirect_callback)),
         complete_callback_(std::move(complete_callback)) {}
   SyntheticResponseURLLoaderClient(const SyntheticResponseURLLoaderClient&) =
       delete;
@@ -223,7 +225,10 @@
   }
   void OnReceiveRedirect(
       const net::RedirectInfo& redirect_info,
-      network::mojom::URLResponseHeadPtr response_head) override {}
+      network::mojom::URLResponseHeadPtr response_head) override {
+    std::move(receive_redirect_callback_)
+        .Run(redirect_info, std::move(response_head));
+  }
   void OnUploadProgress(int64_t current_position,
                         int64_t total_size,
                         OnUploadProgressCallback ack_callback) override {}
@@ -233,6 +238,7 @@
   }
 
   OnReceiveResponseCallback receive_response_callback_;
+  OnReceiveRedirectCallback receive_redirect_callback_;
   OnCompleteCallback complete_callback_;
 
   mojo::Receiver<network::mojom::URLLoaderClient> receiver_{this};
@@ -260,6 +266,7 @@
     uint32_t options,
     const network::ResourceRequest& request,
     OnReceiveResponseCallback receive_response_callback,
+    OnReceiveRedirectCallback receive_redirect_callback,
     OnCompleteCallback complete_callback) {
   TRACE_EVENT("ServiceWorker",
               "ServiceWorkerSyntheticResponseManager::StartRequest");
@@ -270,6 +277,7 @@
       base::BindRepeating(
           &ServiceWorkerSyntheticResponseManager::OnReceiveResponse,
           weak_factory_.GetWeakPtr()),
+      std::move(receive_redirect_callback),
       base::BindOnce(&ServiceWorkerSyntheticResponseManager::OnComplete,
                      weak_factory_.GetWeakPtr()));
   mojo::PendingRemote<network::mojom::URLLoaderClient> client_to_pass;
diff --git a/content/browser/service_worker/service_worker_synthetic_response_manager.h b/content/browser/service_worker/service_worker_synthetic_response_manager.h
index 0a8c48a9..84fdcc9 100644
--- a/content/browser/service_worker/service_worker_synthetic_response_manager.h
+++ b/content/browser/service_worker/service_worker_synthetic_response_manager.h
@@ -37,6 +37,9 @@
   using OnReceiveResponseCallback = base::RepeatingCallback<void(
       network::mojom::URLResponseHeadPtr response_head,
       mojo::ScopedDataPipeConsumerHandle body)>;
+  using OnReceiveRedirectCallback = base::OnceCallback<void(
+      const net::RedirectInfo& redirect_info,
+      network::mojom::URLResponseHeadPtr response_head)>;
   using OnCompleteCallback = base::OnceCallback<void(
       const network::URLLoaderCompletionStatus& status)>;
   using FetchCallback =
@@ -60,6 +63,7 @@
                     uint32_t options,
                     const network::ResourceRequest& request,
                     OnReceiveResponseCallback receive_response_callback,
+                    OnReceiveRedirectCallback receive_redirect_callback,
                     OnCompleteCallback complete_callback);
   void StartSyntheticResponse(FetchCallback callback);
   SyntheticResponseStatus Status() const { return status_; }
diff --git a/crypto/unexportable_key.cc b/crypto/unexportable_key.cc
index 082fe12..ff2705b 100644
--- a/crypto/unexportable_key.cc
+++ b/crypto/unexportable_key.cc
@@ -6,6 +6,11 @@
 
 #include "base/check.h"
 #include "base/functional/bind.h"
+#if BUILDFLAG(IS_WIN)
+#include "crypto/unexportable_key_win.h"
+#elif BUILDFLAG(IS_MAC)
+#include "crypto/apple/unexportable_key_mac.h"
+#endif
 
 namespace crypto {
 
@@ -22,23 +27,6 @@
   return false;
 }
 
-#if BUILDFLAG(IS_WIN)
-std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProviderWin();
-std::unique_ptr<UnexportableKeyProvider>
-GetMicrosoftSoftwareUnexportableKeyProviderWin();
-std::unique_ptr<VirtualUnexportableKeyProvider>
-GetVirtualUnexportableKeyProviderWin();
-#elif BUILDFLAG(IS_MAC)
-namespace apple {
-std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProviderMac(
-    UnexportableKeyProvider::Config config);
-}  // namespace apple
-#endif
-
-// Implemented in unexportable_key_software_unsecure.cc.
-std::unique_ptr<UnexportableKeyProvider>
-GetUnexportableKeyProviderSoftwareUnsecure();
-
 std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProvider(
     UnexportableKeyProvider::Config config) {
   if (g_mock_provider) {
diff --git a/crypto/unexportable_key_win.h b/crypto/unexportable_key_win.h
index eb9c3e6..dcd90bb 100644
--- a/crypto/unexportable_key_win.h
+++ b/crypto/unexportable_key_win.h
@@ -5,8 +5,8 @@
 #ifndef CRYPTO_UNEXPORTABLE_KEY_WIN_H_
 #define CRYPTO_UNEXPORTABLE_KEY_WIN_H_
 
-#include "base/containers/span.h"
-#include "base/win/wincrypt_shim.h"
+#include <memory>
+
 #include "crypto/crypto_export.h"
 #include "crypto/scoped_cng_types.h"
 #include "crypto/unexportable_key.h"
@@ -18,6 +18,19 @@
 CRYPTO_EXPORT ScopedNCryptKey
 DuplicatePlatformKeyHandle(const UnexportableSigningKey& key);
 
+// Returns an `UnexportableKeyProvider` that is backed by the Windows TPM.
+std::unique_ptr<UnexportableKeyProvider> GetUnexportableKeyProviderWin();
+
+// Returns an `UnexportableKeyProvider` that is backed by the Microsoft Software
+// Key Storage Provider.
+std::unique_ptr<UnexportableKeyProvider>
+GetMicrosoftSoftwareUnexportableKeyProviderWin();
+
+// Returns a `VirtualUnexportableKeyProvider` that is backed by the Windows
+// Credential Guard.
+std::unique_ptr<VirtualUnexportableKeyProvider>
+GetVirtualUnexportableKeyProviderWin();
+
 }  // namespace crypto
 
 #endif  // CRYPTO_UNEXPORTABLE_KEY_WIN_H_
diff --git a/device/bluetooth/bluetooth_adapter_win.cc b/device/bluetooth/bluetooth_adapter_win.cc
index 1bbe729..c7645f7 100644
--- a/device/bluetooth/bluetooth_adapter_win.cc
+++ b/device/bluetooth/bluetooth_adapter_win.cc
@@ -175,6 +175,11 @@
 void BluetoothAdapterWin::AdapterStateChanged(
     const BluetoothTaskManagerWin::AdapterState& state) {
   DCHECK(thread_checker_.CalledOnValidThread());
+  // Lifetime: If obtained via BluetoothAdapterFactory::GetClassicAdapter() and
+  // the caller did NOT keep the scoped_refptr<BluetoothAdapter>, running
+  // init_callback_.Run() will release the last reference and destroy |this|.
+  // Use keep_alive to avoid use-after-free issues.
+  scoped_refptr<BluetoothAdapterWin> keep_alive(this);
   name_ = state.name;
   bool was_present = IsPresent();
   bool is_present = !state.address.empty();
diff --git a/gpu/command_buffer/service/BUILD.gn b/gpu/command_buffer/service/BUILD.gn
index 1ce0748b..a1f24b43 100644
--- a/gpu/command_buffer/service/BUILD.gn
+++ b/gpu/command_buffer/service/BUILD.gn
@@ -655,8 +655,6 @@
       "shared_image/dxgi_swap_chain_image_backing.h",
       "shared_image/dxgi_swap_chain_image_representation.cc",
       "shared_image/dxgi_swap_chain_image_representation.h",
-      "shared_image/gpu_memory_buffer_factory_dxgi.cc",
-      "shared_image/gpu_memory_buffer_factory_dxgi.h",
     ]
     libs = [
       "d3d11.lib",
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 08f3da2..40d29eae3 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
@@ -13,6 +13,7 @@
 #include "base/memory/shared_memory_mapping.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/threading/thread_checker.h"
 #include "base/trace_event/trace_event.h"
 #include "base/win/scoped_handle.h"
 #include "components/viz/common/resources/shared_image_format_utils.h"
@@ -20,7 +21,6 @@
 #include "gpu/command_buffer/service/dxgi_shared_handle_manager.h"
 #include "gpu/command_buffer/service/shared_image/d3d_image_backing.h"
 #include "gpu/command_buffer/service/shared_image/d3d_image_utils.h"
-#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"
@@ -40,9 +40,93 @@
 
 namespace {
 
-GpuMemoryBufferFactoryDXGI* GetGpuMemoryBufferFactoryDXGI(
-    scoped_refptr<base::SingleThreadTaskRunner> io_runner) {
-  static auto* factory = new GpuMemoryBufferFactoryDXGI(io_runner);
+class GpuMemoryBufferHandleSharedState {
+ public:
+  GpuMemoryBufferHandleSharedState() { DETACH_FROM_THREAD(thread_checker_); }
+  ~GpuMemoryBufferHandleSharedState() = default;
+
+  GpuMemoryBufferHandleSharedState(const GpuMemoryBufferHandleSharedState&) =
+      delete;
+  GpuMemoryBufferHandleSharedState& operator=(
+      const GpuMemoryBufferHandleSharedState&) = delete;
+
+  // TODO(crbug.com/40774668): Avoid the need for a separate D3D device here by
+  // sharing keyed mutex state between DXGI GMBs and D3D shared image backings.
+  Microsoft::WRL::ComPtr<ID3D11Device> GetOrCreateD3D11Device() {
+    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+    if (!d3d11_device_ || FAILED(d3d11_device_->GetDeviceRemovedReason())) {
+      // Reset device if it was removed.
+      d3d11_device_ = nullptr;
+      // Use same adapter as ANGLE device.
+      auto angle_d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE();
+      if (!angle_d3d11_device) {
+        DLOG(ERROR) << "Failed to get ANGLE D3D11 device";
+        return nullptr;
+      }
+
+      Microsoft::WRL::ComPtr<IDXGIDevice> angle_dxgi_device;
+      HRESULT hr = angle_d3d11_device.As(&angle_dxgi_device);
+      CHECK(SUCCEEDED(hr));
+
+      Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter = nullptr;
+      hr = FAILED(angle_dxgi_device->GetAdapter(&dxgi_adapter));
+      if (FAILED(hr)) {
+        DLOG(ERROR) << "GetAdapter failed with error 0x" << std::hex << hr;
+        return nullptr;
+      }
+
+      // If adapter is not null, driver type must be D3D_DRIVER_TYPE_UNKNOWN
+      // otherwise D3D11CreateDevice will return E_INVALIDARG.
+      // See
+      // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice#return-value
+      const D3D_DRIVER_TYPE driver_type =
+          dxgi_adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE;
+
+      // It's ok to use D3D11_CREATE_DEVICE_SINGLETHREADED because this device
+      // is only ever used on the IO thread (verified by |thread_checker_|).
+      const UINT flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
+
+      // Using D3D_FEATURE_LEVEL_11_1 is ok since we only support D3D11 when the
+      // platform update containing DXGI 1.2 is present on Win7.
+      const D3D_FEATURE_LEVEL feature_levels[] = {
+          D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0,
+          D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0,
+          D3D_FEATURE_LEVEL_9_3,  D3D_FEATURE_LEVEL_9_2,
+          D3D_FEATURE_LEVEL_9_1};
+
+      hr = D3D11CreateDevice(dxgi_adapter.Get(), driver_type,
+                             /*Software=*/nullptr, flags, feature_levels,
+                             std::size(feature_levels), D3D11_SDK_VERSION,
+                             &d3d11_device_, /*pFeatureLevel=*/nullptr,
+                             /*ppImmediateContext=*/nullptr);
+      if (FAILED(hr)) {
+        DLOG(ERROR) << "D3D11CreateDevice failed with error 0x" << std::hex
+                    << hr;
+        return nullptr;
+      }
+
+      const char* kDebugName = "GPUIPC_GpuMemoryBufferHandleSharedState";
+      d3d11_device_->SetPrivateData(WKPDID_D3DDebugObjectName,
+                                    strlen(kDebugName), kDebugName);
+    }
+    DCHECK(d3d11_device_);
+    return d3d11_device_;
+  }
+
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture() {
+    return staging_texture_;
+  }
+
+ private:
+  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_
+      GUARDED_BY_CONTEXT(thread_checker_);
+  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_;
+  THREAD_CHECKER(thread_checker_);
+};
+
+GpuMemoryBufferHandleSharedState* GetGpuMemoryBufferHandleSharedState() {
+  static auto* factory = new GpuMemoryBufferHandleSharedState();
   return factory;
 }
 
@@ -274,7 +358,7 @@
 
   gfx::GpuMemoryBufferHandle handle;
   auto d3d11_device =
-      GetGpuMemoryBufferFactoryDXGI(io_runner)->GetOrCreateD3D11Device();
+      GetGpuMemoryBufferHandleSharedState()->GetOrCreateD3D11Device();
   if (!d3d11_device) {
     return handle;
   }
@@ -335,13 +419,12 @@
 
 // static
 bool D3DImageBackingFactory::CopyNativeBufferToSharedMemoryAsync(
-    scoped_refptr<base::SingleThreadTaskRunner> io_runner,
     gfx::GpuMemoryBufferHandle buffer_handle,
     base::UnsafeSharedMemoryRegion shared_memory) {
   DCHECK_EQ(buffer_handle.type, gfx::GpuMemoryBufferType::DXGI_SHARED_HANDLE);
-  auto* gmb_factory = GetGpuMemoryBufferFactoryDXGI(io_runner);
+  auto* shared_state = GetGpuMemoryBufferHandleSharedState();
 
-  auto d3d11_device = gmb_factory->GetOrCreateD3D11Device();
+  auto d3d11_device = shared_state->GetOrCreateD3D11Device();
   if (!d3d11_device) {
     return false;
   }
@@ -354,7 +437,7 @@
   return CopyDXGIBufferToShMem(buffer_handle.dxgi_handle().buffer_handle(),
                                mapping.GetMemoryAsSpan<uint8_t>(),
                                d3d11_device.Get(),
-                               &gmb_factory->staging_texture());
+                               &shared_state->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 686e1b74..9d40c356 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
@@ -50,6 +50,11 @@
 
   ~D3DImageBackingFactory() override;
 
+  // `io_runner` is needed in order to create GpuMemoryBufferHandles on the
+  // correct thread. GpuServiceImpl calls into this class on the IO thread when
+  // processing IPC requests, so we need to ensure that other callers are able
+  // to thread-hop to that runner when creating GMBHandles (so far, the other
+  // caller for whom it matters is `FrameSinkVideoCapturerImpl` on Windows).
   static gfx::GpuMemoryBufferHandle CreateGpuMemoryBufferHandle(
       scoped_refptr<base::SingleThreadTaskRunner> io_runner,
       const gfx::Size& size,
@@ -57,7 +62,6 @@
       gfx::BufferUsage usage);
 
   static bool CopyNativeBufferToSharedMemoryAsync(
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner,
       gfx::GpuMemoryBufferHandle buffer_handle,
       base::UnsafeSharedMemoryRegion shared_memory);
 
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
deleted file mode 100644
index 1820025..0000000
--- a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.cc
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h"
-
-#include "base/task/single_thread_task_runner.h"
-#include "ui/gl/gl_angle_util_win.h"
-
-namespace gpu {
-
-GpuMemoryBufferFactoryDXGI::GpuMemoryBufferFactoryDXGI(
-    scoped_refptr<base::SingleThreadTaskRunner> io_runner)
-    : io_runner_(std::move(io_runner)) {
-  DETACH_FROM_THREAD(thread_checker_);
-}
-GpuMemoryBufferFactoryDXGI::~GpuMemoryBufferFactoryDXGI() {
-  // Ensure that IO-thread specific state is destroyed on the IO thread. Note
-  // that it is valid to be *accessing* this state on the Viz thread here as the
-  // owner of this instance must have guaranteed all calls to this class on the
-  // IO thread are finished before destroying this object on the Viz thread (or
-  // else those calls would inherently race with destroying this object). Note
-  // also that that we need to be holding the ThreadChecker to access
-  // `d3d11_device_`.
-  DETACH_FROM_THREAD(thread_checker_);
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  if (io_runner_) {
-    io_runner_->PostTask(
-        FROM_HERE,
-        base::BindOnce(
-            [](Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device,
-               Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture) {},
-            std::move(d3d11_device_), std::move(staging_texture_)));
-  }
-}
-
-// TODO(crbug.com/40774668): Avoid the need for a separate D3D device here by
-// sharing keyed mutex state between DXGI GMBs and D3D shared image backings.
-Microsoft::WRL::ComPtr<ID3D11Device>
-GpuMemoryBufferFactoryDXGI::GetOrCreateD3D11Device() {
-  DCHECK(!io_runner_ || io_runner_->BelongsToCurrentThread());
-  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-
-  if (!d3d11_device_ || FAILED(d3d11_device_->GetDeviceRemovedReason())) {
-    // Reset device if it was removed.
-    d3d11_device_ = nullptr;
-    // Use same adapter as ANGLE device.
-    auto angle_d3d11_device = gl::QueryD3D11DeviceObjectFromANGLE();
-    if (!angle_d3d11_device) {
-      DLOG(ERROR) << "Failed to get ANGLE D3D11 device";
-      return nullptr;
-    }
-
-    Microsoft::WRL::ComPtr<IDXGIDevice> angle_dxgi_device;
-    HRESULT hr = angle_d3d11_device.As(&angle_dxgi_device);
-    CHECK(SUCCEEDED(hr));
-
-    Microsoft::WRL::ComPtr<IDXGIAdapter> dxgi_adapter = nullptr;
-    hr = FAILED(angle_dxgi_device->GetAdapter(&dxgi_adapter));
-    if (FAILED(hr)) {
-      DLOG(ERROR) << "GetAdapter failed with error 0x" << std::hex << hr;
-      return nullptr;
-    }
-
-    // If adapter is not null, driver type must be D3D_DRIVER_TYPE_UNKNOWN
-    // otherwise D3D11CreateDevice will return E_INVALIDARG.
-    // See
-    // https://docs.microsoft.com/en-us/windows/win32/api/d3d11/nf-d3d11-d3d11createdevice#return-value
-    const D3D_DRIVER_TYPE driver_type =
-        dxgi_adapter ? D3D_DRIVER_TYPE_UNKNOWN : D3D_DRIVER_TYPE_HARDWARE;
-
-    // It's ok to use D3D11_CREATE_DEVICE_SINGLETHREADED because this device is
-    // only ever used on the IO thread (verified by |thread_checker_|).
-    const UINT flags = D3D11_CREATE_DEVICE_SINGLETHREADED;
-
-    // Using D3D_FEATURE_LEVEL_11_1 is ok since we only support D3D11 when the
-    // platform update containing DXGI 1.2 is present on Win7.
-    const D3D_FEATURE_LEVEL feature_levels[] = {
-        D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1,
-        D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_9_3,  D3D_FEATURE_LEVEL_9_2,
-        D3D_FEATURE_LEVEL_9_1};
-
-    hr = D3D11CreateDevice(dxgi_adapter.Get(), driver_type,
-                           /*Software=*/nullptr, flags, feature_levels,
-                           std::size(feature_levels), D3D11_SDK_VERSION,
-                           &d3d11_device_, /*pFeatureLevel=*/nullptr,
-                           /*ppImmediateContext=*/nullptr);
-    if (FAILED(hr)) {
-      DLOG(ERROR) << "D3D11CreateDevice failed with error 0x" << std::hex << hr;
-      return nullptr;
-    }
-
-    const char* kDebugName = "GPUIPC_GpuMemoryBufferFactoryDXGI";
-    d3d11_device_->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(kDebugName),
-                                  kDebugName);
-  }
-  DCHECK(d3d11_device_);
-  return d3d11_device_;
-}
-
-}  // 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
deleted file mode 100644
index 2db15b8..0000000
--- a/gpu/command_buffer/service/shared_image/gpu_memory_buffer_factory_dxgi.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2017 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GPU_MEMORY_BUFFER_FACTORY_DXGI_H_
-#define GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GPU_MEMORY_BUFFER_FACTORY_DXGI_H_
-
-#include <d3d11_1.h>
-#include <dxgi.h>
-#include <wrl/client.h>
-
-#include "base/memory/scoped_refptr.h"
-#include "base/task/single_thread_task_runner.h"
-#include "base/threading/thread_checker.h"
-#include "components/viz/common/resources/shared_image_format.h"
-#include "gpu/gpu_gles2_export.h"
-#include "ui/gfx/buffer_types.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gpu_memory_buffer_handle.h"
-
-namespace gpu {
-
-class GPU_GLES2_EXPORT GpuMemoryBufferFactoryDXGI {
- public:
-  // Creates new instance of GpuMemoryBufferFactoryDXGI. `io_runner` is needed
-  // in order to create GpuMemoryBuffers on the correct thread. GpuServiceImpl
-  // calls into this class from IO runner (when processing IPC requests), so
-  // we need to ensure that other callers are able to thread-hop to that runner
-  // when creating GMBs (so far, the other caller for whom it matters is
-  // `FrameSinkVideoCapturerImpl` when running in GMB mode on Windows).
-  explicit GpuMemoryBufferFactoryDXGI(
-      scoped_refptr<base::SingleThreadTaskRunner> io_runner = nullptr);
-  ~GpuMemoryBufferFactoryDXGI();
-
-  GpuMemoryBufferFactoryDXGI(const GpuMemoryBufferFactoryDXGI&) = delete;
-  GpuMemoryBufferFactoryDXGI& operator=(const GpuMemoryBufferFactoryDXGI&) =
-      delete;
-
-  Microsoft::WRL::ComPtr<ID3D11Device> GetOrCreateD3D11Device();
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture() {
-    return staging_texture_;
-  }
-
- private:
-  Microsoft::WRL::ComPtr<ID3D11Device> d3d11_device_
-      GUARDED_BY_CONTEXT(thread_checker_);
-
-  Microsoft::WRL::ComPtr<ID3D11Texture2D> staging_texture_;
-
-  // May be null for testing:
-  scoped_refptr<base::SingleThreadTaskRunner> io_runner_;
-
-  THREAD_CHECKER(thread_checker_);
-};
-
-}  // namespace gpu
-
-#endif  // GPU_COMMAND_BUFFER_SERVICE_SHARED_IMAGE_GPU_MEMORY_BUFFER_FACTORY_DXGI_H_
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
index 91d8acd..ec1d40c 100644
--- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc
+++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -728,8 +728,7 @@
     base::UnsafeSharedMemoryRegion shared_memory) {
 #if BUILDFLAG(IS_WIN)
   return D3DImageBackingFactory::CopyNativeBufferToSharedMemoryAsync(
-      shared_image_manager_->io_runner(), std::move(buffer_handle),
-      std::move(shared_memory));
+      std::move(buffer_handle), std::move(shared_memory));
 #else
   return false;
 #endif
diff --git a/gpu/config/skia_limits.cc b/gpu/config/skia_limits.cc
index b08bd762..410f251 100644
--- a/gpu/config/skia_limits.cc
+++ b/gpu/config/skia_limits.cc
@@ -16,40 +16,6 @@
 
 BASE_FEATURE(kGrCacheLimitsFeature, base::FEATURE_ENABLED_BY_DEFAULT);
 
-MIRACLE_PARAMETER_FOR_INT(GetMaxGaneshResourceCacheBytes,
-                          kGrCacheLimitsFeature,
-                          "MaxGaneshResourceCacheBytes",
-                          96 * 1024 * 1024)
-
-MIRACLE_PARAMETER_FOR_INT(GetMaxDefaultGlyphCacheTextureBytes,
-                          kGrCacheLimitsFeature,
-                          "MaxDefaultGlyphCacheTextureBytes",
-                          2048 * 1024 * 4)
-
-// The limit of the bytes allocated toward GPU resources in the GrContext's
-// GPU cache.
-MIRACLE_PARAMETER_FOR_INT(GetMaxLowEndGaneshResourceCacheBytes,
-                          kGrCacheLimitsFeature,
-                          "MaxLowEndGaneshResourceCacheBytes",
-                          48 * 1024 * 1024)
-
-MIRACLE_PARAMETER_FOR_INT(GetMaxHighEndGaneshResourceCacheBytes,
-                          kGrCacheLimitsFeature,
-                          "MaxHighEndGaneshResourceCacheBytes",
-                          256 * 1024 * 1024)
-
-// Limits for glyph cache textures.
-MIRACLE_PARAMETER_FOR_INT(GetMaxLowEndGlyphCacheTextureBytes,
-                          kGrCacheLimitsFeature,
-                          "MaxLowEndGlyphCacheTextureBytes",
-                          1024 * 512 * 4)
-
-// High-end / low-end memory cutoffs.
-MIRACLE_PARAMETER_FOR_INT(GetHighEndMemoryThresholdMB,
-                          kGrCacheLimitsFeature,
-                          "HighEndMemoryThresholdMB",
-                          4096)
-
 // Limits for the Graphite client image provider which is responsible for
 // uploading non-GPU backed images (e.g. raster, lazy/generated) to Graphite.
 // The limits are smallish since only a small number of images take this path
@@ -81,16 +47,26 @@
 void DetermineGrCacheLimitsFromAvailableMemory(
     size_t* max_resource_cache_bytes,
     size_t* max_glyph_cache_texture_bytes) {
+  constexpr size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
+  constexpr size_t kMaxDefaultGlyphCacheTextureBytes = 2048 * 1024 * 4;
   // Default limits.
-  *max_resource_cache_bytes = GetMaxGaneshResourceCacheBytes();
-  *max_glyph_cache_texture_bytes = GetMaxDefaultGlyphCacheTextureBytes();
+  *max_resource_cache_bytes = kMaxGaneshResourceCacheBytes;
+  *max_glyph_cache_texture_bytes = kMaxDefaultGlyphCacheTextureBytes;
 
+  // The limit of the bytes allocated toward GPU resources in the GrContext's
+  // GPU cache.
+  constexpr size_t kMaxLowEndGaneshResourceCacheBytes = 48 * 1024 * 1024;
+  constexpr size_t kMaxHighEndGaneshResourceCacheBytes = 256 * 1024 * 1024;
+  // Limits for glyph cache textures.
+  constexpr size_t kMaxLowEndGlyphCacheTextureBytes = 1024 * 512 * 4;
+  // High-end / low-end memory cutoffs.
+  constexpr int64_t kHighEndMemoryThresholdInMB = 4096;
   if (base::SysInfo::IsLowEndDevice()) {
-    *max_resource_cache_bytes = GetMaxLowEndGaneshResourceCacheBytes();
-    *max_glyph_cache_texture_bytes = GetMaxLowEndGlyphCacheTextureBytes();
+    *max_resource_cache_bytes = kMaxLowEndGaneshResourceCacheBytes;
+    *max_glyph_cache_texture_bytes = kMaxLowEndGlyphCacheTextureBytes;
   } else if (base::SysInfo::AmountOfPhysicalMemory().InMiB() >=
-             GetHighEndMemoryThresholdMB()) {
-    *max_resource_cache_bytes = GetMaxHighEndGaneshResourceCacheBytes();
+             kHighEndMemoryThresholdInMB) {
+    *max_resource_cache_bytes = kMaxHighEndGaneshResourceCacheBytes;
   }
 }
 
diff --git "a/infra/config/generated/builders/ci/ToTLinux \050dbg\051/properties.json" "b/infra/config/generated/builders/ci/ToTLinux \050dbg\051/properties.json"
index 18a9613..c77a6563 100644
--- "a/infra/config/generated/builders/ci/ToTLinux \050dbg\051/properties.json"
+++ "b/infra/config/generated/builders/ci/ToTLinux \050dbg\051/properties.json"
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git "a/infra/config/generated/builders/ci/ToTLinux \050dbg\051/shadow-properties.json" "b/infra/config/generated/builders/ci/ToTLinux \050dbg\051/shadow-properties.json"
index 54c02663..155ae71 100644
--- "a/infra/config/generated/builders/ci/ToTLinux \050dbg\051/shadow-properties.json"
+++ "b/infra/config/generated/builders/ci/ToTLinux \050dbg\051/shadow-properties.json"
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinux/properties.json b/infra/config/generated/builders/ci/ToTLinux/properties.json
index 81c16044a..75e34fa 100644
--- a/infra/config/generated/builders/ci/ToTLinux/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinux/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinux/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinux/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinux/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinux/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxASan/properties.json b/infra/config/generated/builders/ci/ToTLinuxASan/properties.json
index 6356e02..adaae28 100644
--- a/infra/config/generated/builders/ci/ToTLinuxASan/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxASan/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxASan/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxASan/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxASan/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxASan/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/properties.json b/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/properties.json
index dc8d2a1..810ef85 100644
--- a/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxASanLibfuzzer/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxMSan/properties.json b/infra/config/generated/builders/ci/ToTLinuxMSan/properties.json
index 3e4aadeb..a02f266 100644
--- a/infra/config/generated/builders/ci/ToTLinuxMSan/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxMSan/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxMSan/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxMSan/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxMSan/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxMSan/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxPGO/properties.json b/infra/config/generated/builders/ci/ToTLinuxPGO/properties.json
index ecad215..65897be 100644
--- a/infra/config/generated/builders/ci/ToTLinuxPGO/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxPGO/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxPGO/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxPGO/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxPGO/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxPGO/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxTSan/properties.json b/infra/config/generated/builders/ci/ToTLinuxTSan/properties.json
index 2446fe9..cddebdbf 100644
--- a/infra/config/generated/builders/ci/ToTLinuxTSan/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxTSan/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxTSan/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxTSan/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxTSan/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxTSan/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/properties.json b/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/properties.json
index 2b46f58..3c65d36 100644
--- a/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/properties.json
@@ -57,7 +57,8 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-trusted"
+    "project": "rbe-chromium-trusted",
+    "remote_jobs": 400
   },
   "$recipe_engine/resultdb/test_presentation": {
     "column_keys": [],
diff --git a/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/shadow-properties.json b/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/shadow-properties.json
index 54c02663..155ae71 100644
--- a/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/shadow-properties.json
+++ b/infra/config/generated/builders/ci/ToTLinuxUBSanVptr/shadow-properties.json
@@ -8,6 +8,7 @@
     "enable_cloud_trace": true,
     "experiments": [],
     "metrics_project": "chromium-reclient-metrics",
-    "project": "rbe-chromium-untrusted"
+    "project": "rbe-chromium-untrusted",
+    "remote_jobs": 400
   }
 }
\ No newline at end of file
diff --git a/infra/config/subprojects/chromium/ci/chromium.clang.star b/infra/config/subprojects/chromium/ci/chromium.clang.star
index 848dbcd..b6f36f6 100644
--- a/infra/config/subprojects/chromium/ci/chromium.clang.star
+++ b/infra/config/subprojects/chromium/ci/chromium.clang.star
@@ -929,6 +929,7 @@
         ],
     ),
     short_name = "rel",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -968,6 +969,7 @@
         ],
     ),
     short_name = "dbg",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1014,6 +1016,7 @@
         ],
     ),
     short_name = "asn",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1061,6 +1064,7 @@
     # Requires a large disk, so has a machine specifically devoted to it
     builderless = False,
     short_name = "fuz",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1118,6 +1122,7 @@
         ],
     ),
     short_name = "msn",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1159,6 +1164,7 @@
         ],
     ),
     short_name = "pgo",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1199,6 +1205,7 @@
         ],
     ),
     short_name = "tsn",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 clang_tot_linux_builder(
@@ -1239,6 +1246,7 @@
         ],
     ),
     short_name = "usn",
+    siso_remote_jobs = min(siso.remote_jobs.HIGH_JOBS_FOR_CI, 400),
 )
 
 ci.builder(
diff --git a/internal b/internal
index 96c1786..9543534 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 96c17864244a5d24cebd6605e8895b4f414ed1f8
+Subproject commit 954353405806383ec740f812cfd40c08c435c4a5
diff --git a/ios/build/chrome_build.gni b/ios/build/chrome_build.gni
index 2407f9c2..122a3316 100644
--- a/ios/build/chrome_build.gni
+++ b/ios/build/chrome_build.gni
@@ -60,9 +60,6 @@
   ios_passkey_keychain_provider_chrome_target = "//ios/chrome/common/credential_provider:passkey_keychain_provider_implementation"
   ios_passkey_keychain_provider_extension_target = "//ios/chrome/common/credential_provider:passkey_keychain_provider_implementation"
 
-  # TODO(crbug.com/448228341): Remove after transition to two targets.
-  ios_passkey_keychain_provider_target = "//ios/chrome/common/credential_provider:passkey_keychain_provider_implementation"
-
   # Label of the target providing implementation for FontProvider.
   # Overridden when using the Google-internal repository to build Chrome on iOS.
   ios_font_provider_target =
diff --git a/media/base/audio_bus.h b/media/base/audio_bus.h
index 7369fe3..b8478687 100644
--- a/media/base/audio_bus.h
+++ b/media/base/audio_bus.h
@@ -176,17 +176,7 @@
   // Returns a raw pointer to the requested channel.  Pointer is guaranteed to
   // have a 16-byte alignment.  Warning: Do not rely on having sane (i.e. not
   // inf, nan, or between [-1.0, 1.0]) values in the channel data.
-  // TODO(crbug.com/373960632): Remove these methods, and rename `channel_span`
-  // to `channel`.
-  float* channel(int channel) {
-    CHECK(!is_bitstream_format_);
-    return channel_data_[channel].data();
-  }
-  const float* channel(int channel) const {
-    CHECK(!is_bitstream_format_);
-    return channel_data_[channel].data();
-  }
-
+  // TODO(crbug.com/373960632): Rename `channel_span` to `channel`.
   Channel channel_span(int channel) {
     CHECK(!is_bitstream_format_);
     return channel_data_[channel];
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc
index 80f86845..8e3db3f1 100644
--- a/media/base/media_switches.cc
+++ b/media/base/media_switches.cc
@@ -929,6 +929,13 @@
 #endif
 );
 
+// Enables a platform-specific resolution cutoff for prioritizing platform
+// decoders over software decoders or vice-versa.
+//
+// Note: This feature is used by ChromeOS tests and shouldn't be removed even
+// though it has long been enabled by default.
+BASE_FEATURE(kResolutionBasedDecoderPriority, base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Allows the AutoPictureInPictureTabHelper to automatically enter
 // picture-in-picture for websites with video playback (instead of only websites
 // using camera or microphone).
diff --git a/media/base/media_switches.h b/media/base/media_switches.h
index a707db8e..02090f06 100644
--- a/media/base/media_switches.h
+++ b/media/base/media_switches.h
@@ -387,6 +387,7 @@
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kWebRTCColorAccuracy);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kWebrtcMediaCapabilitiesParameters);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kWidevinePersistentLicenseSupport);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kResolutionBasedDecoderPriority);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kMatchSourceAudioChannelLayout);
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/media/filters/decoder_selector.cc b/media/filters/decoder_selector.cc
index c7e9dce..b3b8258 100644
--- a/media/filters/decoder_selector.cc
+++ b/media/filters/decoder_selector.cc
@@ -74,10 +74,12 @@
 DecoderSelector<StreamType>::DecoderSelector(
     scoped_refptr<base::SequencedTaskRunner> task_runner,
     CreateDecodersCB create_decoders_cb,
-    MediaLog* media_log)
+    MediaLog* media_log,
+    bool enable_priority_based_selection)
     : task_runner_(std::move(task_runner)),
       create_decoders_cb_(std::move(create_decoders_cb)),
-      media_log_(media_log) {
+      media_log_(media_log),
+      enable_priority_based_selection_(enable_priority_based_selection) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
 }
 
@@ -349,7 +351,7 @@
     // selection based on resolution. Experiments show this greatly improves
     // rebuffering for src= playbacks without config changes, but doesn't help
     // and may hurt Media Source based playbacks.
-    if (stream_->SupportsConfigChanges()) {
+    if (!enable_priority_based_selection_ || stream_->SupportsConfigChanges()) {
       decoders_.push_back(std::move(decoder));
       continue;
     }
diff --git a/media/filters/decoder_selector.h b/media/filters/decoder_selector.h
index ca0a5ae5..c3aece0 100644
--- a/media/filters/decoder_selector.h
+++ b/media/filters/decoder_selector.h
@@ -66,7 +66,8 @@
   // characteristics of each decoder and config (resolution, platform, etc).
   DecoderSelector(scoped_refptr<base::SequencedTaskRunner> task_runner,
                   CreateDecodersCB create_decoders_cb,
-                  MediaLog* media_log);
+                  MediaLog* media_log,
+                  bool enable_priority_based_selection = false);
 
   DecoderSelector(const DecoderSelector&) = delete;
   DecoderSelector& operator=(const DecoderSelector&) = delete;
@@ -153,6 +154,8 @@
   // failing due to running out of more acceptable decoders.
   std::optional<DecoderStatus> decode_failure_reinit_cause_ = std::nullopt;
 
+  const bool enable_priority_based_selection_;
+
   // Indicates that the first decoder in `decoders_` is a platform decoder and
   // should maintain its place when FilterAndSortAvailableDecoders() runs.
   bool prefer_prepended_platform_decoder_ = false;
diff --git a/media/filters/decoder_selector_unittest.cc b/media/filters/decoder_selector_unittest.cc
index d5310956..8d99ec5a 100644
--- a/media/filters/decoder_selector_unittest.cc
+++ b/media/filters/decoder_selector_unittest.cc
@@ -344,13 +344,14 @@
     }
   }
 
-  void CreateDecoderSelector(bool supports_config_changes = false) {
+  void CreateDecoderSelector(bool supports_config_changes = false,
+                             bool enable_priority_based_selection = true) {
     EXPECT_CALL(demuxer_stream_, SupportsConfigChanges())
         .WillRepeatedly(Return(supports_config_changes));
     decoder_selector_ = std::make_unique<Selector>(
         task_environment_.GetMainThreadTaskRunner(),
         base::BindRepeating(&Self::CreateDecoders, base::Unretained(this)),
-        &media_log_);
+        &media_log_, enable_priority_based_selection);
     decoder_selector_->Initialize(
         traits_.get(), &demuxer_stream_, cdm_context_.get(),
         base::BindRepeating(&Self::OnWaiting, base::Unretained(this)));
@@ -515,7 +516,34 @@
   // prioritized on any platform.
   this->demuxer_stream_.set_video_decoder_config(
       TestVideoConfig::Custom(gfx::Size(64, 64)));
-  this->CreateDecoderSelector(/*supports_config_changes=*/true);
+  this->CreateDecoderSelector(/*supports_config_changes=*/true,
+                              /*enable_priority_based_selection=*/true);
+
+  EXPECT_CALL(*this, OnDecoderSelected(kDecoder1));
+  this->SelectNextDecoder();
+  EXPECT_CALL(*this, OnDecoderSelected(kDecoder2));
+  this->SelectNextDecoder();
+  EXPECT_CALL(*this, OnDecoderSelected(kDecoder3));
+  this->SelectNextDecoder();
+  EXPECT_CALL(*this, OnDecoderSelected(kDecoder4));
+  this->SelectNextDecoder();
+  EXPECT_CALL(*this, NoDecoderSelected());
+  this->SelectNextDecoder();
+}
+
+TEST_F(VideoDecoderSelectorTest,
+       ClearStream_PrioritizeSoftwareDecodersFullyDisabled) {
+  this->AddMockPlatformDecoder(kDecoder1, kClearOnly);
+  this->AddMockDecoder(kDecoder2, kClearOnly);
+  this->AddMockPlatformDecoder(kDecoder3, kAlwaysSucceed);
+  this->AddMockDecoder(kDecoder4, kAlwaysSucceed);
+
+  // Create a clear config that will cause software decoders to be
+  // prioritized on any platform.
+  this->demuxer_stream_.set_video_decoder_config(
+      TestVideoConfig::Custom(gfx::Size(64, 64)));
+  this->CreateDecoderSelector(/*supports_config_changes=*/false,
+                              /*enable_priority_based_selection=*/false);
 
   EXPECT_CALL(*this, OnDecoderSelected(kDecoder1));
   this->SelectNextDecoder();
diff --git a/media/filters/decoder_stream.cc b/media/filters/decoder_stream.cc
index 5cc6adc..f7503e9 100644
--- a/media/filters/decoder_stream.cc
+++ b/media/filters/decoder_stream.cc
@@ -107,7 +107,11 @@
       stream_(nullptr),
       cdm_context_(nullptr),
       decoder_produced_a_frame_(false),
-      decoder_selector_(task_runner_, std::move(create_decoders_cb), media_log),
+      decoder_selector_(
+          task_runner_,
+          std::move(create_decoders_cb),
+          media_log,
+          base::FeatureList::IsEnabled(kResolutionBasedDecoderPriority)),
       decoding_eos_(false),
       preparing_output_(false),
       pending_decode_requests_(0),
diff --git a/media/filters/ffmpeg_demuxer.cc b/media/filters/ffmpeg_demuxer.cc
index 99b40c3..b8a6fdb 100644
--- a/media/filters/ffmpeg_demuxer.cc
+++ b/media/filters/ffmpeg_demuxer.cc
@@ -457,9 +457,16 @@
   // reference inner memory of FFmpeg.  As such we should transfer the packet
   // into memory we control.
   buffer = DecoderBuffer::CopyFrom(AVPacketData(*packet).subspan(data_offset));
-  if (side_data.size() > 0) {
-    buffer->WritableSideData().alpha_data =
-        base::HeapArray<uint8_t>::CopiedFrom(side_data);
+
+  if (side_data.size() > 8) {
+    // First 8 bytes of side data is the side_data_id in big endian. This is the
+    // same as the matroska BlockAddID whose values are documented here:
+    // https://www.matroska.org/technical/codec_specs.html#block-addition-mappings
+    const uint64_t side_data_id = base::U64FromBigEndian(side_data.first<8u>());
+    if (side_data_id == 1) {
+      buffer->WritableSideData().alpha_data =
+          base::HeapArray<uint8_t>::CopiedFrom(side_data.subspan(8u));
+    }
   }
 
   if (decrypt_config) {
diff --git a/media/filters/video_decoder_stream_unittest.cc b/media/filters/video_decoder_stream_unittest.cc
index 9f15a14..fd319081 100644
--- a/media/filters/video_decoder_stream_unittest.cc
+++ b/media/filters/video_decoder_stream_unittest.cc
@@ -514,6 +514,8 @@
 
   base::test::SingleThreadTaskEnvironment task_environment_{
       base::test::TaskEnvironment::TimeSource::MOCK_TIME};
+  base::test::ScopedFeatureList enabled_features_{
+      kResolutionBasedDecoderPriority};
 
   StrictMock<MockMediaLog> media_log_;
   std::unique_ptr<VideoDecoderStream> video_decoder_stream_;
diff --git a/media/filters/vpx_video_decoder.cc b/media/filters/vpx_video_decoder.cc
index 55e269d..ad3c939 100644
--- a/media/filters/vpx_video_decoder.cc
+++ b/media/filters/vpx_video_decoder.cc
@@ -421,18 +421,11 @@
     const DecoderBuffer* buffer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!vpx_codec_alpha_ || !buffer->side_data() ||
-      buffer->side_data()->alpha_data.size() < 8) {
+      buffer->side_data()->alpha_data.empty()) {
     return kAlphaPlaneProcessed;
   }
 
-  // First 8 bytes of side data is |side_data_id| in big endian.
-  auto [alpha_data_id, alpha_data] =
-      buffer->side_data()->alpha_data.as_span().split_at<8u>();
-  const uint64_t side_data_id = base::U64FromBigEndian(alpha_data_id);
-  if (side_data_id != 1) {
-    return kAlphaPlaneProcessed;
-  }
-
+  auto& alpha_data = buffer->side_data()->alpha_data;
   // Try and decode buffer->raw_side_data() minus the first 8 bytes as a full
   // frame.
   {
diff --git a/media/formats/webm/webm_cluster_parser.cc b/media/formats/webm/webm_cluster_parser.cc
index 017b6b3..897325c 100644
--- a/media/formats/webm/webm_cluster_parser.cc
+++ b/media/formats/webm/webm_cluster_parser.cc
@@ -519,10 +519,17 @@
           .subspan(data_offset);
   auto buffer = StreamParserBuffer::CopyFrom(data_span, is_keyframe,
                                              buffer_type, track_num);
-  if (additional_size) {
-    buffer->WritableSideData().alpha_data =
-        base::HeapArray<uint8_t>::CopiedFrom(UNSAFE_TODO(
-            base::span<const uint8_t>(additional, additional_size)));
+  if (additional_size > 8) {
+    auto side_data =
+        UNSAFE_TODO(base::span<const uint8_t>(additional, additional_size));
+    // First 8 bytes of side data is the side_data_id in big endian. This is the
+    // same as the matroska BlockAddID whose values are documented here:
+    // https://www.matroska.org/technical/codec_specs.html#block-addition-mappings
+    const uint64_t side_data_id = base::U64FromBigEndian(side_data.first<8u>());
+    if (side_data_id == 1) {
+      buffer->WritableSideData().alpha_data =
+          base::HeapArray<uint8_t>::CopiedFrom(side_data.subspan(8u));
+    }
   }
 
   if (decrypt_config) {
diff --git a/media/video/alpha_video_encoder_wrapper_unittest.cc b/media/video/alpha_video_encoder_wrapper_unittest.cc
index 7cbced93..f1f7b16 100644
--- a/media/video/alpha_video_encoder_wrapper_unittest.cc
+++ b/media/video/alpha_video_encoder_wrapper_unittest.cc
@@ -265,12 +265,8 @@
         buffer->set_timestamp(output.timestamp);
         buffer->set_is_key_frame(output.key_frame);
         EXPECT_FALSE(output.alpha_data.empty());
-        // Side data id for alpha. Big endian one.
-        std::vector<uint8_t> buf_alpha = {0, 0, 0, 0, 0, 0, 0, 1};
-        buf_alpha.insert(buf_alpha.end(), output.alpha_data.begin(),
-                         output.alpha_data.end());
         buffer->WritableSideData().alpha_data =
-            base::HeapArray<uint8_t>::CopiedFrom(buf_alpha);
+            base::HeapArray<uint8_t>::CopiedFrom(output.alpha_data);
         decoder_->Decode(std::move(buffer), base::DoNothing());
       });
 
diff --git a/mojo/public/BUILD.gn b/mojo/public/BUILD.gn
index 2150baaa..cdbfb98 100644
--- a/mojo/public/BUILD.gn
+++ b/mojo/public/BUILD.gn
@@ -10,6 +10,7 @@
     "cpp/bindings",
     "cpp/test:test_mojom",
     "interfaces/bindings/tests:test_interfaces",
+    "rust:mojo_c_system_api",
   ]
 
   if (is_android) {
@@ -24,6 +25,7 @@
   deps = [
     "c/system",
     "cpp/bindings",
+    "rust:mojo_c_system_api",
   ]
 }
 
diff --git a/mojo/public/rust/BUILD.gn b/mojo/public/rust/BUILD.gn
new file mode 100644
index 0000000..cd0a0d3
--- /dev/null
+++ b/mojo/public/rust/BUILD.gn
@@ -0,0 +1,9 @@
+# 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("//build/rust/rust_bindgen.gni")
+
+rust_bindgen("mojo_c_system_api") {
+  header = "//mojo/public/c/system/thunks.h"
+  deps = [ "//mojo/public/c/system" ]
+}
diff --git a/mojo/public/tools/bindings/README.md b/mojo/public/tools/bindings/README.md
index 8a10d8d..56e24826 100644
--- a/mojo/public/tools/bindings/README.md
+++ b/mojo/public/tools/bindings/README.md
@@ -627,6 +627,12 @@
   if other factors such as inlining or code folding end up obscuring the message
   information. This generates extra code, so it is not the default behavior.
 
+* **`[VendorSpecified]`**: The `VendorSpecified` attribute can be used on any of
+  the mojo entities, such as structs, unions, interfaces, constants, and enums,
+  in which downstream vendors can customize the code generation requirements for
+  their respective products.  The attribute is a string value that can be
+  referenced in a templating system and can be used for conditional generation.
+
 ## Generated Code For Target Languages
 
 When the bindings generator successfully processes an input Mojom file, it emits
diff --git a/mojo/public/tools/bindings/checks/mojom_attributes_check.py b/mojo/public/tools/bindings/checks/mojom_attributes_check.py
index 1322069..49a792c 100644
--- a/mojo/public/tools/bindings/checks/mojom_attributes_check.py
+++ b/mojo/public/tools/bindings/checks/mojom_attributes_check.py
@@ -9,6 +9,7 @@
 _COMMON_ATTRIBUTES = {
     'EnableIf',
     'EnableIfNot',
+    'VendorSpecified',
 }
 
 # For struct, union & parameter lists.
diff --git a/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py b/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py
index e0dc5b2..3832d503 100644
--- a/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py
+++ b/mojo/public/tools/bindings/checks/mojom_attributes_check_unittest.py
@@ -108,6 +108,11 @@
       interface FooWithDirectReceiver {
         Method();
       };
+
+      [VendorSpecified="foo=bar"]
+      interface InterfaceWithVendorSpecifiedStringAttribute {
+        Method();
+      };
     """)
 
   def testWrongModuleStable(self):
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc
index 2ec43f38..f5d37057 100644
--- a/net/http/http_stream_pool_attempt_manager.cc
+++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -505,8 +505,7 @@
 
   DCHECK(!HasAvailableSpdySession());
 
-  MaybeAttemptTcpBased(/*exclude_ip_endpoint=*/std::nullopt,
-                       /*max_attempts=*/1);
+  MaybeAttemptTcpBased(/*exclude_ip_endpoint=*/std::nullopt);
 }
 
 void HttpStreamPool::AttemptManager::CancelTcpBasedAttempts(
@@ -1284,8 +1283,7 @@
 }
 
 void HttpStreamPool::AttemptManager::MaybeAttemptTcpBased(
-    std::optional<IPEndPoint> exclude_ip_endpoint,
-    std::optional<size_t> max_attempts) {
+    std::optional<IPEndPoint> exclude_ip_endpoint) {
   if (is_shutting_down()) {
     return;
   }
@@ -1301,7 +1299,6 @@
 
   // There might be multiple pending jobs. Make attempts as much as needed
   // and allowed.
-  size_t num_attempts = 0;
   const bool using_tls = UsingTls();
   while (IsTcpBasedAttemptReady()) {
     // TODO(crbug.com/346835898): Change to DCHECK once we stabilize the
@@ -1333,11 +1330,6 @@
     }
 
     CreateAndStartTcpBasedAttempt(using_tls, *ip_endpoint, slot);
-
-    ++num_attempts;
-    if (max_attempts.has_value() && num_attempts >= *max_attempts) {
-      break;
-    }
   }
 }
 
diff --git a/net/http/http_stream_pool_attempt_manager.h b/net/http/http_stream_pool_attempt_manager.h
index 1e8e3ef..07ff02fa 100644
--- a/net/http/http_stream_pool_attempt_manager.h
+++ b/net/http/http_stream_pool_attempt_manager.h
@@ -347,11 +347,9 @@
 
   // Attempts connections if there are pending jobs and IPEndPoints that
   // haven't failed. If `exclude_ip_endpoint` is given, exclude the IPEndPoint
-  // from attempts. If `max_attempts` is given, attempts connections up to
-  // `max_attempts`.
+  // from attempts.
   void MaybeAttemptTcpBased(
-      std::optional<IPEndPoint> exclude_ip_endpoint = std::nullopt,
-      std::optional<size_t> max_attempts = std::nullopt);
+      std::optional<IPEndPoint> exclude_ip_endpoint = std::nullopt);
 
   // Creates and starts a TCP based attempt.
   void CreateAndStartTcpBasedAttempt(bool using_tls,
diff --git a/services/webnn/tflite/graph_builder_tflite.cc b/services/webnn/tflite/graph_builder_tflite.cc
index 7e72d6b..1b17a32e 100644
--- a/services/webnn/tflite/graph_builder_tflite.cc
+++ b/services/webnn/tflite/graph_builder_tflite.cc
@@ -4640,6 +4640,7 @@
     int32_t axis) -> base::expected<int32_t, std::string> {
   const std::vector<uint32_t> indices_strides =
       CalculateStrides(indices_dimensions);
+  CHECK_EQ(indices_dimensions.size(), input_dimensions.size());
   const size_t indices_rank = indices_strides.size();
 
   // Clamp the values in `indices` to be in range of `-N` (inclusive) to `N`
@@ -4695,16 +4696,32 @@
 
   ASSIGN_OR_RETURN(const TensorInfo& input_tensor_info,
                    SerializeInputTensorInfo(gather_elements.input_operand_id));
-  ASSIGN_OR_RETURN(
-      const TensorIndex indices_tensor_index,
-      SerializeElementsCoordinates<int64_t>(
-          indices_operand.descriptor.shape(),
-          GetConstantInt64Value(gather_elements.indices_operand_id),
-          input_tensor_info.dimensions, gather_elements.axis));
-  const TensorIndex output_tensor_index =
-      SerializeOutputTensorInfo(gather_elements.output_operand_id).index;
-  return SerializeGatherNDOperation(input_tensor_info.index,
-                                    indices_tensor_index, output_tensor_index);
+
+  const base::FixedArray<int64_t> indices_value =
+      GetConstantInt64Value(gather_elements.indices_operand_id);
+  ASSIGN_OR_RETURN(const TensorIndex indices_tensor_index,
+                   SerializeElementsCoordinates<int64_t>(
+                       indices_operand.descriptor.shape(), indices_value,
+                       input_tensor_info.dimensions, gather_elements.axis));
+  const TensorInfo& output_tensor_info =
+      SerializeOutputTensorInfo(gather_elements.output_operand_id);
+  // The emulated GatherND will always output a tensor with one dimension
+  // because the shape of the indices tensor is 2D [flat_indices_size,
+  // input_rank], while GatherElements requires output tensor shape being the
+  // same as indices tensor, so we need to insert a reshape.
+  //
+  // For example, if the input shape is [4, 2, 2],  the indices are [1, 2, 2]
+  // and axis = 0, then the output shape of gatherND will be [4] that is
+  // calculated with ResizeTensor. The output tensor needs to be reshaped to [1,
+  // 2, 2].
+  const TensorIndex gather_nd_tensor_index = SerializeTemporaryTensor(
+      {base::checked_cast<int32_t>(indices_value.size())},
+      input_tensor_info.data_type);
+  operators_.emplace_back(SerializeGatherNDOperation(
+      input_tensor_info.index, indices_tensor_index, gather_nd_tensor_index));
+  return SerializeReshapeOperation(gather_nd_tensor_index,
+                                   output_tensor_info.index,
+                                   output_tensor_info.dimensions);
 }
 
 auto GraphBuilderTflite::SerializeGatherND(const mojom::GatherND& gather_nd)
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 79d35b8..bcd3afd 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -17568,7 +17568,6 @@
                         "autofill_address": "true",
                         "click_to_call": "true",
                         "collaboration_messaging": "true",
-                        "cookie_controls": "true",
                         "discounts": "true",
                         "file_system_access": "true",
                         "find": "true",
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index 0372e77..14c86e5 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/14240658/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/14243656/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 69530df..de65270 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/14240658/artifacts/repository/androidx/activity/activity/1.12.0-SNAPSHOT/activity-1.12.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/activity/activity/1.12.0-SNAPSHOT/activity-1.12.0-20251009.205119-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 6ce8ed0..f2ca0d7 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/14240658/artifacts/repository/androidx/activity/activity-compose/1.12.0-SNAPSHOT/activity-compose-1.12.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/activity/activity-compose/1.12.0-SNAPSHOT/activity-compose-1.12.0-20251009.205119-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 bfe96e6b..c33f371 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/14240658/artifacts/repository/androidx/activity/activity-ktx/1.12.0-SNAPSHOT/activity-ktx-1.12.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/activity/activity-ktx/1.12.0-SNAPSHOT/activity-ktx-1.12.0-20251009.205119-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 3576a2e..b8bc358c 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/14240658/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/annotation/annotation-experimental/1.6.0-SNAPSHOT/annotation-experimental-1.6.0-20251009.205119-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 92f477a..31710a7 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/14240658/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/annotation/annotation-jvm/1.10.0-SNAPSHOT/annotation-jvm-1.10.0-20251009.205119-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 abed040..bfcdd972e 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/14240658/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/appcompat/appcompat/1.8.0-SNAPSHOT/appcompat-1.8.0-20251009.205119-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 f8f5eda..91c49d4d 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/14240658/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/appcompat/appcompat-resources/1.8.0-SNAPSHOT/appcompat-resources-1.8.0-20251009.205119-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 c822f784..cfd1003b 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/14240658/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/appsearch/appsearch/1.2.0-SNAPSHOT/appsearch-1.2.0-20251009.205119-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 6184c5d..a85ff7da 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/14240658/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/appsearch/appsearch-builtin-types/1.2.0-SNAPSHOT/appsearch-builtin-types-1.2.0-20251009.205119-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 83edd11a..8d062ce 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/14240658/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/appsearch/appsearch-platform-storage/1.2.0-SNAPSHOT/appsearch-platform-storage-1.2.0-20251009.205119-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 97c878d..a17e4f6b 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/14240658/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/arch/core/core-common/2.3.0-SNAPSHOT/core-common-2.3.0-20251009.205119-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 9204586..6bed21e 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/14240658/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/arch/core/core-runtime/2.3.0-SNAPSHOT/core-runtime-2.3.0-20251009.205119-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 d3b0179..74ee2d71 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/14240658/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/autofill/autofill/1.4.0-SNAPSHOT/autofill-1.4.0-20251009.205119-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 f7dea50..0c831c9 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/14240658/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/benchmark/benchmark-common/1.5.0-SNAPSHOT/benchmark-common-1.5.0-20251009.205119-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 0e6f0ae..cc50822d 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/14240658/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/benchmark/benchmark-junit4/1.5.0-SNAPSHOT/benchmark-junit4-1.5.0-20251009.205119-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 11f8eb4eb..dace457 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/14240658/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/benchmark/benchmark-macro/1.5.0-SNAPSHOT/benchmark-macro-1.5.0-20251009.205119-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 8a3e8982a..1594217 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/14240658/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/benchmark/benchmark-macro-junit4/1.5.0-SNAPSHOT/benchmark-macro-junit4-1.5.0-20251009.205119-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 9f79bf78..c14dc951 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/14240658/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/benchmark/benchmark-traceprocessor-android/1.5.0-SNAPSHOT/benchmark-traceprocessor-android-1.5.0-20251009.205119-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 04ac33d..9edb95b1 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/14240658/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/biometric/biometric/1.4.0-SNAPSHOT/biometric-1.4.0-20251009.205119-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 1edb61d0..42cf5c2 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/14240658/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/browser/browser/1.10.0-SNAPSHOT/browser-1.10.0-20251009.205119-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 ac4b4db..55c57a5a 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/14240658/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/cardview/cardview/1.1.0-SNAPSHOT/cardview-1.1.0-20251009.205119-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 ea3fdb8..15837ce 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/14240658/artifacts/repository/androidx/collection/collection-jvm/1.6.0-SNAPSHOT/collection-jvm-1.6.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/collection/collection-jvm/1.6.0-SNAPSHOT/collection-jvm-1.6.0-20251009.205119-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 c626a9f3..ef6ae3d 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/14240658/artifacts/repository/androidx/collection/collection-ktx/1.6.0-SNAPSHOT/collection-ktx-1.6.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/collection/collection-ktx/1.6.0-SNAPSHOT/collection-ktx-1.6.0-20251009.205119-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 f3a17a7..243546ac 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/14240658/artifacts/repository/androidx/compose/animation/animation-android/1.10.0-SNAPSHOT/animation-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/animation/animation-android/1.10.0-SNAPSHOT/animation-android-1.10.0-20251009.205119-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 91138b4..208476a8 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/14240658/artifacts/repository/androidx/compose/animation/animation-core-android/1.10.0-SNAPSHOT/animation-core-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/animation/animation-core-android/1.10.0-SNAPSHOT/animation-core-android-1.10.0-20251009.205119-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 57a7c47..6e3e6951 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/14240658/artifacts/repository/androidx/compose/foundation/foundation-android/1.10.0-SNAPSHOT/foundation-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/foundation/foundation-android/1.10.0-SNAPSHOT/foundation-android-1.10.0-20251009.205119-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 3c59a323..82f4a75 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/14240658/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.10.0-SNAPSHOT/foundation-layout-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/foundation/foundation-layout-android/1.10.0-SNAPSHOT/foundation-layout-android-1.10.0-20251009.205119-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 aaac9fe7..c7ab368 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/14240658/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/material3/material3-android/1.5.0-SNAPSHOT/material3-android-1.5.0-20251009.205119-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 2baeb2e7..8ed8253 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/14240658/artifacts/repository/androidx/compose/material/material-ripple-android/1.10.0-SNAPSHOT/material-ripple-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/material/material-ripple-android/1.10.0-SNAPSHOT/material-ripple-android-1.10.0-20251009.205119-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 b4c8dee..20995cd 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/14240658/artifacts/repository/androidx/compose/runtime/runtime-android/1.10.0-SNAPSHOT/runtime-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/runtime/runtime-android/1.10.0-SNAPSHOT/runtime-android-1.10.0-20251009.205119-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 626c55e..93ad8c6 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/14240658/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.10.0-SNAPSHOT/runtime-annotation-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/runtime/runtime-annotation-android/1.10.0-SNAPSHOT/runtime-annotation-android-1.10.0-20251009.205119-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 3a7b603..c01e04db 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/14240658/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.10.0-SNAPSHOT/runtime-retain-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/runtime/runtime-retain-android/1.10.0-SNAPSHOT/runtime-retain-android-1.10.0-20251009.205119-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 c9712e6..0f40669c 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/14240658/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.10.0-SNAPSHOT/runtime-saveable-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/runtime/runtime-saveable-android/1.10.0-SNAPSHOT/runtime-saveable-android-1.10.0-20251009.205119-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 a179b55..95acd3f8 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/14240658/artifacts/repository/androidx/compose/ui/ui-android/1.10.0-SNAPSHOT/ui-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-android/1.10.0-SNAPSHOT/ui-android-1.10.0-20251009.205119-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 47a23803..36febb06 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/14240658/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.10.0-SNAPSHOT/ui-geometry-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-geometry-android/1.10.0-SNAPSHOT/ui-geometry-android-1.10.0-20251009.205119-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 de632dd8..360c530 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/14240658/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.10.0-SNAPSHOT/ui-graphics-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-graphics-android/1.10.0-SNAPSHOT/ui-graphics-android-1.10.0-20251009.205119-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 b9952854..dd0f186 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/14240658/artifacts/repository/androidx/compose/ui/ui-test-android/1.10.0-SNAPSHOT/ui-test-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-test-android/1.10.0-SNAPSHOT/ui-test-android-1.10.0-20251009.205119-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 b9a6a64..0030a3e 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/14240658/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.10.0-SNAPSHOT/ui-test-junit4-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-test-junit4-android/1.10.0-SNAPSHOT/ui-test-junit4-android-1.10.0-20251009.205119-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 1ee48c70..4b62b74 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/14240658/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.10.0-SNAPSHOT/ui-test-manifest-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-test-manifest/1.10.0-SNAPSHOT/ui-test-manifest-1.10.0-20251009.205119-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 a7fa1e9..9d02e2a 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/14240658/artifacts/repository/androidx/compose/ui/ui-text-android/1.10.0-SNAPSHOT/ui-text-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-text-android/1.10.0-SNAPSHOT/ui-text-android-1.10.0-20251009.205119-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 e6f475b..093cfa84 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/14240658/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.10.0-SNAPSHOT/ui-text-google-fonts-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-text-google-fonts/1.10.0-SNAPSHOT/ui-text-google-fonts-1.10.0-20251009.205119-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 9cf03db..4c54c93 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/14240658/artifacts/repository/androidx/compose/ui/ui-unit-android/1.10.0-SNAPSHOT/ui-unit-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-unit-android/1.10.0-SNAPSHOT/ui-unit-android-1.10.0-20251009.205119-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 a238f894..66e3bd1 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/14240658/artifacts/repository/androidx/compose/ui/ui-util-android/1.10.0-SNAPSHOT/ui-util-android-1.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/compose/ui/ui-util-android/1.10.0-SNAPSHOT/ui-util-android-1.10.0-20251009.205119-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 2581f77..8c7c40a4 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/14240658/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/constraintlayout/constraintlayout/2.3.0-SNAPSHOT/constraintlayout-2.3.0-20251009.205119-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 322bb9a4..b071e2a 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/14240658/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/constraintlayout/constraintlayout-core/1.2.0-SNAPSHOT/constraintlayout-core-1.2.0-20251009.205119-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 a3b2bc54..87203820 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/14240658/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/core/core/1.18.0-SNAPSHOT/core-1.18.0-20251009.205119-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 e5769b6..fd044f4b 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/14240658/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/core/core-ktx/1.18.0-SNAPSHOT/core-ktx-1.18.0-20251009.205119-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 5a93611c..c36f267 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/14240658/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/core/core-viewtree/1.1.0-SNAPSHOT/core-viewtree-1.1.0-20251009.205119-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 f59665dd..9e7df7e 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/14240658/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/credentials/credentials/1.6.0-SNAPSHOT/credentials-1.6.0-20251009.205119-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 3481044..fea2631 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/14240658/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/credentials/credentials-play-services-auth/1.6.0-SNAPSHOT/credentials-play-services-auth-1.6.0-20251009.205119-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 ec21be85..39c3b81 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/14240658/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/credentials/registry/registry-provider/1.0.0-SNAPSHOT/registry-provider-1.0.0-20251009.205119-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 fe4e483..44b9ea7 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/14240658/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/credentials/registry/registry-provider-play-services/1.0.0-SNAPSHOT/registry-provider-play-services-1.0.0-20251009.205119-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 b3c3bd9..2ee3ad1 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/14240658/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/cursoradapter/cursoradapter/1.1.0-SNAPSHOT/cursoradapter-1.1.0-20251009.205119-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 d3d42e12..f40aabcd5 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/14240658/artifacts/repository/androidx/datastore/datastore-android/1.2.0-SNAPSHOT/datastore-android-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-android/1.2.0-SNAPSHOT/datastore-android-1.2.0-20251009.205119-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 701500a..0ce86f3 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/14240658/artifacts/repository/androidx/datastore/datastore-core-android/1.2.0-SNAPSHOT/datastore-core-android-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-core-android/1.2.0-SNAPSHOT/datastore-core-android-1.2.0-20251009.205119-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 ba31adb3..25a9a432 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/14240658/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.2.0-SNAPSHOT/datastore-core-okio-jvm-1.2.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-core-okio-jvm/1.2.0-SNAPSHOT/datastore-core-okio-jvm-1.2.0-20251009.205119-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 bfce113..0642599 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/14240658/artifacts/repository/androidx/datastore/datastore-preferences-android/1.2.0-SNAPSHOT/datastore-preferences-android-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-preferences-android/1.2.0-SNAPSHOT/datastore-preferences-android-1.2.0-20251009.205119-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 dd6adb67..de4bdea 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/14240658/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.2.0-SNAPSHOT/datastore-preferences-core-android-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-preferences-core-android/1.2.0-SNAPSHOT/datastore-preferences-core-android-1.2.0-20251009.205119-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 a4bb253..703866e 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/14240658/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.2.0-SNAPSHOT/datastore-preferences-external-protobuf-1.2.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-preferences-external-protobuf/1.2.0-SNAPSHOT/datastore-preferences-external-protobuf-1.2.0-20251009.205119-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 e3371ab..adabc1a 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/14240658/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.2.0-SNAPSHOT/datastore-preferences-proto-1.2.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/datastore/datastore-preferences-proto/1.2.0-SNAPSHOT/datastore-preferences-proto-1.2.0-20251009.205119-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 1f75254..62ed3bf 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/14240658/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/drawerlayout/drawerlayout/1.3.0-SNAPSHOT/drawerlayout-1.3.0-20251009.205119-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 20e87f40e5..1a488e3 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/14240658/artifacts/repository/androidx/emoji/emoji/1.2.0-SNAPSHOT/emoji-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/emoji/emoji/1.2.0-SNAPSHOT/emoji-1.2.0-20251009.205119-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 758de1b..3017eab5 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/14240658/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/fragment/fragment/1.9.0-SNAPSHOT/fragment-1.9.0-20251009.205119-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 2a3dc4d..df76051 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/14240658/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/fragment/fragment-compose/1.9.0-SNAPSHOT/fragment-compose-1.9.0-20251009.205119-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 b5bbcfb1..ceafb4cf 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/14240658/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/fragment/fragment-ktx/1.9.0-SNAPSHOT/fragment-ktx-1.9.0-20251009.205119-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 8e6c36a..ea03e92 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/14240658/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/fragment/fragment-testing/1.9.0-SNAPSHOT/fragment-testing-1.9.0-20251009.205119-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 ba1d1559..46edb0af 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/14240658/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/fragment/fragment-testing-manifest/1.9.0-SNAPSHOT/fragment-testing-manifest-1.9.0-20251009.205119-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 65e87ae..930b1b7 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/14240658/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/graphics/graphics-path/1.1.0-SNAPSHOT/graphics-path-1.1.0-20251009.205119-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 9f73807..1c68768 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/14240658/artifacts/repository/androidx/graphics/graphics-shapes-android/1.1.0-SNAPSHOT/graphics-shapes-android-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/graphics/graphics-shapes-android/1.1.0-SNAPSHOT/graphics-shapes-android-1.1.0-20251009.205119-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 61ee7c1..35937b0 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/14240658/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/interpolator/interpolator/1.1.0-SNAPSHOT/interpolator-1.1.0-20251009.205119-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 d382c158..4758ca1 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.10.0-SNAPSHOT/lifecycle-common-java8-2.10.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-common-java8/2.10.0-SNAPSHOT/lifecycle-common-java8-2.10.0-20251009.205119-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 eaadf4ad..a76fde4 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.10.0-SNAPSHOT/lifecycle-common-jvm-2.10.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-common-jvm/2.10.0-SNAPSHOT/lifecycle-common-jvm-2.10.0-20251009.205119-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 5026eb6..487dc2e 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.10.0-SNAPSHOT/lifecycle-livedata-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-livedata/2.10.0-SNAPSHOT/lifecycle-livedata-2.10.0-20251009.205119-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 821f1e86..eb07ae14 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.10.0-SNAPSHOT/lifecycle-livedata-core-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core/2.10.0-SNAPSHOT/lifecycle-livedata-core-2.10.0-20251009.205119-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 8ad4534..70501da 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-core-ktx-2.10.0-20251009.205119-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 4959582..c4ed10c6 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-ktx-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.10.0-SNAPSHOT/lifecycle-livedata-ktx-2.10.0-20251009.205119-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 a20dcc6..bc2ee85 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-process/2.10.0-SNAPSHOT/lifecycle-process-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-process/2.10.0-SNAPSHOT/lifecycle-process-2.10.0-20251009.205119-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 d6b5594..a54afa9 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.10.0-SNAPSHOT/lifecycle-runtime-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-runtime-android/2.10.0-SNAPSHOT/lifecycle-runtime-android-2.10.0-20251009.205119-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 41b7e67..aa424b0 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.10.0-SNAPSHOT/lifecycle-runtime-compose-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-runtime-compose-android/2.10.0-SNAPSHOT/lifecycle-runtime-compose-android-2.10.0-20251009.205119-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 ecdb1a8..0b4f8f5 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.10.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-runtime-ktx-android/2.10.0-SNAPSHOT/lifecycle-runtime-ktx-android-2.10.0-20251009.205119-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 1518d41..5509898 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-service/2.10.0-SNAPSHOT/lifecycle-service-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-service/2.10.0-SNAPSHOT/lifecycle-service-2.10.0-20251009.205119-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 982f9f2..526e2dd 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-android-2.10.0-20251009.205119-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 be4d5b8..efd8322 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-compose-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-compose-android-2.10.0-20251009.205119-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 38d2b0b..b750418 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.10.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.10.0-SNAPSHOT/lifecycle-viewmodel-ktx-2.10.0-20251009.205119-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 9ddd0df9..eed4b30 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/14240658/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/lifecycle/lifecycle-viewmodel-savedstate-android/2.10.0-SNAPSHOT/lifecycle-viewmodel-savedstate-android-2.10.0-20251009.205119-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 930a756f..1c70c2f 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/14240658/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/loader/loader/1.2.0-SNAPSHOT/loader-1.2.0-20251009.205119-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 7b8f4141..b7a03ce8 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/14240658/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/media/media/1.8.0-SNAPSHOT/media-1.8.0-20251009.205119-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 d607e61..4c16bdde 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/14240658/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/navigation/navigation-common-android/2.10.0-SNAPSHOT/navigation-common-android-2.10.0-20251009.205119-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 97ec2c1..659f7fc 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/14240658/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/navigation/navigation-compose-android/2.10.0-SNAPSHOT/navigation-compose-android-2.10.0-20251009.205119-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 60a6cd31..cc8118b 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/14240658/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/navigation/navigation-runtime-android/2.10.0-SNAPSHOT/navigation-runtime-android-2.10.0-20251009.205119-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 5822b04..7e8ae0d 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/14240658/artifacts/repository/androidx/navigationevent/navigationevent-android/1.0.0-SNAPSHOT/navigationevent-android-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/navigationevent/navigationevent-android/1.0.0-SNAPSHOT/navigationevent-android-1.0.0-20251009.205119-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 c8abce8..0cf3588 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/14240658/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.0.0-SNAPSHOT/navigationevent-compose-android-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/navigationevent/navigationevent-compose-android/1.0.0-SNAPSHOT/navigationevent-compose-android-1.0.0-20251009.205119-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 bc6b6a72..3c2da61 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/14240658/artifacts/repository/androidx/paging/paging-common-android/3.4.0-SNAPSHOT/paging-common-android-3.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/paging/paging-common-android/3.4.0-SNAPSHOT/paging-common-android-3.4.0-20251009.205119-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 1cb6b30..ba31b046 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/14240658/artifacts/repository/androidx/paging/paging-common-ktx/3.4.0-SNAPSHOT/paging-common-ktx-3.4.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/paging/paging-common-ktx/3.4.0-SNAPSHOT/paging-common-ktx-3.4.0-20251009.205119-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 ed4a0b55..3b817a24 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/14240658/artifacts/repository/androidx/paging/paging-compose-android/3.4.0-SNAPSHOT/paging-compose-android-3.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/paging/paging-compose-android/3.4.0-SNAPSHOT/paging-compose-android-3.4.0-20251009.205119-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 60972a4..b339997 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/14240658/artifacts/repository/androidx/paging/paging-runtime/3.4.0-SNAPSHOT/paging-runtime-3.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/paging/paging-runtime/3.4.0-SNAPSHOT/paging-runtime-3.4.0-20251009.205119-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 a34f55f..f46c397 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/14240658/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/palette/palette/1.1.0-SNAPSHOT/palette-1.1.0-20251009.205119-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 2b350d8..54a3e6e8 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/14240658/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/pdf/pdf-document-service/1.0.0-SNAPSHOT/pdf-document-service-1.0.0-20251009.205119-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 20a35344..d3e02bcd 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/14240658/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/pdf/pdf-viewer/1.0.0-SNAPSHOT/pdf-viewer-1.0.0-20251009.205119-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 4320352..45e588d 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/14240658/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/pdf/pdf-viewer-fragment/1.0.0-SNAPSHOT/pdf-viewer-fragment-1.0.0-20251009.205119-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 446e7007..837c951 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/14240658/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/preference/preference/1.3.0-SNAPSHOT/preference-1.3.0-20251009.205119-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 46321b5..2d38256f7 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/14240658/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/profileinstaller/profileinstaller/1.5.0-SNAPSHOT/profileinstaller-1.5.0-20251009.205119-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 04b6f70f..28b3928 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/14240658/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/recyclerview/recyclerview/1.5.0-SNAPSHOT/recyclerview-1.5.0-20251009.205119-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 d0d0fa6..f332b71 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/14240658/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20251009.124049-1.jar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/resourceinspection/resourceinspection-annotation/1.1.0-SNAPSHOT/resourceinspection-annotation-1.1.0-20251009.205119-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 cfd0f87..1fc1d2e 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/14240658/artifacts/repository/androidx/savedstate/savedstate-android/1.4.0-SNAPSHOT/savedstate-android-1.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/savedstate/savedstate-android/1.4.0-SNAPSHOT/savedstate-android-1.4.0-20251009.205119-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 fde5460..265c438 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/14240658/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.4.0-SNAPSHOT/savedstate-compose-android-1.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/savedstate/savedstate-compose-android/1.4.0-SNAPSHOT/savedstate-compose-android-1.4.0-20251009.205119-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 19dc123..9cf7942 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/14240658/artifacts/repository/androidx/savedstate/savedstate-ktx/1.4.0-SNAPSHOT/savedstate-ktx-1.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/savedstate/savedstate-ktx/1.4.0-SNAPSHOT/savedstate-ktx-1.4.0-20251009.205119-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 927712a..fc992c8 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/14240658/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/slidingpanelayout/slidingpanelayout/1.3.0-SNAPSHOT/slidingpanelayout-1.3.0-20251009.205119-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 90c604d..020b2f9b 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/14240658/artifacts/repository/androidx/swiperefreshlayout/swiperefreshlayout/1.2.0-SNAPSHOT/swiperefreshlayout-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/swiperefreshlayout/swiperefreshlayout/1.2.0-SNAPSHOT/swiperefreshlayout-1.2.0-20251009.205119-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 ac5a6192..7399222 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/14240658/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/test/uiautomator/uiautomator/2.4.0-SNAPSHOT/uiautomator-2.4.0-20251009.205119-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 f1cd44ae..7d1cbec 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/14240658/artifacts/repository/androidx/transition/transition/1.7.0-SNAPSHOT/transition-1.7.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/transition/transition/1.7.0-SNAPSHOT/transition-1.7.0-20251009.205119-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 973021b2..4c79175 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/14240658/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/viewpager2/viewpager2/1.2.0-SNAPSHOT/viewpager2-1.2.0-20251009.205119-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 8c3f9cd..3073c7e 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/14240658/artifacts/repository/androidx/webkit/webkit/1.15.0-SNAPSHOT/webkit-1.15.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/webkit/webkit/1.15.0-SNAPSHOT/webkit-1.15.0-20251009.205119-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 e8959c2..28250c4 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/14240658/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/window/sidecar/sidecar/1.0.0-SNAPSHOT/sidecar-1.0.0-20251009.205119-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 517f3cf..3f4e3dcc 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/14240658/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/window/window/1.6.0-SNAPSHOT/window-1.6.0-20251009.205119-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 1b47c43..6566d1b 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/14240658/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20251009.124049-1.aar
+URL: https://androidx.dev/snapshots/builds/14243656/artifacts/repository/androidx/window/window-core-android/1.6.0-SNAPSHOT/window-core-android-1.6.0-20251009.205119-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 074eec2..8af6c56 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 074eec2f148edf8fb9f1672e54cec3472d6d7a67
+Subproject commit 8af6c56672bf1819bfb72c539a072e2b12964cf3
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
index d490a10..62eca4e 100644
--- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
+++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -670,7 +670,8 @@
 
     code_generator_info = cg_context.member_like.code_generator_info
     is_partial = code_generator_info.defined_in_partial
-    if (is_partial and
+    is_across_component = code_generator_info.defined_across_component
+    if ((is_partial or is_across_component) and
             not (cg_context.constructor or cg_context.member_like.is_static)):
         arguments.append("*${blink_receiver}")
 
@@ -704,7 +705,7 @@
         func_name = _make_reflect_accessor_func_name(cg_context)
 
     if (cg_context.constructor or cg_context.member_like.is_static
-            or is_partial):
+            or is_partial or is_across_component):
         class_like = cg_context.member_like.owner_mixin or cg_context.class_like
         class_name = (code_generator_info.receiver_implemented_as
                       or name_style.class_(class_like.identifier))
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py b/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
index 481408a0..ecf4ca43 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/code_generator_info.py
@@ -6,6 +6,7 @@
 # attributes are auto-generated from this list because they're boilerplated.
 _CODE_GENERATOR_INFO_ATTRIBUTES = (
     'blink_headers',
+    'defined_across_component',
     'defined_in_partial',
     'for_testing',
     'is_active_script_wrappable',
diff --git a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
index 4a176dc..8582697 100644
--- a/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
+++ b/third_party/blink/renderer/bindings/scripts/web_idl/idl_compiler.py
@@ -108,6 +108,7 @@
 
         # Merge partial definitions.
         self._record_defined_in_partial_and_mixin()
+        self._record_defined_across_component()
         self._propagate_extattrs_per_idl_fragment()
         self._determine_blink_headers()
         self._merge_partial_interface_likes()
@@ -311,6 +312,51 @@
             for member in new_ir.iter_all_members():
                 member.code_generator_info.set_defined_in_partial(is_partial)
 
+    def _record_defined_across_component(self):
+
+        def check_across_component(original_ir, extended_ir):
+            return ("core" in original_ir.components
+                    and "modules" in extended_ir.components)
+
+        def set_defined_across_component(ir, value):
+            ir.code_generator_info.set_defined_across_component(value)
+            for member in ir.iter_all_members():
+                member.code_generator_info.set_defined_across_component(value)
+
+        interfaces = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE)
+        mixins = self._ir_map.find_by_kind(IRMap.IR.Kind.INTERFACE_MIXIN)
+        includes = self._ir_map.find_by_kind(IRMap.IR.Kind.INCLUDES)
+        partials = self._ir_map.irs_of_kinds(
+            IRMap.IR.Kind.PARTIAL_INTERFACE,
+            IRMap.IR.Kind.PARTIAL_INTERFACE_MIXIN)
+        interfaces_or_mixins = interfaces | mixins
+
+        self._ir_map.move_to_new_phase()
+
+        # TODO(crbug.com/449800522): Remove `WebGL2RenderingContextBase`
+        # condition after WebGL2RenderingContextBase follows the spec.
+        across_component_mixins = {
+            mixins[include.mixin_identifier]
+            for include_list in includes.values()
+            for include in include_list
+            if include.interafce_identifier != "WebGL2RenderingContextBase" and
+            check_across_component(interfaces[include.interafce_identifier],
+                                   mixins[include.mixin_identifier])
+        }
+
+        for old_ir in mixins.values():
+            new_ir = make_copy(old_ir)
+            self._ir_map.add(new_ir)
+            is_across_component = old_ir in across_component_mixins
+            set_defined_across_component(new_ir, is_across_component)
+
+        for old_ir in partials:
+            new_ir = make_copy(old_ir)
+            self._ir_map.add(new_ir)
+            is_across_component = check_across_component(
+                interfaces_or_mixins[new_ir.identifier], old_ir)
+            set_defined_across_component(new_ir, is_across_component)
+
     def _propagate_extattrs_per_idl_fragment(self):
         def propagate_extattr(extattr_key_and_attr_name,
                               bag=None,
@@ -423,7 +469,9 @@
             new_ir = self._maybe_make_copy(old_ir)
             self._ir_map.add(new_ir)
 
-            if new_ir.is_mixin and not new_ir.is_partial:
+            if (new_ir.is_mixin
+                    and not new_ir.code_generator_info.defined_across_component
+                    and not new_ir.is_partial):
                 continue
 
             basepath, _ = posixpath.splitext(
diff --git a/third_party/blink/renderer/core/dom/focusgroup_flags.cc b/third_party/blink/renderer/core/dom/focusgroup_flags.cc
index f9bf6363..e1e2ac57 100644
--- a/third_party/blink/renderer/core/dom/focusgroup_flags.cc
+++ b/third_party/blink/renderer/core/dom/focusgroup_flags.cc
@@ -59,7 +59,6 @@
     {"row-flow", FocusgroupFlags::kRowFlow},
     {"col-flow", FocusgroupFlags::kColFlow},
     {"no-memory", FocusgroupFlags::kNoMemory},
-    // Deprecated: {"extend", FocusgroupFlags::kExtend},
 };
 
 // Returns true if a flag contains a modifier only meaningful for grid
diff --git a/third_party/blink/renderer/core/dom/focusgroup_flags.h b/third_party/blink/renderer/core/dom/focusgroup_flags.h
index 60ad7d1..d96f71ae 100644
--- a/third_party/blink/renderer/core/dom/focusgroup_flags.h
+++ b/third_party/blink/renderer/core/dom/focusgroup_flags.h
@@ -54,10 +54,6 @@
 
   // Memory behavior override disables history-based focus restoration:
   kNoMemory = 1 << 6,
-
-  // Deprecated. Will be removed when opt-out behavior is implemented.
-  // Placed last for easy identification; its bit may be recycled after removal.
-  kExtend = 1 << 7,
 };
 
 inline constexpr FocusgroupFlags operator&(FocusgroupFlags a,
diff --git a/third_party/blink/renderer/core/editing/selection_adjuster.cc b/third_party/blink/renderer/core/editing/selection_adjuster.cc
index eee0f73..7638b41 100644
--- a/third_party/blink/renderer/core/editing/selection_adjuster.cc
+++ b/third_party/blink/renderer/core/editing/selection_adjuster.cc
@@ -36,6 +36,7 @@
 #include "third_party/blink/renderer/core/editing/visible_units.h"
 #include "third_party/blink/renderer/core/html/html_body_element.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
+#include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 
 namespace blink {
 
@@ -263,6 +264,14 @@
         const VisiblePositionTemplate<Strategy> visible_paragraph_end =
             EndOfParagraph(CreateVisiblePosition(passed_end));
 
+        // If we're selecting within a table cell, constrain the selection
+        // to stay within that cell to avoid including unwanted table structure
+        if (RuntimeEnabledFeatures::
+                RestrictTableCellSelectionToBoundaryEnabled() &&
+            EnclosingTableCell(visible_paragraph_end.DeepEquivalent())) {
+          return visible_paragraph_end.DeepEquivalent();
+        }
+
         // Include the "paragraph break" (the space from the end of this
         // paragraph to the start of the next one) in the selection.
         const VisiblePositionTemplate<Strategy> end =
diff --git a/third_party/blink/renderer/core/events/message_event.cc b/third_party/blink/renderer/core/events/message_event.cc
index 91c2b4b..96642e3 100644
--- a/third_party/blink/renderer/core/events/message_event.cc
+++ b/third_party/blink/renderer/core/events/message_event.cc
@@ -93,8 +93,10 @@
       data_as_v8_value_.Set(initializer->data().GetIsolate(), data);
     }
   }
-  if (initializer->hasOrigin())
-    origin_ = initializer->origin();
+  if (initializer->hasOrigin()) {
+    potentially_invalid_origin_serialization_ = initializer->origin();
+    origin_ = SecurityOrigin::CreateFromString(initializer->origin());
+  }
   if (initializer->hasLastEventId())
     last_event_id_ = initializer->lastEventId();
   if (initializer->hasSource() && IsValidSource(initializer->source()))
@@ -106,13 +108,13 @@
   DCHECK(IsValidSource(source_.Get()));
 }
 
-MessageEvent::MessageEvent(const String& origin,
+MessageEvent::MessageEvent(scoped_refptr<const SecurityOrigin> origin,
                            const String& last_event_id,
                            EventTarget* source,
                            GCedMessagePortArray* ports)
     : Event(event_type_names::kMessage, Bubbles::kNo, Cancelable::kNo),
       data_type_(kDataTypeScriptValue),
-      origin_(origin),
+      origin_(std::move(origin)),
       last_event_id_(last_event_id),
       source_(source),
       ports_(ports) {
@@ -120,7 +122,7 @@
 }
 
 MessageEvent::MessageEvent(scoped_refptr<SerializedScriptValue> data,
-                           const String& origin,
+                           scoped_refptr<const SecurityOrigin> origin,
                            MessageOriginKind message_origin_kind,
                            const String& last_event_id,
                            EventTarget* source,
@@ -132,7 +134,7 @@
           SerializedScriptValue::Unpack(std::move(data))),
       data_is_from_untrusted_source_(message_origin_kind ==
                                      kMessageIsCrossOrigin),
-      origin_(origin),
+      origin_(std::move(origin)),
       last_event_id_(last_event_id),
       source_(source),
       ports_(ports),
@@ -144,7 +146,7 @@
 
 MessageEvent::MessageEvent(
     scoped_refptr<SerializedScriptValue> data,
-    const String& origin,
+    scoped_refptr<const SecurityOrigin> origin,
     MessageOriginKind message_origin_kind,
     const String& last_event_id,
     EventTarget* source,
@@ -157,7 +159,7 @@
           SerializedScriptValue::Unpack(std::move(data))),
       data_is_from_untrusted_source_(message_origin_kind ==
                                      kMessageIsCrossOrigin),
-      origin_(origin),
+      origin_(std::move(origin)),
       last_event_id_(last_event_id),
       source_(source),
       channels_(std::move(channels)),
@@ -168,37 +170,41 @@
                                              SizeOfExternalMemoryInBytes());
 }
 
-MessageEvent::MessageEvent(const String& origin, EventTarget* source)
+MessageEvent::MessageEvent(scoped_refptr<const SecurityOrigin> origin,
+                           EventTarget* source)
     : Event(event_type_names::kMessageerror, Bubbles::kNo, Cancelable::kNo),
       data_type_(kDataTypeNull),
-      origin_(origin),
+      origin_(std::move(origin)),
       source_(source) {
   DCHECK(IsValidSource(source_.Get()));
 }
 
-MessageEvent::MessageEvent(const String& data, const String& origin)
+MessageEvent::MessageEvent(const String& data,
+                           scoped_refptr<const SecurityOrigin> origin)
     : Event(event_type_names::kMessage, Bubbles::kNo, Cancelable::kNo),
       data_type_(kDataTypeString),
       data_as_string_(data),
-      origin_(origin) {
+      origin_(std::move(origin)) {
   serialized_data_memory_accounter_.Increase(v8::Isolate::GetCurrent(),
                                              SizeOfExternalMemoryInBytes());
 }
 
-MessageEvent::MessageEvent(Blob* data, const String& origin)
+MessageEvent::MessageEvent(Blob* data,
+                           scoped_refptr<const SecurityOrigin> origin)
     : Event(event_type_names::kMessage, Bubbles::kNo, Cancelable::kNo),
       data_type_(kDataTypeBlob),
       data_as_blob_(data),
-      origin_(origin) {
+      origin_(std::move(origin)) {
   serialized_data_memory_accounter_.Increase(v8::Isolate::GetCurrent(),
                                              SizeOfExternalMemoryInBytes());
 }
 
-MessageEvent::MessageEvent(DOMArrayBuffer* data, const String& origin)
+MessageEvent::MessageEvent(DOMArrayBuffer* data,
+                           scoped_refptr<const SecurityOrigin> origin)
     : Event(event_type_names::kMessage, Bubbles::kNo, Cancelable::kNo),
       data_type_(kDataTypeArrayBuffer),
       data_as_array_buffer_(data),
-      origin_(origin) {
+      origin_(std::move(origin)) {
   serialized_data_memory_accounter_.Increase(v8::Isolate::GetCurrent(),
                                              SizeOfExternalMemoryInBytes());
 }
@@ -234,7 +240,8 @@
   data_type_ = kDataTypeScriptValue;
   data_as_v8_value_.Set(data.GetIsolate(), data.V8Value());
   is_data_dirty_ = true;
-  origin_ = origin;
+  potentially_invalid_origin_serialization_ = origin;
+  origin_ = SecurityOrigin::CreateFromString(origin);
   last_event_id_ = last_event_id;
   source_ = source;
   if (ports.empty()) {
@@ -250,7 +257,7 @@
     bool bubbles,
     bool cancelable,
     scoped_refptr<SerializedScriptValue> data,
-    const String& origin,
+    scoped_refptr<const SecurityOrigin> origin,
     MessageOriginKind message_origin_kind,
     const String& last_event_id,
     EventTarget* source,
@@ -267,7 +274,7 @@
       SerializedScriptValue::Unpack(std::move(data));
   is_data_dirty_ = true;
   data_is_from_untrusted_source_ = message_origin_kind == kMessageIsCrossOrigin;
-  origin_ = origin;
+  origin_ = std::move(origin);
   last_event_id_ = last_event_id;
   source_ = source;
   ports_ = ports;
@@ -282,7 +289,7 @@
                                     bool bubbles,
                                     bool cancelable,
                                     const String& data,
-                                    const String& origin,
+                                    scoped_refptr<const SecurityOrigin> origin,
                                     const String& last_event_id,
                                     EventTarget* source,
                                     GCedMessagePortArray* ports) {
@@ -294,7 +301,7 @@
   data_type_ = kDataTypeString;
   data_as_string_ = data;
   is_data_dirty_ = true;
-  origin_ = origin;
+  origin_ = std::move(origin);
   last_event_id_ = last_event_id;
   source_ = source;
   ports_ = ports;
@@ -309,18 +316,16 @@
   // https://github.com/mikewest/incentivize-origin-checks/.
   if (should_measure_data_access_before_origin_) {
     if (ExecutionContext* context = ExecutionContext::From(script_state)) {
-      scoped_refptr<SecurityOrigin> sending_origin =
-          SecurityOrigin::CreateFromString(origin_);
       const SecurityOrigin* receiving_origin = context->GetSecurityOrigin();
-      if (sending_origin->IsSameOriginWith(receiving_origin)) {
-        UseCounter::Count(context,
-                          WebFeature::kMessageEventDataBeforeSameOrigin);
-      } else if (sending_origin->IsSameSiteWith(receiving_origin)) {
-        UseCounter::Count(context,
-                          WebFeature::kMessageEventDataBeforeSameSiteOrigin);
-      } else if (sending_origin->IsOpaque()) {
+      if (!origin_ || origin_->IsOpaque()) {
         UseCounter::Count(context,
                           WebFeature::kMessageEventDataBeforeOpaqueOrigin);
+      } else if (origin_->IsSameOriginWith(receiving_origin)) {
+        UseCounter::Count(context,
+                          WebFeature::kMessageEventDataBeforeSameOrigin);
+      } else if (origin_->IsSameSiteWith(receiving_origin)) {
+        UseCounter::Count(context,
+                          WebFeature::kMessageEventDataBeforeSameSiteOrigin);
       } else {
         UseCounter::Count(context,
                           WebFeature::kMessageEventDataBeforeCrossSiteOrigin);
@@ -385,10 +390,16 @@
   return ScriptValue(isolate, value);
 }
 
-const String& MessageEvent::originForBindings() {
+String MessageEvent::originForBindings() {
   data_is_from_untrusted_source_ = false;
   should_measure_data_access_before_origin_ = false;
-  return origin();
+  if (!potentially_invalid_origin_serialization_.IsNull()) {
+    return potentially_invalid_origin_serialization_;
+  }
+
+  // If no origin was provided (e.g. we're generating this event via
+  // `MessagePort.postMessage`), then we'll serialize to the empty string.
+  return origin_ ? origin_->ToString() : "";
 }
 
 const AtomicString& MessageEvent::InterfaceName() const {
diff --git a/third_party/blink/renderer/core/events/message_event.h b/third_party/blink/renderer/core/events/message_event.h
index 037ab1b..3795d37b 100644
--- a/third_party/blink/renderer/core/events/message_event.h
+++ b/third_party/blink/renderer/core/events/message_event.h
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
 #include "third_party/blink/renderer/platform/bindings/v8_external_memory_accounter.h"
 #include "third_party/blink/renderer/platform/bindings/v8_private_property.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
 namespace blink {
@@ -62,56 +63,69 @@
 
   static MessageEvent* Create() { return MakeGarbageCollected<MessageEvent>(); }
   static MessageEvent* Create(GCedMessagePortArray* ports,
-                              const String& origin,
+                              scoped_refptr<const SecurityOrigin> origin,
                               const String& last_event_id,
                               EventTarget* source) {
-    return MakeGarbageCollected<MessageEvent>(origin, last_event_id, source,
-                                              ports);
+    return MakeGarbageCollected<MessageEvent>(std::move(origin), last_event_id,
+                                              source, ports);
   }
   static MessageEvent* Create(GCedMessagePortArray* ports,
                               scoped_refptr<SerializedScriptValue> data,
-                              const String& origin,
+                              scoped_refptr<const SecurityOrigin> origin,
                               MessageOriginKind message_origin_kind,
                               const String& last_event_id,
                               EventTarget* source) {
     return MakeGarbageCollected<MessageEvent>(
-        std::move(data), origin, message_origin_kind, last_event_id, source,
-        ports, nullptr);
+        std::move(data), std::move(origin), message_origin_kind, last_event_id,
+        source, ports, nullptr);
   }
   static MessageEvent* Create(GCedMessagePortArray* ports,
                               scoped_refptr<SerializedScriptValue> data,
                               UserActivation* user_activation) {
-    return MakeGarbageCollected<MessageEvent>(std::move(data), String(),
-                                              kMessageIsSameOrigin, String(),
-                                              nullptr, ports, user_activation);
+    return MakeGarbageCollected<MessageEvent>(
+        std::move(data), /*origin=*/nullptr, kMessageIsSameOrigin, String(),
+        nullptr, ports, user_activation);
   }
   static MessageEvent* Create(
       Vector<MessagePortChannel> channels,
       scoped_refptr<SerializedScriptValue> data,
-      const String& origin,
+      scoped_refptr<const SecurityOrigin> origin,
       MessageOriginKind message_origin_kind,
       const String& last_event_id,
       EventTarget* source,
       UserActivation* user_activation,
       mojom::blink::DelegatedCapability delegated_capability) {
     return MakeGarbageCollected<MessageEvent>(
-        std::move(data), origin, message_origin_kind, last_event_id, source,
-        std::move(channels), user_activation, delegated_capability);
+        std::move(data), std::move(origin), message_origin_kind, last_event_id,
+        source, std::move(channels), user_activation, delegated_capability);
   }
-  static MessageEvent* CreateError(const String& origin = String(),
+  static MessageEvent* CreateError() {
+    scoped_refptr<const SecurityOrigin> nullptr_origin;
+    return MakeGarbageCollected<MessageEvent>(std::move(nullptr_origin),
+                                              nullptr);
+  }
+  static MessageEvent* CreateError(const MessageEvent* event) {
+    return MakeGarbageCollected<MessageEvent>(event->GetSecurityOrigin(),
+                                              event->source());
+  }
+  static MessageEvent* CreateError(const SecurityOrigin* origin,
                                    EventTarget* source = nullptr) {
     return MakeGarbageCollected<MessageEvent>(origin, source);
   }
-  static MessageEvent* Create(const String& data,
-                              const String& origin = String()) {
-    return MakeGarbageCollected<MessageEvent>(data, origin);
+  static MessageEvent* Create(
+      const String& data,
+      scoped_refptr<const SecurityOrigin> origin = nullptr) {
+    return MakeGarbageCollected<MessageEvent>(data, std::move(origin));
   }
-  static MessageEvent* Create(Blob* data, const String& origin = String()) {
-    return MakeGarbageCollected<MessageEvent>(data, origin);
+  static MessageEvent* Create(
+      Blob* data,
+      scoped_refptr<const SecurityOrigin> origin = nullptr) {
+    return MakeGarbageCollected<MessageEvent>(data, std::move(origin));
   }
-  static MessageEvent* Create(DOMArrayBuffer* data,
-                              const String& origin = String()) {
-    return MakeGarbageCollected<MessageEvent>(data, origin);
+  static MessageEvent* Create(
+      DOMArrayBuffer* data,
+      scoped_refptr<const SecurityOrigin> origin = nullptr) {
+    return MakeGarbageCollected<MessageEvent>(data, std::move(origin));
   }
   static MessageEvent* Create(const AtomicString& type,
                               const MessageEventInit* initializer,
@@ -119,19 +133,19 @@
 
   MessageEvent();
   MessageEvent(const AtomicString&, const MessageEventInit*);
-  MessageEvent(const String& origin,
+  MessageEvent(scoped_refptr<const SecurityOrigin> origin,
                const String& last_event_id,
                EventTarget* source,
                GCedMessagePortArray*);
   MessageEvent(scoped_refptr<SerializedScriptValue> data,
-               const String& origin,
+               scoped_refptr<const SecurityOrigin> origin,
                MessageOriginKind message_origin_kind,
                const String& last_event_id,
                EventTarget* source,
                GCedMessagePortArray*,
                UserActivation* user_activation);
   MessageEvent(scoped_refptr<SerializedScriptValue> data,
-               const String& origin,
+               scoped_refptr<const SecurityOrigin> origin,
                MessageOriginKind message_origin_kind,
                const String& last_event_id,
                EventTarget* source,
@@ -139,12 +153,15 @@
                UserActivation* user_activation,
                mojom::blink::DelegatedCapability delegated_capability);
   // Creates a "messageerror" event.
-  MessageEvent(const String& origin, EventTarget* source);
-  MessageEvent(const String& data, const String& origin);
-  MessageEvent(Blob* data, const String& origin);
-  MessageEvent(DOMArrayBuffer* data, const String& origin);
+  MessageEvent(scoped_refptr<const SecurityOrigin> origin, EventTarget* source);
+  MessageEvent(const String& data, scoped_refptr<const SecurityOrigin> origin);
+  MessageEvent(Blob* data, scoped_refptr<const SecurityOrigin> origin);
+  MessageEvent(DOMArrayBuffer* data,
+               scoped_refptr<const SecurityOrigin> origin);
   ~MessageEvent() override;
 
+  // This is exposed to JavaScript, and so accepts a serialized |origin| rather
+  // than a `SecurityOrigin`.
   void initMessageEvent(const AtomicString& type,
                         bool bubbles,
                         bool cancelable,
@@ -153,11 +170,14 @@
                         const String& last_event_id,
                         EventTarget* source,
                         MessagePortArray ports);
+
+  // These `initMessageEvent` overrides are not actually implementations of the
+  // bindings-exposed `initMessageEvent` method, and should be renamed.
   void initMessageEvent(const AtomicString& type,
                         bool bubbles,
                         bool cancelable,
                         scoped_refptr<SerializedScriptValue> data,
-                        const String& origin,
+                        scoped_refptr<const SecurityOrigin> origin,
                         MessageOriginKind message_origin_kind,
                         const String& last_event_id,
                         EventTarget* source,
@@ -168,10 +188,11 @@
                         bool bubbles,
                         bool cancelable,
                         const String& data,
-                        const String& origin,
+                        scoped_refptr<const SecurityOrigin> origin,
                         const String& last_event_id,
                         EventTarget* source,
                         GCedMessagePortArray*);
+
   // To evaluate the viability of shipping anything remotely resembling
   // https://github.com/mikewest/incentivize-origin-checks/, this method should
   // be called when `MessageEvent` objects are sent to `Window` via
@@ -182,8 +203,9 @@
 
   ScriptValue data(ScriptState*);
   bool IsDataDirty() const { return is_data_dirty_; }
-  const String& origin() const { return origin_; }
-  const String& originForBindings();
+  // This returns a serialized origin string (which might be "null") to support
+  // JavaScript bindings. Prefer `GetSecurityOrigin()` below for other uses.
+  String originForBindings();
   const String& lastEventId() const { return last_event_id_; }
   EventTarget* source() const { return source_.Get(); }
   MessagePortArray ports();
@@ -225,6 +247,10 @@
 
   void LockToAgentCluster();
 
+  scoped_refptr<const SecurityOrigin> GetSecurityOrigin() const {
+    return origin_;
+  }
+
  private:
   enum DataType {
     kDataTypeNull,  // For "messageerror" events.
@@ -249,7 +275,16 @@
   Member<Blob> data_as_blob_;
   Member<DOMArrayBuffer> data_as_array_buffer_;
   bool is_data_dirty_ = true;
-  String origin_;
+
+  // We hold a `SecurityOrigin` in `origin_` which we'll use for any and all
+  // security checks. We also potentially have to hold a string representing
+  // the serialized origin that was handed to us if the `MessageEvent` was
+  // constructed from JavaScript, as the object is specced to return that
+  // string even if it's not a valid origin serialization. See
+  // https://github.com/whatwg/html/issues/11759 for discussion.
+  scoped_refptr<const SecurityOrigin> origin_;
+  String potentially_invalid_origin_serialization_;
+
   bool should_measure_data_access_before_origin_ = false;
   String last_event_id_;
   Member<EventTarget> source_;
diff --git a/third_party/blink/renderer/core/events/message_event_test.cc b/third_party/blink/renderer/core/events/message_event_test.cc
index 9b34910..5aedd61 100644
--- a/third_party/blink/renderer/core/events/message_event_test.cc
+++ b/third_party/blink/renderer/core/events/message_event_test.cc
@@ -86,7 +86,7 @@
       GetTotalAmountOfExternalAllocatedMemoryForTesting(scope.GetIsolate());
 
   GCedMessagePortArray* ports = MakeGarbageCollected<GCedMessagePortArray>(0);
-  MessageEvent::Create(ports, serialized_script_value, /* origin=*/{},
+  MessageEvent::Create(ports, serialized_script_value, /* origin=*/nullptr,
                        MessageEvent::kMessageIsSameOrigin,
                        /* last_event_id=*/{}, /* source=*/nullptr);
 
diff --git a/third_party/blink/renderer/core/exported/web_dom_message_event.cc b/third_party/blink/renderer/core/exported/web_dom_message_event.cc
index 1c81e551..ec766dbc 100644
--- a/third_party/blink/renderer/core/exported/web_dom_message_event.cc
+++ b/third_party/blink/renderer/core/exported/web_dom_message_event.cc
@@ -44,7 +44,7 @@
   // TODO(esprehn): Chromium always passes empty string for lastEventId, is that
   // right?
   Unwrap<MessageEvent>()->initMessageEvent(
-      event_type_names::kMessage, false, false, message_data, "",
+      event_type_names::kMessage, false, false, message_data, nullptr,
       MessageEvent::kMessageIsSameOrigin, "" /*lastEventId*/, nullptr, {},
       nullptr /*user_activation*/, mojom::blink::DelegatedCapability::kNone);
 }
diff --git a/third_party/blink/renderer/core/fetch/request.cc b/third_party/blink/renderer/core/fetch/request.cc
index eb6d8e6c..46f0d701 100644
--- a/third_party/blink/renderer/core/fetch/request.cc
+++ b/third_party/blink/renderer/core/fetch/request.cc
@@ -185,7 +185,8 @@
   request->SetAttributionReportingSupport(original->AttributionSupport());
   request->SetServiceWorkerRaceNetworkRequestToken(
       original->ServiceWorkerRaceNetworkRequestToken());
-  if (original->HasRetryOptions()) {
+  if (RuntimeEnabledFeatures::FetchRetryEnabled(context) &&
+      original->HasRetryOptions()) {
     request->SetRetryOptions(original->RetryOptions().value());
   }
 
@@ -673,7 +674,8 @@
   if (init->hasKeepalive())
     request->SetKeepalive(init->keepalive());
 
-  if (init->hasRetryOptions()) {
+  if (RuntimeEnabledFeatures::FetchRetryEnabled(execution_context) &&
+      init->hasRetryOptions()) {
     UseCounter::Count(execution_context, WebFeature::kFetchRetry);
     network::FetchRetryOptions options;
     RetryOptions* retry_options = init->retryOptions();
@@ -1260,6 +1262,32 @@
   return MakeGarbageCollected<Request>(script_state, request, headers, signal);
 }
 
+RetryOptions* Request::getRetryOptions() const {
+  if (!request_->HasRetryOptions()) {
+    return nullptr;
+  }
+
+  const network::FetchRetryOptions& network_options =
+      request_->RetryOptions().value();
+  RetryOptions* options = RetryOptions::Create();
+  options->setMaxAttempts(network_options.max_attempts);
+  if (network_options.initial_delay.has_value()) {
+    options->setInitialDelay(
+        network_options.initial_delay.value().InMilliseconds());
+  }
+  if (network_options.backoff_factor.has_value()) {
+    options->setBackoffFactor(network_options.backoff_factor.value());
+  }
+  if (network_options.max_age.has_value()) {
+    options->setMaxAge(network_options.max_age->InMilliseconds());
+  }
+  options->setRetryAfterUnload(network_options.retry_after_unload);
+  options->setRetryNonIdempotent(network_options.retry_non_idempotent);
+  options->setRetryOnlyIfServerUnreached(
+      network_options.retry_only_if_server_unreached);
+  return options;
+}
+
 FetchRequestData* Request::PassRequestData(ScriptState* script_state,
                                            ExceptionState& exception_state) {
   DCHECK(!IsBodyUsed());
diff --git a/third_party/blink/renderer/core/fetch/request.h b/third_party/blink/renderer/core/fetch/request.h
index d3d67f6..cfdd15b5 100644
--- a/third_party/blink/renderer/core/fetch/request.h
+++ b/third_party/blink/renderer/core/fetch/request.h
@@ -28,6 +28,7 @@
 class BodyStreamBuffer;
 class ExceptionState;
 class RequestInit;
+class RetryOptions;
 class V8ReferrerPolicy;
 class V8RequestDestination;
 class V8RequestCache;
@@ -95,6 +96,8 @@
   // From Request.idl:
   // This function must be called with entering an appropriate V8 context.
   Request* clone(ScriptState*, ExceptionState&);
+  // Returns the retry options set on the request if exists.
+  RetryOptions* getRetryOptions() const;
 
   FetchRequestData* PassRequestData(ScriptState*, ExceptionState&);
   mojom::blink::FetchAPIRequestPtr CreateFetchAPIRequest() const;
diff --git a/third_party/blink/renderer/core/fetch/request.idl b/third_party/blink/renderer/core/fetch/request.idl
index cbf6c54..bd6904c6 100644
--- a/third_party/blink/renderer/core/fetch/request.idl
+++ b/third_party/blink/renderer/core/fetch/request.idl
@@ -75,6 +75,8 @@
     [MeasureAs=RequestIsHistoryNavigation] readonly attribute boolean isHistoryNavigation;
     [RaisesException, CallWith=ScriptState, NewObject] Request clone();
 
+    [RuntimeEnabled=FetchRetry] RetryOptions? getRetryOptions();
+
     [Affects=Everything, RuntimeEnabled=FetchUploadStreaming] readonly attribute ReadableStream? body;
 };
 
diff --git a/third_party/blink/renderer/core/fetch/request_test.cc b/third_party/blink/renderer/core/fetch/request_test.cc
index cf619661..15354d0a 100644
--- a/third_party/blink/renderer/core/fetch/request_test.cc
+++ b/third_party/blink/renderer/core/fetch/request_test.cc
@@ -7,14 +7,17 @@
 #include <memory>
 #include <utility>
 
+#include "base/test/scoped_feature_list.h"
 #include "services/network/public/mojom/fetch_api.mojom-blink.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/blink/public/common/features_generated.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
 #include "third_party/blink/public/platform/web_url_request.h"
 #include "third_party/blink/renderer/bindings/core/v8/to_v8_traits.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_request_destination.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_request_init.h"
+#include "third_party/blink/renderer/bindings/core/v8/v8_retry_options.h"
 #include "third_party/blink/renderer/core/fileapi/blob.h"
 #include "third_party/blink/renderer/core/html/forms/form_data.h"
 #include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
@@ -275,4 +278,80 @@
   EXPECT_EQ(url_with_fragment, fetch_api_request->url);
 }
 
+TEST(RequestRetryOptionsTest, RetryOptionsEnabledNoOptionsSet) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(blink::features::kFetchRetry);
+  test::TaskEnvironment task_environment;
+  V8TestingScope scope;
+
+  Request* request = Request::Create(
+      scope.GetScriptState(), "https://example.com", scope.GetExceptionState());
+  ASSERT_FALSE(scope.GetExceptionState().HadException());
+
+  EXPECT_EQ(request->getRetryOptions(), nullptr);
+}
+
+TEST(RequestRetryOptionsTest, RetryOptionsEnabledWithOptionsSet) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(blink::features::kFetchRetry);
+  test::TaskEnvironment task_environment;
+  V8TestingScope scope;
+
+  RequestInit* init = RequestInit::Create();
+  RetryOptions* retry_options = RetryOptions::Create();
+  retry_options->setMaxAttempts(5);
+  retry_options->setInitialDelay(100);
+  retry_options->setBackoffFactor(2.5);
+  retry_options->setMaxAge(5000);
+  retry_options->setRetryAfterUnload(true);
+  retry_options->setRetryNonIdempotent(true);
+  retry_options->setRetryOnlyIfServerUnreached(true);
+  init->setRetryOptions(retry_options);
+
+  Request* request =
+      Request::Create(scope.GetScriptState(), "https://example.com", init,
+                      scope.GetExceptionState());
+  ASSERT_FALSE(scope.GetExceptionState().HadException());
+
+  RetryOptions* result = request->getRetryOptions();
+  ASSERT_NE(result, nullptr);
+  EXPECT_EQ(result->maxAttempts(), 5u);
+  EXPECT_TRUE(result->hasInitialDelay());
+  EXPECT_EQ(result->initialDelay(), 100u);
+  EXPECT_TRUE(result->hasBackoffFactor());
+  EXPECT_EQ(result->backoffFactor(), 2.5);
+  EXPECT_EQ(result->maxAge(), 5000u);
+  EXPECT_TRUE(result->retryAfterUnload());
+  EXPECT_TRUE(result->retryNonIdempotent());
+  EXPECT_TRUE(result->retryOnlyIfServerUnreached());
+}
+
+TEST(RequestRetryOptionsTest, RetryOptionsEnabledWithPartialOptionsSet) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(blink::features::kFetchRetry);
+  test::TaskEnvironment task_environment;
+  V8TestingScope scope;
+
+  RequestInit* init = RequestInit::Create();
+  RetryOptions* retry_options = RetryOptions::Create();
+  retry_options->setMaxAttempts(2);
+  retry_options->setMaxAge(2000);
+  init->setRetryOptions(retry_options);
+
+  Request* request =
+      Request::Create(scope.GetScriptState(), "https://example.com", init,
+                      scope.GetExceptionState());
+  ASSERT_FALSE(scope.GetExceptionState().HadException());
+
+  RetryOptions* result = request->getRetryOptions();
+  ASSERT_NE(result, nullptr);
+  EXPECT_EQ(result->maxAttempts(), 2u);
+  EXPECT_FALSE(result->hasInitialDelay());
+  EXPECT_FALSE(result->hasBackoffFactor());
+  EXPECT_EQ(result->maxAge(), 2000u);
+  EXPECT_FALSE(result->retryAfterUnload());
+  EXPECT_FALSE(result->retryNonIdempotent());
+  EXPECT_FALSE(result->retryOnlyIfServerUnreached());
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 2e4dc6e..a8f76819 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -1265,7 +1265,7 @@
   // local dispatch.
   MessageEvent* event = MessageEvent::Create(
       std::move(posted_message->channels), std::move(posted_message->data),
-      posted_message->source_origin->ToString(), message_origin_kind, String(),
+      std::move(posted_message->source_origin), message_origin_kind, String(),
       posted_message->source, posted_message->user_activation,
       posted_message->delegated_capability);
 
@@ -1357,11 +1357,11 @@
     }
   }
 
+  scoped_refptr<const SecurityOrigin> sender_origin =
+      event->GetSecurityOrigin();
   if (event->IsOriginCheckRequiredToAccessData()) {
-    scoped_refptr<SecurityOrigin> sender_security_origin =
-        SecurityOrigin::CreateFromString(event->origin());
-    if (!sender_security_origin->IsSameOriginWith(GetSecurityOrigin())) {
-      event = MessageEvent::CreateError(event->origin(), event->source());
+    if (!sender_origin->IsSameOriginWith(GetSecurityOrigin())) {
+      event = MessageEvent::CreateError(event);
     }
   }
   if (event->IsLockedToAgentCluster()) {
@@ -1369,10 +1369,8 @@
       UseCounter::Count(
           this,
           WebFeature::kMessageEventSharedArrayBufferDifferentAgentCluster);
-      event = MessageEvent::CreateError(event->origin(), event->source());
+      event = MessageEvent::CreateError(event);
     } else {
-      scoped_refptr<SecurityOrigin> sender_origin =
-          SecurityOrigin::CreateFromString(event->origin());
       if (!sender_origin->IsSameOriginWith(GetSecurityOrigin())) {
         UseCounter::Count(
             this, WebFeature::kMessageEventSharedArrayBufferSameAgentCluster);
@@ -1384,7 +1382,7 @@
   }
 
   if (!event->CanDeserializeIn(this)) {
-    event = MessageEvent::CreateError(event->origin(), event->source());
+    event = MessageEvent::CreateError(event);
   }
 
   if (event->delegatedCapability() ==
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc
index dc1464a..06053c5 100644
--- a/third_party/blink/renderer/core/frame/local_frame.cc
+++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -3842,18 +3842,19 @@
 
 void LocalFrame::PostMessageEvent(
     const std::optional<RemoteFrameToken>& source_frame_token,
-    const String& source_origin,
-    const String& target_origin,
+    const String& serialized_source_origin,
+    const String& serialized_target_origin,
     BlinkTransferableMessage message) {
   probe::FrameRelatedTask probe(DomWindow());
   TRACE_EVENT0("blink", "LocalFrame::PostMessageEvent");
   RemoteFrame* source_frame = SourceFrameForOptionalToken(source_frame_token);
 
-  // We must pass in the target_origin to do the security check on this side,
-  // since it may have changed since the original postMessage call was made.
-  scoped_refptr<SecurityOrigin> target_security_origin;
-  if (!target_origin.empty()) {
-    target_security_origin = SecurityOrigin::CreateFromString(target_origin);
+  // We must pass in the serialized_target_origin to do the security check on
+  // this side, since it may have changed since the original postMessage call
+  // was made.
+  scoped_refptr<const SecurityOrigin> target_origin;
+  if (!serialized_target_origin.empty()) {
+    target_origin = SecurityOrigin::CreateFromString(serialized_target_origin);
   }
 
   // Preparation of the MessageEvent.
@@ -3878,9 +3879,17 @@
         message.user_activation->was_active);
   }
 
+  // `serialized_source_origin` will be an empty string for certain calls
+  // initiated from WebView; we handle that as a nullptr, not an opaque origin.
+  // See `org.chromium.android_webview.AwContents.postMessageToMainFrame()`.
+  scoped_refptr<const SecurityOrigin> source_origin;
+  if (!serialized_source_origin.empty()) {
+    source_origin = SecurityOrigin::CreateFromString(serialized_source_origin);
+  }
+
   const MessageEvent::MessageOriginKind message_origin_kind =
-      SecurityOrigin::CreateFromString(source_origin)
-              ->IsSameOriginWith(DomWindow()->GetSecurityOrigin())
+      (source_origin &&
+       source_origin->IsSameOriginWith(DomWindow()->GetSecurityOrigin()))
           ? MessageEvent::kMessageIsSameOrigin
           : MessageEvent::kMessageIsCrossOrigin;
   message_event->initMessageEvent(
@@ -3895,7 +3904,7 @@
 
   // Finally dispatch the message to the DOM Window.
   DomWindow()->DispatchMessageEventWithOriginCheck(
-      target_security_origin.get(), message_event,
+      target_origin.get(), message_event,
       MakeGarbageCollected<SourceLocation>(String(), String(), 0, 0, nullptr),
       message.sender_agent_cluster_id);
 }
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h
index 71eb863..6ea33fee 100644
--- a/third_party/blink/renderer/core/frame/local_frame.h
+++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -769,10 +769,12 @@
   void AddInspectorIssue(AuditsIssue issue);
   void SaveImageAt(const gfx::Point& window_point);
   void AdvanceFocusForIME(mojom::blink::FocusType focus_type);
+  // TODO(449581913): This, along with the mojo interface and its callers,
+  // should work with `SecurityOrigin` objects rather than strings.
   void PostMessageEvent(
       const std::optional<RemoteFrameToken>& source_frame_token,
-      const String& source_origin,
-      const String& target_origin,
+      const String& serialized_source_origin,
+      const String& serialized_target_origin,
       BlinkTransferableMessage message);
 
   void SetScaleFactor(float scale);
diff --git a/third_party/blink/renderer/core/page/focus_controller.cc b/third_party/blink/renderer/core/page/focus_controller.cc
index c0893d6..e18d49a 100644
--- a/third_party/blink/renderer/core/page/focus_controller.cc
+++ b/third_party/blink/renderer/core/page/focus_controller.cc
@@ -336,9 +336,15 @@
 }
 
 const Element* InclusiveAncestorOpenPopoverWithInvoker(const Element* element) {
-  for (; element; element = FlatTreeTraversal::ParentElement(*element)) {
-    if (InvokerForOpenPopover(element)) {
-      return element;  // Return the popover
+  for (const Element* current = element; current;
+       current = FlatTreeTraversal::ParentElement(*current)) {
+    if (RuntimeEnabledFeatures::
+            OpenPopoverInvokerRestrictToSameTreeScopeEnabled() &&
+        element->GetTreeScope() != current->GetTreeScope()) {
+      break;
+    }
+    if (InvokerForOpenPopover(current)) {
+      return current;  // Return the popover
     }
   }
   return nullptr;
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller.cc b/third_party/blink/renderer/core/page/focusgroup_controller.cc
index 774bfc2..8858b8675 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller.cc
@@ -63,387 +63,40 @@
 
   // Only allow linear focusgroup navigation when the focus is on a focusgroup
   // item.
-  if (!utils::IsFocusgroupItem(initial_element))
-    return false;
-
-  if (utils::IsDirectionForward(direction)) {
-    return AdvanceForward(initial_element, direction);
-  } else {
-    DCHECK(utils::IsDirectionBackward(direction));
-    return AdvanceBackward(initial_element, direction);
-  }
-}
-
-// static
-bool FocusgroupController::AdvanceForward(Element* initial_element,
-                                          FocusgroupDirection direction) {
-  DCHECK(initial_element);
-  DCHECK(utils::IsDirectionForward(direction));
-  DCHECK(utils::IsFocusgroupItem(initial_element));
-
-  Element* nearest_focusgroup = utils::FindNearestFocusgroupAncestor(
+  Element* owner = utils::FindNearestFocusgroupAncestor(
       initial_element, FocusgroupType::kLinear);
-  // We only allow focusgroup navigation when we are inside of a focusgroup.
-  if (!nearest_focusgroup)
+  if (!owner) {
     return false;
-
-  // When the focusgroup we're in doesn't support the axis of the arrow key
-  // pressed, it might still be able to descend so we can't return just yet.
-  // However, if it can't descend, we should return right away.
-  bool can_only_descend = !utils::IsAxisSupported(
-      nearest_focusgroup->GetFocusgroupData().flags, direction);
-
-  // We use the first element after the focusgroup we're in, excluding its
-  // subtree, as a shortcut to determine if we exited the current focusgroup
-  // without having to compute the current focusgroup ancestor on every pass.
-  Element* first_element_after_focusgroup =
-      utils::NextElement(nearest_focusgroup, /* skip_subtree */ true);
-
-  Element* current = initial_element;
-
-  while (true) {
-    // 1. Determine whether to descend in other focusgroup.
-    bool skip_subtree = false;
-    FocusgroupData current_data = current->GetFocusgroupData();
-    bool descended = false;
-    if (current_data.behavior != FocusgroupBehavior::kNoBehavior) {
-      // When we're on a non-extending focusgroup, we shouldn't go into it. Same
-      // for when we're at the root of an extending focusgroup that doesn't
-      // support the axis of the arrow pressed.
-      if (!(current_data.flags & FocusgroupFlags::kExtend) ||
-          !utils::IsAxisSupported(current_data.flags, direction)) {
-        skip_subtree = true;
-      } else {
-        nearest_focusgroup = current;
-        first_element_after_focusgroup =
-            utils::NextElement(nearest_focusgroup, /* skip_subtree */ true);
-        descended = true;
-      }
-    }
-
-    // See comment where |can_only_descend| is declared.
-    if (can_only_descend && !descended)
-      return false;
-
-    // 2. Move |current| to the next element.
-    current = utils::NextElement(current, skip_subtree);
-
-    // 3. When |current| is located on the next element after the focusgroup
-    // we're currently in, it means that we just exited the current
-    // focusgroup we were in. We need to validate that we have the right to
-    // exit it, since there are a few cases that might prevent us from going
-    // to the next element. See the function `CanExitFocusgroupForward` for more
-    // details about when we shouldn't allow exiting the current focusgroup.
-    //
-    // When this is true, we have exited the current focusgroup we were in. If
-    // we were in an extending focusgroup, we should advance to the next item in
-    // the parent focusgroup if the axis is supported.
-    if (current && current == first_element_after_focusgroup) {
-      if (CanExitFocusgroupForward(nearest_focusgroup, current, direction)) {
-        nearest_focusgroup = utils::FindNearestFocusgroupAncestor(
-            current, FocusgroupType::kLinear);
-        first_element_after_focusgroup =
-            utils::NextElement(nearest_focusgroup, /* skip_subtree */ true);
-      } else {
-        current = nullptr;
-      }
-    }
-
-    // 4. When |current| is null, try to wrap.
-    if (!current) {
-      current = WrapForward(nearest_focusgroup, direction);
-
-      if (!current) {
-        // We couldn't wrap and we're out of options.
-        break;
-      }
-    }
-
-    // Avoid looping infinitely by breaking when the next logical element is the
-    // one we started on.
-    if (current == initial_element)
-      break;
-
-    // 5. |current| is finally on the next element. Focus it if it's one that
-    // should be part of the focusgroup, otherwise continue the loop until it
-    // finds the next item or can't find any.
-    if (utils::IsFocusgroupItem(current)) {
-      Focus(current, direction);
-      return true;
-    }
   }
-  return false;
-}
-
-// static
-//
-// This function validates that we can exit the current focusgroup by calling
-// `CanExitFocusgroupForwardRecursive`, which validates that all ancestor
-// focusgroups can be exited safely. We need to validate that the ancestor
-// focusgroups can be exited only if they are exited. Here are the key scenarios
-// where we prohibit a focusgroup from being exited: a. If we're going to an
-// element that isn't part of a focusgroup. b. If we're exiting a root
-// focusgroup (one that doesn't extend). c. If we're going to a focusgroup that
-// doesn't support the direction. d. If we're exiting a focusgroup that should
-// wrap.
-bool FocusgroupController::CanExitFocusgroupForward(
-    const Element* exiting_focusgroup,
-    const Element* next_element,
-    FocusgroupDirection direction) {
-  DCHECK(exiting_focusgroup);
-  DCHECK(next_element);
-  DCHECK(utils::NextElement(exiting_focusgroup, /*skip_subtree */ true) ==
-         next_element);
-
-  const Element* next_element_focusgroup = utils::FindNearestFocusgroupAncestor(
-      next_element, FocusgroupType::kLinear);
-  if (!next_element_focusgroup)
+  if (!utils::IsFocusgroupItemWithOwner(initial_element, owner)) {
     return false;
+  }
 
-  return CanExitFocusgroupForwardRecursive(
-      exiting_focusgroup, next_element, direction,
-      utils::WrapsInDirection(exiting_focusgroup->GetFocusgroupData().flags,
-                              direction));
-}
+  FocusgroupData owner_data = owner->GetFocusgroupData();
+  if (!utils::IsAxisSupported(owner_data.flags, direction)) {
+    // Axis not supported; no navigation allowed.
+    return false;
+  }
 
-// static
-bool FocusgroupController::CanExitFocusgroupForwardRecursive(
-    const Element* exiting_focusgroup,
-    const Element* next_element,
-    FocusgroupDirection direction,
-    bool check_wrap) {
-  DCHECK(exiting_focusgroup);
-  DCHECK(next_element);
-
-  // When this is true, we are not exiting |exiting_focusgroup| and thus won't
-  // be exiting any ancestor focusgroup.
-  if (utils::NextElement(exiting_focusgroup, /* skip_subtree */ true) !=
-      next_element) {
+  // Attempt to find next candidate in chosen direction.
+  Element* candidate =
+      utils::NextFocusgroupItemInDirection(owner, initial_element, direction);
+  if (candidate) {
+    Focus(candidate, direction);
     return true;
   }
 
-  FocusgroupData exiting_focusgroup_data =
-      exiting_focusgroup->GetFocusgroupData();
-  DCHECK(exiting_focusgroup_data.behavior != FocusgroupBehavior::kNoBehavior);
-
-  if (!(exiting_focusgroup_data.flags & FocusgroupFlags::kExtend)) {
+  // No candidate found – wrap if allowed for the given direction.
+  if (!utils::WrapsInDirection(owner_data.flags, direction)) {
     return false;
   }
-
-  const Element* parent_focusgroup = utils::FindNearestFocusgroupAncestor(
-      exiting_focusgroup, FocusgroupType::kLinear);
-  FocusgroupData parent_focusgroup_data =
-      parent_focusgroup ? parent_focusgroup->GetFocusgroupData()
-                        : FocusgroupData{FocusgroupBehavior::kNoBehavior,
-                                         FocusgroupFlags::kNone};
-
-  DCHECK(utils::IsAxisSupported(exiting_focusgroup_data.flags, direction));
-  if (!utils::IsAxisSupported(parent_focusgroup_data.flags, direction)) {
+  Element* wrap_item =
+      utils::WrappedFocusgroupCandidate(owner, initial_element, direction);
+  if (!wrap_item) {
     return false;
   }
-
-  if (check_wrap) {
-    DCHECK(utils::WrapsInDirection(exiting_focusgroup_data.flags, direction));
-    if (!utils::WrapsInDirection(parent_focusgroup_data.flags, direction)) {
-      return false;
-    }
-  }
-
-  return CanExitFocusgroupForwardRecursive(parent_focusgroup, next_element,
-                                           direction, check_wrap);
-}
-
-// static
-Element* FocusgroupController::WrapForward(Element* nearest_focusgroup,
-                                           FocusgroupDirection direction) {
-  // 1. Get the focusgroup that initiates the wrapping scope in this axis. We
-  // need to go up to the root-most focusgroup in order to be able to get the
-  // "next" element, ie. the first item of this focusgroup. Stopping at the
-  // first focusgroup that supports wrapping in that axis would break the
-  // extend behavior and return the wrong element.
-  Element* focusgroup_wrap_root = nullptr;
-  for (Element* focusgroup = nearest_focusgroup; focusgroup;
-       focusgroup = utils::FindNearestFocusgroupAncestor(
-           focusgroup, FocusgroupType::kLinear)) {
-    FocusgroupData data = focusgroup->GetFocusgroupData();
-    if (!utils::WrapsInDirection(data.flags, direction)) {
-      break;
-    }
-
-    focusgroup_wrap_root = focusgroup;
-
-    if (!(data.flags & FocusgroupFlags::kExtend)) {
-      break;
-    }
-  }
-
-  // 2. There are no next valid element and we can't wrap - `AdvanceForward`
-  // should fail.
-  if (!focusgroup_wrap_root)
-    return nullptr;
-
-  // 3. Set the focus on the first element within the subtree of the
-  // current focusgroup.
-  return utils::NextElement(focusgroup_wrap_root, /* skip_subtree */ false);
-}
-
-// static
-bool FocusgroupController::AdvanceBackward(Element* initial_element,
-                                           FocusgroupDirection direction) {
-  DCHECK(initial_element);
-  DCHECK(utils::IsDirectionBackward(direction));
-  DCHECK(utils::IsFocusgroupItem(initial_element));
-
-  // 1. Validate that we're in a focusgroup. Keep the reference to the current
-  // focusgroup we're in since we'll use it if we need to wrap.
-  Element* initial_focusgroup = utils::FindNearestFocusgroupAncestor(
-      initial_element, FocusgroupType::kLinear);
-  if (!initial_focusgroup)
-    return false;
-  bool can_only_ascend = !utils::IsAxisSupported(
-      initial_focusgroup->GetFocusgroupData().flags, direction);
-
-  Element* current = initial_element;
-  Element* parent = FlatTreeTraversal::ParentElement(*current);
-  while (true) {
-    // 2. To find the previous focusgroup item, we start by getting the previous
-    // element in preorder traversal. We are guaranteed to have a non-null
-    // previous element since, below, we return as soon as the current as
-    // reached the root most focusgroup.
-    current = utils::PreviousElement(current);
-    DCHECK(current);
-
-    // 3. When going to the previous element in preorder traversal, there are 3
-    // possible cases. We either moved:
-    // i. to the sibling of the last element;
-    // ii. to a descendant of the sibling of the last element;
-    // iii. to the parent of the last element.
-    //
-    // When in (i), we know we are still part of the focusgroup the last element
-    // was in. We can assume that the value of |current| is valid.
-    //
-    // When in (ii), we need to validate that we didn't descend into a different
-    // focusgroup. `utils::AdjustElementOutOfUnrelatedFocusgroup` takes care of
-    // that and, if it did descend in a separate focusgroup, it will return an
-    // adjusted value for |current| out of that other focusgroup.
-    //
-    // When in (iii), we first need to try to wrap. If it succeeded, the
-    // |current| element will be located on the last element of the focusgroup
-    // and might have descended into another focusgroup. Once again, we'll need
-    // to validate and potentially adjust the element using
-    // `utils::AdjustElementOutOfUnrelatedFocusgroup`. If we can't wrap, we
-    // must validate that |current|, which is now located on its parent, is
-    // still part of the focusgroup.
-    bool ascended = false;
-    if (current == parent) {
-      // Case (iii).
-      Element* wrap_result = WrapBackward(current, direction);
-      if (wrap_result) {
-        current = utils::AdjustElementOutOfUnrelatedFocusgroup(
-            wrap_result, parent, direction);
-        parent = FlatTreeTraversal::ParentElement(*current);
-      } else {
-        // Wrapping wasn't an option. At this point, we can only attempt to
-        // ascend to the parent.
-
-        // We can't ascend out of a non-extending focusgroup.
-        FocusgroupData current_data = current->GetFocusgroupData();
-        if (current_data.behavior != FocusgroupBehavior::kNoBehavior &&
-            !(current_data.flags & FocusgroupFlags::kExtend)) {
-          return false;
-        }
-
-        // We can't ascend if there is no focusgroup ancestor.
-        Element* parent_focusgroup = utils::FindNearestFocusgroupAncestor(
-            current, FocusgroupType::kLinear);
-        if (!parent_focusgroup)
-          return false;
-
-        // We can't ascend if the parent focusgroup doesn't support the axis of
-        // the arrow key pressed.
-        if (!utils::IsAxisSupported(
-                parent_focusgroup->GetFocusgroupData().flags, direction)) {
-          return false;
-        }
-
-        // At this point, we are certain that we can ascend to the parent
-        // element.
-        ascended = true;
-        parent = FlatTreeTraversal::ParentElement(*parent);
-        // No need to check if the new |parent| is null or not because, if that
-        // was the case, the check above for the |parent_focusgroup| would have
-        // failed and returned early.
-      }
-    } else if (FlatTreeTraversal::ParentElement(*current) != parent) {
-      // Case (ii).
-      current = utils::AdjustElementOutOfUnrelatedFocusgroup(current, parent,
-                                                             direction);
-      parent = FlatTreeTraversal::ParentElement(*current);
-    }
-
-    // Avoid looping infinitely by breaking when the previous logical element is
-    // the one we started on.
-    if (current == initial_element)
-      break;
-
-    // 4. At this point, we know that |current| is a valid element in our
-    // focusgroup. The only thing left to do is set the focus on the element if
-    // it's a focusgroup item and we're allowed to do so. If not, we'll stay in
-    // the loop until we find a suitable previous focusgroup item.
-    if (!utils::IsFocusgroupItem(current))
-      continue;
-
-    // 5. When in a focusgroup that doesn't support the arrow axis, we still
-    // iterate over the previous elements in the hopes of ascending to another
-    // focusgroup. Ascending from a focusgroup that doesn't support the arrow
-    // axis is permitted only when the focused element was the first focusgroup
-    // item in a focusgroup.
-    if (can_only_ascend && !ascended) {
-      // Here, since we found out that there was a previous item, ascending is
-      // not an option anymore so we break out of the loop to indicate that
-      // advancing backward wasn't possible.
-      break;
-    }
-
-    Focus(current, direction);
-    return true;
-  }
-
-  return false;
-}
-
-// static
-Element* FocusgroupController::WrapBackward(Element* current,
-                                            FocusgroupDirection direction) {
-  DCHECK(current);
-  DCHECK(utils::IsDirectionBackward(direction));
-
-  FocusgroupData current_data = current->GetFocusgroupData();
-
-  if (current_data.behavior == FocusgroupBehavior::kNoBehavior) {
-    return nullptr;
-  }
-
-  if (!utils::IsAxisSupported(current_data.flags, direction)) {
-    return nullptr;
-  }
-
-  if (!utils::WrapsInDirection(current_data.flags, direction)) {
-    return nullptr;
-  }
-
-  // Don't wrap when on a focusgroup that got its wrapping behavior in this
-  // axis from its parent focusgroup - that other focusgroup will handle the
-  // wrapping once we'll reach it.
-  Element* parent_focusgroup =
-      utils::FindNearestFocusgroupAncestor(current, FocusgroupType::kLinear);
-  if (current_data.flags & FocusgroupFlags::kExtend && parent_focusgroup &&
-      utils::WrapsInDirection(parent_focusgroup->GetFocusgroupData().flags,
-                              direction)) {
-    return nullptr;
-  }
-
-  return utils::LastElementWithin(current);
+  Focus(wrap_item, direction);
+  return true;
 }
 
 // static
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller.h b/third_party/blink/renderer/core/page/focusgroup_controller.h
index 71f5872..e35f65a 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller.h
+++ b/third_party/blink/renderer/core/page/focusgroup_controller.h
@@ -29,24 +29,6 @@
   // moved the focus.
   static bool Advance(Element* initial_element, FocusgroupDirection direction);
 
-  static bool AdvanceForward(Element* initial_element,
-                             FocusgroupDirection direction);
-  static bool CanExitFocusgroupForward(const Element* exiting_focusgroup,
-                                       const Element* entering_focusgroup,
-                                       FocusgroupDirection direction);
-  static bool CanExitFocusgroupForwardRecursive(
-      const Element* exiting_focusgroup,
-      const Element* next_element,
-      FocusgroupDirection direction,
-      bool check_wrap);
-  static Element* WrapForward(Element* nearest_focusgroup,
-                              FocusgroupDirection direction);
-
-  static bool AdvanceBackward(Element* initial_element,
-                              FocusgroupDirection direction);
-  static Element* WrapBackward(Element* nearest_focusgroup,
-                               FocusgroupDirection direction);
-
   static bool AdvanceInGrid(Element* initial_element,
                             Element* grid_root,
                             FocusgroupDirection direction);
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_test.cc b/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
index 391ce38..ab1b4c0 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_test.cc
@@ -248,130 +248,6 @@
                                       FocusgroupDirection::kForwardBlock));
 }
 
-TEST_F(FocusgroupControllerTest, FocusgroupExtendsInAxis) {
-  FocusgroupFlags focusgroup = FocusgroupFlags::kNone;
-  FocusgroupFlags extending_focusgroup = FocusgroupFlags::kNone;
-
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                              FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  focusgroup = static_cast<FocusgroupFlags>(FocusgroupFlags::kInline |
-                                            FocusgroupFlags::kBlock);
-
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                              FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  extending_focusgroup = static_cast<FocusgroupFlags>(FocusgroupFlags::kInline |
-                                                      FocusgroupFlags::kBlock);
-
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                              FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  extending_focusgroup = FocusgroupFlags::kExtend;
-
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                             FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  extending_focusgroup |= FocusgroupFlags::kInline;
-
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                             FocusgroupDirection::kNone));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  extending_focusgroup |= FocusgroupFlags::kBlock;
-
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                             FocusgroupDirection::kNone));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  focusgroup = FocusgroupFlags::kNone;
-  extending_focusgroup = FocusgroupFlags::kExtend | FocusgroupFlags::kInline |
-                         FocusgroupFlags::kBlock;
-
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                              FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  focusgroup |= FocusgroupFlags::kBlock;
-
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                             FocusgroupDirection::kNone));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_FALSE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-
-  focusgroup |= FocusgroupFlags::kInline;
-
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(extending_focusgroup, focusgroup,
-                                             FocusgroupDirection::kNone));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kBackwardBlock));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardInline));
-  ASSERT_TRUE(utils::FocusgroupExtendsInAxis(
-      extending_focusgroup, focusgroup, FocusgroupDirection::kForwardBlock));
-}
-
 TEST_F(FocusgroupControllerTest, FindNearestFocusgroupAncestor) {
   GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
     <div>
@@ -380,7 +256,7 @@
     <div id=fg1 focusgroup="toolbar">
       <span id=item2 tabindex=-1></span>
       <div>
-        <div id=fg2 focusgroup="toolbar extend">
+        <div id=fg2 focusgroup="toolbar">
           <span id=item3 tabindex=-1></span>
           <div>
             <span id=item4></span>
@@ -400,7 +276,7 @@
           </table>
           <div id=fg6-container>
             <template shadowrootmode=open>
-              <div id=fg6 focusgroup="toolbar extend">
+              <div id=fg6 focusgroup="toolbar">
                 <span id=item8 tabindex=-1></span>
               </div>
             </template>
@@ -558,16 +434,17 @@
   ASSERT_EQ(utils::PreviousElement(fg3), item3);
 }
 
-TEST_F(FocusgroupControllerTest, LastElementWithin) {
+TEST_F(FocusgroupControllerTest, LastFocusgroupItemWithin) {
   GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
-    <div id=fg1 focusgroup>
+    <div id=fg1 focusgroup="toolbar">
       <span id=item1></span>
       <span id=item2 tabindex=-1></span>
     </div>
-    <div id=fg2 focusgroup>
+    <div id=fg2 focusgroup="toolbar">
         <template shadowrootmode=open>
           <span id=item3 tabindex=-1></span>
-          <span id=item4></span>
+          <span id=item4 tabindex=-1></span>
+          <span id=item5></span>
         </template>
     </div>
     <span id=item5 tabindex=-1></span>
@@ -582,47 +459,79 @@
   ASSERT_TRUE(item2);
   ASSERT_TRUE(item4);
 
-  ASSERT_EQ(utils::LastElementWithin(fg1), item2);
-  ASSERT_EQ(utils::LastElementWithin(fg2), item4);
-  ASSERT_EQ(utils::LastElementWithin(item4), nullptr);
+  EXPECT_EQ(utils::LastFocusgroupItemWithin(fg1), item2);
+  EXPECT_EQ(utils::LastFocusgroupItemWithin(fg2), item4);
+  EXPECT_EQ(utils::LastFocusgroupItemWithin(item4), nullptr);
 }
 
-TEST_F(FocusgroupControllerTest, IsFocusgroupItem) {
-  GetDocument().body()->SetInnerHTMLWithoutTrustedTypes(R"HTML(
+TEST_F(FocusgroupControllerTest, FirstFocusgroupItemWithin) {
+  GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
     <div id=fg1 focusgroup="toolbar">
-      <span id=item1 tabindex=0></span>
-      <span id=item2></span>
-      <div id=fg2 focusgroup="toolbar extend">
-        <span tabindex=-1></span>
-        <div id=non-fg1 tabindex=-1>
+      <span id=item1></span>
+      <span id=item2 tabindex=-1></span>
+    </div>
+    <div id=fg2 focusgroup="toolbar">
+        <template shadowrootmode=open>
           <span id=item3 tabindex=-1></span>
-        </div>
-      </div>
-      <button id=button1></button>
+          <span id=item4 tabindex=-1></span>
+          <span id=item5></span>
+        </template>
     </div>
   )HTML");
-  auto* item1 = GetElementById("item1");
-  auto* item2 = GetElementById("item2");
-  auto* item3 = GetElementById("item3");
+
   auto* fg1 = GetElementById("fg1");
   auto* fg2 = GetElementById("fg2");
-  auto* non_fg1 = GetElementById("non-fg1");
-  auto* button1 = GetElementById("button1");
-  ASSERT_TRUE(item1);
-  ASSERT_TRUE(item2);
-  ASSERT_TRUE(item3);
   ASSERT_TRUE(fg1);
   ASSERT_TRUE(fg2);
-  ASSERT_TRUE(non_fg1);
-  ASSERT_TRUE(button1);
 
-  ASSERT_TRUE(utils::IsFocusgroupItem(item1));
-  ASSERT_FALSE(utils::IsFocusgroupItem(item2));
-  ASSERT_FALSE(utils::IsFocusgroupItem(item3));
-  ASSERT_FALSE(utils::IsFocusgroupItem(fg1));
-  ASSERT_FALSE(utils::IsFocusgroupItem(fg2));
-  ASSERT_TRUE(utils::IsFocusgroupItem(non_fg1));
-  ASSERT_TRUE(utils::IsFocusgroupItem(button1));
+  auto* item2 = GetElementById("item2");
+  auto* item3 = fg2->GetShadowRoot()->getElementById(AtomicString("item3"));
+  auto* item4 = fg2->GetShadowRoot()->getElementById(AtomicString("item4"));
+
+  ASSERT_TRUE(item2);
+  ASSERT_TRUE(item3);
+  ASSERT_TRUE(item4);
+
+  EXPECT_EQ(utils::FirstFocusgroupItemWithin(fg1), item2);
+  EXPECT_EQ(utils::FirstFocusgroupItemWithin(fg2), item3);
+  EXPECT_EQ(utils::FirstFocusgroupItemWithin(item4), nullptr);
+}
+
+TEST_F(FocusgroupControllerTest, IsFocusgroupItemWithOwner) {
+  GetDocument().body()->SetInnerHTMLWithoutTrustedTypes(R"HTML(
+    <div id=outer_fg focusgroup="toolbar">
+      <span id=outer_item1 tabindex=0></span>
+      <div>
+        <div id=inner_fg focusgroup="toolbar">
+          <span id=inner_item1 tabindex=-1></span>
+          <span id=inner_item2 tabindex=-1></span>
+        </div>
+      </div>
+      <span id=outer_item2 tabindex=-1></span>
+    </div>
+  )HTML");
+  auto* outer_fg = GetElementById("outer_fg");
+  auto* inner_fg = GetElementById("inner_fg");
+  auto* outer_item1 = GetElementById("outer_item1");
+  auto* outer_item2 = GetElementById("outer_item2");
+  auto* inner_item1 = GetElementById("inner_item1");
+  auto* inner_item2 = GetElementById("inner_item2");
+
+  // Outer focusgroup items should belong to outer context.
+  EXPECT_TRUE(utils::IsFocusgroupItemWithOwner(outer_item1, outer_fg));
+  EXPECT_TRUE(utils::IsFocusgroupItemWithOwner(outer_item2, outer_fg));
+
+  // Inner focusgroup items should NOT belong to outer context.
+  EXPECT_FALSE(utils::IsFocusgroupItemWithOwner(inner_item1, outer_fg));
+  EXPECT_FALSE(utils::IsFocusgroupItemWithOwner(inner_item2, outer_fg));
+
+  // Inner focusgroup items should belong to inner context.
+  EXPECT_TRUE(utils::IsFocusgroupItemWithOwner(inner_item1, inner_fg));
+  EXPECT_TRUE(utils::IsFocusgroupItemWithOwner(inner_item2, inner_fg));
+
+  // Outer focusgroup items should NOT belong to inner context.
+  EXPECT_FALSE(utils::IsFocusgroupItemWithOwner(outer_item1, inner_fg));
+  EXPECT_FALSE(utils::IsFocusgroupItemWithOwner(outer_item2, inner_fg));
 }
 
 TEST_F(FocusgroupControllerTest, CellAtIndexInRowBehaviorOnNoCellFound) {
@@ -756,4 +665,76 @@
   ASSERT_EQ(GetDocument().FocusedElement(), item1);
 }
 
+TEST_F(FocusgroupControllerTest, NestedFocusgroupsHaveSeparateScopes) {
+  GetDocument().body()->SetHTMLUnsafeWithoutTrustedTypes(R"HTML(
+    <div id=outer focusgroup="toolbar">
+      <button id=outer1 tabindex=0>Outer 1</button>
+      <button id=outer2 tabindex=-1>Outer 2</button>
+
+      <div id=inner focusgroup="menu">
+        <button id=inner1 tabindex=-1>Inner 1</button>
+        <button id=inner2 tabindex=-1>Inner 2</button>
+        <button id=inner3 tabindex=-1>Inner 3</button>
+      </div>
+
+      <button id=outer3 tabindex=-1>Outer 3</button>
+    </div>
+  )HTML");
+  UpdateAllLifecyclePhasesForTest();
+
+  auto* outer = GetElementById("outer");
+  auto* inner = GetElementById("inner");
+  auto* outer1 = GetElementById("outer1");
+  auto* outer2 = GetElementById("outer2");
+  auto* outer3 = GetElementById("outer3");
+  auto* inner1 = GetElementById("inner1");
+  auto* inner2 = GetElementById("inner2");
+  auto* inner3 = GetElementById("inner3");
+
+  ASSERT_TRUE(outer);
+  ASSERT_TRUE(inner);
+  ASSERT_TRUE(outer1);
+  ASSERT_TRUE(outer2);
+  ASSERT_TRUE(outer3);
+  ASSERT_TRUE(inner1);
+  ASSERT_TRUE(inner2);
+  ASSERT_TRUE(inner3);
+
+  // Verify that the outer elements belong to the outer focusgroup.
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(outer1, FocusgroupType::kLinear),
+      outer);
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(outer2, FocusgroupType::kLinear),
+      outer);
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(outer3, FocusgroupType::kLinear),
+      outer);
+
+  // Verify that the inner elements belong to the inner focusgroup, not the
+  // outer one.
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(inner1, FocusgroupType::kLinear),
+      inner);
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(inner2, FocusgroupType::kLinear),
+      inner);
+  EXPECT_EQ(
+      utils::FindNearestFocusgroupAncestor(inner3, FocusgroupType::kLinear),
+      inner);
+
+  // Verify that NextElement within outer focusgroup skips the inner focusgroup
+  // elements.
+  EXPECT_EQ(utils::NextElement(outer1, /* skip_subtree */ false), outer2);
+  EXPECT_EQ(utils::NextElement(outer2, /* skip_subtree */ false), inner);
+
+  // When we encounter the inner focusgroup container, NextElement should skip
+  // its subtree and go to the next element in the outer focusgroup.
+  EXPECT_EQ(utils::NextElement(inner, /* skip_subtree */ true), outer3);
+
+  // Verify that within the inner focusgroup, navigation works independently.
+  EXPECT_EQ(utils::NextElement(inner1, /* skip_subtree */ false), inner2);
+  EXPECT_EQ(utils::NextElement(inner2, /* skip_subtree */ false), inner3);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc b/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
index f6aba30..f11db2e 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_utils.cc
@@ -77,20 +77,6 @@
          ((flags & FocusgroupFlags::kWrapBlock) && IsDirectionBlock(direction));
 }
 
-bool FocusgroupControllerUtils::FocusgroupExtendsInAxis(
-    FocusgroupFlags extending_focusgroup,
-    FocusgroupFlags focusgroup,
-    FocusgroupDirection direction) {
-  if (focusgroup == FocusgroupFlags::kNone ||
-      extending_focusgroup == FocusgroupFlags::kNone) {
-    return false;
-  }
-
-  return extending_focusgroup & FocusgroupFlags::kExtend &&
-         (IsAxisSupported(focusgroup, direction) ==
-          IsAxisSupported(extending_focusgroup, direction));
-}
-
 Element* FocusgroupControllerUtils::FindNearestFocusgroupAncestor(
     const Element* element,
     FocusgroupType type) {
@@ -133,10 +119,11 @@
                                                 bool skip_subtree) {
   DCHECK(current);
   Node* node;
-  if (skip_subtree)
+  if (skip_subtree) {
     node = FlatTreeTraversal::NextSkippingChildren(*current);
-  else
+  } else {
     node = FlatTreeTraversal::Next(*current);
+  }
 
   Element* next_element;
   // Here, we don't need to skip the subtree when getting the next element since
@@ -144,59 +131,134 @@
   // NextSkippingChildren above.
   for (; node; node = FlatTreeTraversal::Next(*node)) {
     next_element = DynamicTo<Element>(node);
-    if (next_element)
+    if (next_element) {
       return next_element;
+    }
   }
   return nullptr;
 }
 
-Element* FocusgroupControllerUtils::PreviousElement(const Element* current) {
+Element* FocusgroupControllerUtils::PreviousElement(const Element* current,
+                                                    bool skip_subtree) {
   DCHECK(current);
-  Node* node = FlatTreeTraversal::Previous(*current);
-
-  Element* previous_element;
+  Node* node;
+  if (skip_subtree) {
+    node = FlatTreeTraversal::PreviousAbsoluteSibling(*current);
+  } else {
+    node = FlatTreeTraversal::Previous(*current);
+  }
   for (; node; node = FlatTreeTraversal::Previous(*node)) {
-    previous_element = DynamicTo<Element>(node);
-    if (previous_element)
+    if (Element* previous_element = DynamicTo<Element>(node)) {
       return previous_element;
+    }
   }
   return nullptr;
 }
 
-Element* FocusgroupControllerUtils::LastElementWithin(const Element* current) {
-  DCHECK(current);
-  Node* last_node = FlatTreeTraversal::LastWithin(*current);
-
-  // We now have the last Node, but it might not be the last Element. Find it
-  // by going to the previous element in preorder if needed.
-  Element* last_element;
-  for (; last_node && last_node != current;
-       last_node = FlatTreeTraversal::Previous(*last_node)) {
-    last_element = DynamicTo<Element>(last_node);
-    if (last_element)
-      return last_element;
+Element* FocusgroupControllerUtils::NextElementInDirection(
+    const Element* current,
+    FocusgroupDirection direction,
+    bool skip_subtree) {
+  if (!current) {
+    return nullptr;
+  }
+  if (IsDirectionForward(direction)) {
+    return NextElement(current, skip_subtree);
+  }
+  if (IsDirectionBackward(direction)) {
+    return PreviousElement(current, skip_subtree);
   }
   return nullptr;
 }
 
-bool FocusgroupControllerUtils::IsFocusgroupItem(const Element* element) {
-  if (!element || !element->IsFocusable())
-    return false;
+// Returns next candidate focusgroup item inside |owner| relative to
+// |current_item| in the specified direction.
+Element* FocusgroupControllerUtils::NextFocusgroupItemInDirection(
+    const Element* owner,
+    const Element* current_item,
+    FocusgroupDirection direction) {
+  if (!owner || !current_item || owner == current_item) {
+    return nullptr;
+  }
 
-  // All children of a focusgroup are considered focusgroup items if they are
-  // focusable.
-  Element* parent = FlatTreeTraversal::ParentElement(*element);
-  if (!parent)
-    return false;
+  Element* next_element =
+      NextElementInDirection(current_item, direction, /*skip_subtree=*/false);
+  while (next_element &&
+         FlatTreeTraversal::IsDescendantOf(*next_element, *owner)) {
+    if (next_element != owner) {
+      if (next_element->GetFocusgroupData().behavior !=
+          FocusgroupBehavior::kNoBehavior) {
+        // We can skip the entire subtree for both nested focusgroups and
+        // opted out subtrees.
+        next_element = NextElementInDirection(next_element, direction,
+                                              /*skip_subtree=*/true);
+        continue;
+      }
+    }
+    if (IsFocusgroupItemWithOwner(next_element, owner)) {
+      return next_element;
+    }
+    next_element =
+        NextElementInDirection(next_element, direction, /*skip_subtree=*/false);
+  }
+  return nullptr;
+}
 
-  FocusgroupData parent_data = parent->GetFocusgroupData();
-  return parent_data.behavior != FocusgroupBehavior::kNoBehavior;
+bool FocusgroupControllerUtils::IsFocusgroupItemWithOwner(
+    const Element* element,
+    const Element* focusgroup_owner) {
+  if (!element || !element->IsFocusable() || !focusgroup_owner) {
+    return false;
+  }
+  if (!IsActualFocusgroup(focusgroup_owner->GetFocusgroupData())) {
+    return false;
+  }
+
+  // An element is a focusgroup item in a specific focusgroup context if:
+  // 1. It is focusable.
+  // 2. It is not opted out or in an opted out subtree.
+  // 3. It is a descendant of a focusgroup.
+  // 4. It is not inside a nested focusgroup which would create a separate
+  // scope.
+
+  // Check if this element has been opted out from focusgroup participation.
+  if (IsElementInOptedOutSubtree(element)) {
+    return false;
+  }
+
+  // Check if the element is a descendant of the focusgroup context.
+  bool is_descendant = false;
+  for (Element* ancestor = FlatTreeTraversal::ParentElement(*element); ancestor;
+       ancestor = FlatTreeTraversal::ParentElement(*ancestor)) {
+    if (ancestor == focusgroup_owner) {
+      is_descendant = true;
+      break;
+    }
+  }
+  if (!is_descendant) {
+    return false;
+  }
+
+  // Check if there's any nested focusgroup between this element and the
+  // focusgroup context. If so, this element belongs to the nested focusgroup,
+  // not the outer focusgroup.
+  for (Element* ancestor = FlatTreeTraversal::ParentElement(*element);
+       ancestor && ancestor != focusgroup_owner;
+       ancestor = FlatTreeTraversal::ParentElement(*ancestor)) {
+    FocusgroupData ancestor_data = ancestor->GetFocusgroupData();
+    if (IsActualFocusgroup(ancestor_data)) {
+      // Found a nested focusgroup - this element belongs to that scope instead.
+      return false;
+    }
+  }
+
+  return true;
 }
 
 // This function is called whenever the |element| passed by parameter has fallen
 // into a subtree while navigating backward. Its objective is to prevent
-// |element| from having descended into a non-extending focusgroup. When it
-// detects its the case, it returns |element|'s first ancestor who is still part
+// |element| from having descended into an opted-out focusgroup. When it
+// detects this case, it returns |element|'s first ancestor who is still part
 // of the same focusgroup as |stop_ancestor|. The returned element is
 // necessarily an element part of the previous focusgroup, but not necessarily a
 // focusgroup item.
@@ -217,11 +279,11 @@
 //    |   |
 //    b1  b2
 //
-// where |fg2| is a focusgroup that doesn't extend the focusgroup |fg1|. While
-// |fg2| is part of the focusgroup |fg1|, its subtree isn't. If the focus is on
+// where |fg2| is a focusgroup that opts out of the focusgroup |fg1|. While
+// elements within |fg2| are not managed by |fg1|. If the focus is on
 // |a2|, the second item of the top-most focusgroup, and we go backward using
 // the arrow keys, the focus should move to |fg2|. It shouldn't go inside of
-// |fg2|, since it's a different focusgroup that doesn't extend its parent
+// |fg2|, since it's a different focusgroup that has opted out of its parent
 // focusgroup.
 //
 // However, the previous element in preorder traversal from |a2| is |b2|, which
@@ -257,12 +319,10 @@
       break;
 
     // We consider |element| as being part of a different focusgroup than the
-    // one we were previously in when one of its ancestor is a focusgroup that
-    // doesn't extend the previous one.
+    // one we were previously in when one of its ancestor has any focusgroup
+    // declaration, which creates a separate scope.
     FocusgroupData ancestor_data = ancestor->GetFocusgroupData();
-    if (ancestor_data.behavior != FocusgroupBehavior::kNoBehavior &&
-        !FocusgroupExtendsInAxis(ancestor_data.flags, focusgroup_data.flags,
-                                 direction)) {
+    if (IsActualFocusgroup(ancestor_data)) {
       adjusted_element = ancestor;
     }
   }
@@ -282,6 +342,24 @@
   return IsA<LayoutTableCell>(element->GetLayoutObject());
 }
 
+bool FocusgroupControllerUtils::IsElementInOptedOutSubtree(
+    const Element* element) {
+  // Starting with this element, walk up the ancestor chain looking for an
+  // opted-out focusgroup. Stop when we reach a focusgroup root or the document
+  // root.
+  while (element) {
+    if (element->GetFocusgroupData().behavior == FocusgroupBehavior::kOptOut) {
+      return true;
+    }
+    // Stop at the first focusgroup root.
+    if (IsActualFocusgroup(element->GetFocusgroupData())) {
+      return false;
+    }
+    element = FlatTreeTraversal::ParentElement(*element);
+  }
+  return false;
+}
+
 GridFocusgroupStructureInfo*
 FocusgroupControllerUtils::CreateGridFocusgroupStructureInfoForGridRoot(
     Element* root) {
@@ -295,4 +373,81 @@
   }
 }
 
+Element* FocusgroupControllerUtils::WrappedFocusgroupCandidate(
+    const Element* owner,
+    const Element* current,
+    FocusgroupDirection direction) {
+  DCHECK(owner && current);
+  DCHECK(IsFocusgroupItemWithOwner(current, owner));
+
+  Element* wrap_candidate = nullptr;
+  if (IsDirectionForward(direction)) {
+    wrap_candidate = FirstFocusgroupItemWithin(owner);
+  } else if (IsDirectionBackward(direction)) {
+    wrap_candidate = LastFocusgroupItemWithin(owner);
+  }
+
+  // If the wrap candidate is valid and isn't the current element, return it.
+  if (wrap_candidate && wrap_candidate != current) {
+    return wrap_candidate;
+  }
+  return nullptr;
+}
+
+Element* FocusgroupControllerUtils::FirstFocusgroupItemWithin(
+    const Element* owner) {
+  if (!owner || !IsActualFocusgroup(owner->GetFocusgroupData())) {
+    return nullptr;
+  }
+
+  for (Element* el = NextElement(owner, /*skip_subtree=*/false);
+       el && FlatTreeTraversal::IsDescendantOf(*el, *owner);
+       el = NextElement(el, /*skip_subtree=*/false)) {
+    if (el != owner) {
+      FocusgroupData data = el->GetFocusgroupData();
+      if (data.behavior != FocusgroupBehavior::kNoBehavior) {
+        // Skip nested focusgroup subtree entirely.
+        el = NextElement(el, /*skip_subtree=*/true);
+        if (!el) {
+          break;
+        }
+        el = PreviousElement(el);
+        continue;
+      }
+    }
+    if (IsFocusgroupItemWithOwner(el, owner)) {
+      return el;
+    }
+  }
+  return nullptr;
+}
+
+Element* FocusgroupControllerUtils::LastFocusgroupItemWithin(
+    const Element* owner) {
+  if (!owner || !IsActualFocusgroup(owner->GetFocusgroupData())) {
+    return nullptr;
+  }
+
+  Element* last = nullptr;
+  for (Element* el = NextElement(owner, /*skip_subtree=*/false);
+       el && FlatTreeTraversal::IsDescendantOf(*el, *owner);
+       el = NextElement(el, /*skip_subtree=*/false)) {
+    if (el != owner) {
+      FocusgroupData data = el->GetFocusgroupData();
+      if (data.behavior != FocusgroupBehavior::kNoBehavior) {
+        el = NextElement(el, /*skip_subtree=*/true);
+        if (!el) {
+          break;
+        }
+        el = PreviousElement(el);
+        continue;
+      }
+    }
+    if (IsFocusgroupItemWithOwner(el, owner)) {
+      last = el;
+    }
+  }
+  return last;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/page/focusgroup_controller_utils.h b/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
index 5af34b6..9a4f3e4 100644
--- a/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
+++ b/third_party/blink/renderer/core/page/focusgroup_controller_utils.h
@@ -41,24 +41,51 @@
                               FocusgroupDirection direction);
   static bool WrapsInDirection(FocusgroupFlags flags,
                                FocusgroupDirection direction);
-  static bool FocusgroupExtendsInAxis(FocusgroupFlags extending_focusgroup,
-                                      FocusgroupFlags focusgroup,
-                                      FocusgroupDirection direction);
-
   static Element* FindNearestFocusgroupAncestor(const Element* element,
                                                 FocusgroupType type);
+  static Element* NextElementInDirection(const Element* current,
+                                         FocusgroupDirection direction,
+                                         bool skip_subtree);
   static Element* NextElement(const Element* current, bool skip_subtree);
-  static Element* PreviousElement(const Element* current);
-  static Element* LastElementWithin(const Element* current);
+  static Element* PreviousElement(const Element* current,
+                                  bool skip_subtree = false);
+
+  // Returns the next focusgroup item candidate within the |owner| subtree
+  // relative to |current_item| in the traversal order implied by |direction|.
+  // For forward directions this returns the first subsequent eligible item.
+  // For backward directions this returns the last eligible item that appears
+  // before |current|. Returns nullptr if none is found. Nested focusgroup
+  // subtrees are skipped entirely.
+  static Element* NextFocusgroupItemInDirection(const Element* owner,
+                                                const Element* current_item,
+                                                FocusgroupDirection direction);
+
+  // Returns the element to focus when wrapping within |owner| in the given
+  // |direction| starting from |current|. Skips nested focusgroup subtrees and
+  // never returns |current| itself. Returns nullptr if no alternative item
+  // exists.
+  static Element* WrappedFocusgroupCandidate(const Element* owner,
+                                             const Element* current,
+                                             FocusgroupDirection direction);
+
+  // Returns the first/last focusgroup item within |owner|'s scope, or nullptr
+  // if no eligible item exists. |owner| must itself be a focusgroup owner.
+  static Element* FirstFocusgroupItemWithin(const Element* owner);
+  static Element* LastFocusgroupItemWithin(const Element* owner);
 
   static Element* AdjustElementOutOfUnrelatedFocusgroup(
       Element* element,
       Element* stop_ancestor,
       FocusgroupDirection direction);
 
-  static bool IsFocusgroupItem(const Element* element);
+  static bool IsFocusgroupItemWithOwner(const Element* element,
+                                        const Element* focusgroup_owner);
   static bool IsGridFocusgroupItem(const Element* element);
 
+  // Returns true if the element is opted out or within an opted-out focusgroup
+  // subtree.
+  static bool IsElementInOptedOutSubtree(const Element* element);
+
   static GridFocusgroupStructureInfo*
   CreateGridFocusgroupStructureInfoForGridRoot(Element* root);
 };
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
index 64be67f..485ba964 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
@@ -282,6 +282,9 @@
 
   Element& container = GetElementById(AtomicString("container"));
   gfx::Size bubble_size = container.VisibleBoundsInLocalRoot().size();
+  if (bubble_size.IsEmpty()) {
+    return;
+  }
 
   bool show_bottom_arrow = false;
   double bubble_y = anchor_rect.bottom();
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc
index 8957478..ce1d735 100644
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate_test.cc
@@ -68,6 +68,7 @@
 
   // Trigger the overlay animations.
   delegate_ptr->UpdateFrameViewState(*overlay);
+  delegate_ptr->UpdateFrameViewState(*overlay);
 
   // Now find the related animations, and make sure they weren't composited.
   Document* internal_document =
diff --git a/third_party/blink/renderer/core/url/dom_origin.cc b/third_party/blink/renderer/core/url/dom_origin.cc
index 4f3e127..d76afc2 100644
--- a/third_party/blink/renderer/core/url/dom_origin.cc
+++ b/third_party/blink/renderer/core/url/dom_origin.cc
@@ -140,8 +140,7 @@
     // TODO(434131026): We only have a serialized origin here, which means
     // our handling of `null` is broken. We'll need to teach `MessageEvent`
     // to hold a `SecurityOrigin` instead.
-    return MakeGarbageCollected<DOMOrigin>(
-        SecurityOrigin::CreateFromString(event->origin()));
+    return MakeGarbageCollected<DOMOrigin>(event->GetSecurityOrigin());
   }
 
   // Origin
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
index f2cb9d4..37eb300 100644
--- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
+++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -281,10 +281,10 @@
       *GetExecutionContext(), std::move(message.ports));
   debugger->ExternalAsyncTaskStarted(message.sender_stack_trace_id);
   if (message.message->CanDeserializeIn(GetExecutionContext())) {
-    MessageEvent* event =
-        MessageEvent::Create(ports, std::move(message.message), /* origin=*/{},
-                             MessageEvent::kMessageIsSameOrigin,
-                             /* last_event_id=*/{}, /* source=*/nullptr);
+    MessageEvent* event = MessageEvent::Create(
+        ports, std::move(message.message), /* origin=*/nullptr,
+        MessageEvent::kMessageIsSameOrigin,
+        /* last_event_id=*/{}, /* source=*/nullptr);
     event->SetTraceId(message.trace_id);
     TRACE_EVENT(
         "devtools.timeline", "HandlePostMessage", "data",
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
index cb069c9..bd62eb3 100644
--- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -201,7 +201,7 @@
   port->Entangle(std::move(channel));
   MessageEvent* event =
       MessageEvent::Create(MakeGarbageCollected<GCedMessagePortArray>(1, port),
-                           String(), String(), port);
+                           /*origin=*/nullptr, String(), port);
   event->initEvent(event_type_names::kConnect, false, false);
   DispatchEvent(*event);
 }
diff --git a/third_party/blink/renderer/modules/badging/navigator_badge.idl b/third_party/blink/renderer/modules/badging/navigator_badge.idl
index db1daff4..cb1455c 100644
--- a/third_party/blink/renderer/modules/badging/navigator_badge.idl
+++ b/third_party/blink/renderer/modules/badging/navigator_badge.idl
@@ -4,12 +4,13 @@
 
 // https://wicg.github.io/badging/
 [
-    SecureContext,
-    ImplementedAs=NavigatorBadge
-] partial interface Navigator {
+    SecureContext
+] interface mixin NavigatorBadge {
   [CallWith=ScriptState, MeasureAs=BadgeSet, RaisesException]
   Promise<undefined> setAppBadge(optional [EnforceRange] unsigned long long contents);
 
   [CallWith=ScriptState, MeasureAs=BadgeClear, RaisesException]
   Promise<undefined> clearAppBadge();
 };
+
+Navigator includes NavigatorBadge;
diff --git a/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc b/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
index ef78e54..02ed844e 100644
--- a/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
+++ b/third_party/blink/renderer/modules/broadcastchannel/broadcast_channel.cc
@@ -174,11 +174,11 @@
        context->IsSameAgentCluster(message.sender_agent_cluster_id)) &&
       message.message->CanDeserializeIn(context)) {
     event = MessageEvent::Create(nullptr, std::move(message.message),
-                                 context->GetSecurityOrigin()->ToString(),
+                                 context->GetSecurityOrigin(),
                                  MessageEvent::kMessageIsSameOrigin,
                                  /* last_event_id=*/{}, /* source=*/nullptr);
   } else {
-    event = MessageEvent::CreateError(context->GetSecurityOrigin()->ToString());
+    event = MessageEvent::CreateError(context->GetSecurityOrigin());
   }
 
   if (base::FeatureList::IsEnabled(features::kBFCacheOpenBroadcastChannel) &&
diff --git a/third_party/blink/renderer/modules/eventsource/event_source.cc b/third_party/blink/renderer/modules/eventsource/event_source.cc
index 9a0b1ea..cc50273 100644
--- a/third_party/blink/renderer/modules/eventsource/event_source.cc
+++ b/third_party/blink/renderer/modules/eventsource/event_source.cc
@@ -249,8 +249,7 @@
 
   resource_identifier_ = identifier;
   current_url_ = response.CurrentRequestUrl();
-  event_stream_origin_ =
-      SecurityOrigin::Create(response.CurrentRequestUrl())->ToString();
+  event_stream_origin_ = SecurityOrigin::Create(response.CurrentRequestUrl());
   int status_code = response.HttpStatusCode();
   bool mime_type_is_valid = response.MimeType() == "text/event-stream";
   bool response_is_valid = status_code == 200 && mime_type_is_valid;
diff --git a/third_party/blink/renderer/modules/eventsource/event_source.h b/third_party/blink/renderer/modules/eventsource/event_source.h
index d8e91370..7cc2c1ff 100644
--- a/third_party/blink/renderer/modules/eventsource/event_source.h
+++ b/third_party/blink/renderer/modules/eventsource/event_source.h
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 
 namespace blink {
@@ -133,7 +134,7 @@
   HeapTaskRunnerTimer<EventSource> connect_timer_;
 
   uint64_t reconnect_delay_;
-  String event_stream_origin_;
+  scoped_refptr<const SecurityOrigin> event_stream_origin_;
   uint64_t resource_identifier_ = 0;
 
   // The world in which this EventSource was created. We need to store this
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
index 230ff97..48a34f6 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_container.cc
@@ -824,8 +824,7 @@
     if (!msg.sender_origin ||
         !msg.sender_origin->IsSameOriginWith(target_origin)) {
       event = MessageEvent::CreateError(
-          GetExecutionContext()->GetSecurityOrigin()->ToString(),
-          service_worker);
+          GetExecutionContext()->GetSecurityOrigin(), service_worker);
     }
   }
   if (!event) {
@@ -834,12 +833,12 @@
          context->IsSameAgentCluster(msg.sender_agent_cluster_id)) &&
         msg.message->CanDeserializeIn(context)) {
       event = MessageEvent::Create(ports, std::move(msg.message),
-                                   context->GetSecurityOrigin()->ToString(),
+                                   context->GetSecurityOrigin(),
                                    MessageEvent::kMessageIsSameOrigin,
                                    String() /* lastEventId */, service_worker);
     } else {
-      event = MessageEvent::CreateError(
-          context->GetSecurityOrigin()->ToString(), service_worker);
+      event = MessageEvent::CreateError(context->GetSecurityOrigin(),
+                                        service_worker);
     }
   }
   // Schedule the event to be dispatched on the correct task source:
diff --git a/third_party/blink/renderer/modules/webcodecs/decoder_selector.cc b/third_party/blink/renderer/modules/webcodecs/decoder_selector.cc
index f2be50446..7f3e5d7 100644
--- a/third_party/blink/renderer/modules/webcodecs/decoder_selector.cc
+++ b/third_party/blink/renderer/modules/webcodecs/decoder_selector.cc
@@ -5,13 +5,13 @@
 #include "third_party/blink/renderer/modules/webcodecs/decoder_selector.h"
 
 #include "base/check_op.h"
-#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/notreached.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
 #include "media/base/channel_layout.h"
 #include "media/base/demuxer_stream.h"
+#include "media/base/media_switches.h"
 #include "media/base/sample_format.h"
 #include "media/filters/decrypting_demuxer_stream.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
@@ -19,9 +19,6 @@
 
 namespace blink {
 
-// TODO(crbug.com/368085608): Remove after M143 goes stable.
-BASE_FEATURE(kResolutionBasedDecoderPriority, base::FEATURE_ENABLED_BY_DEFAULT);
-
 // Demuxing isn't part of WebCodecs. This shim allows us to reuse decoder
 // selection logic from <video>.
 // TODO(chcunningham): Maybe refactor DecoderSelector to separate dependency on
@@ -56,7 +53,8 @@
     // resolution when hardwareAcceleration == "no-preference". If it's instead
     // "prefer-hardware" or "prefer-software" the flag has no effect since only
     // the hardware or software factory is returned via `create_decoders_cb`.
-    return !base::FeatureList::IsEnabled(kResolutionBasedDecoderPriority);
+    return !base::FeatureList::IsEnabled(
+        media::kResolutionBasedDecoderPriority);
   }
 
   void set_low_delay(bool low_delay) { low_delay_ = low_delay; }
@@ -92,7 +90,8 @@
     typename Decoder::OutputCB output_cb)
     : impl_(std::move(task_runner),
             std::move(create_decoders_cb),
-            &null_media_log_),
+            &null_media_log_,
+            /*enable_priority_based_selection=*/true),
       demuxer_stream_(new NullDemuxerStream<StreamType>()),
       stream_traits_(CreateStreamTraits()),
       output_cb_(output_cb) {
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
index 4f2c091..4a98e9e3 100644
--- a/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
+++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_broker_test.cc
@@ -9,6 +9,7 @@
 
 #include "base/run_loop.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/threading/thread.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
@@ -414,6 +415,8 @@
 }
 
 TEST_F(VideoDecoderBrokerTest, Decode_MultipleAccelerationPreferences) {
+  base::test::ScopedFeatureList enabled_features_{
+      media::kResolutionBasedDecoderPriority};
   V8TestingScope v8_scope;
   ExecutionContext* execution_context = v8_scope.GetExecutionContext();
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl
index 805733d..1f1d442 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_base.idl
@@ -518,4 +518,3 @@
         [AllowShared, BufferSourceTypeNoSizeLimit] ArrayBufferView dstData, GLintptr offset);
     void readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLintptr offset);
 };
-WebGL2RenderingContextBase includes WebGLRenderingContextBase;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
index 9100073..2959694 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
@@ -1835,17 +1835,6 @@
     GetDrawingBuffer()->SetBufferClearNeeded(true);
 }
 
-bool WebGLRenderingContextBase::
-    CanUseDrawingBufferSIWithoutCopyForLowLatency() {
-  CHECK(GetDrawingBuffer());
-
-  if (!SharedGpuContext::IsGpuCompositingEnabled()) {
-    return false;
-  }
-
-  return GetDrawingBuffer()->SupportsConcurrentReadWrite();
-}
-
 void WebGLRenderingContextBase::PageVisibilityChanged() {
   if (GetDrawingBuffer())
     GetDrawingBuffer()->SetIsInHiddenPage(!Host()->IsPageVisible());
@@ -1883,7 +1872,8 @@
     return nullptr;
   }
 
-  if (CanUseDrawingBufferSIWithoutCopyForLowLatency()) {
+  if (SharedGpuContext::IsGpuCompositingEnabled() &&
+      GetDrawingBuffer()->SupportsNoCopyExportForLowLatency()) {
     auto resource = ExportLowLatencyCanvasResource(source_buffer);
     return resource ? resource->Bitmap() : nullptr;
   }
@@ -1972,7 +1962,8 @@
     return nullptr;
   }
 
-  if (CanUseDrawingBufferSIWithoutCopyForLowLatency()) {
+  if (SharedGpuContext::IsGpuCompositingEnabled() &&
+      GetDrawingBuffer()->SupportsNoCopyExportForLowLatency()) {
     return ExportLowLatencyCanvasResource(source_buffer);
   }
 
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
index 48b5dd8f..7b5a3fc 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.h
@@ -719,7 +719,6 @@
 
   // CanvasRenderingContext implementation.
   bool IsComposited() const override { return true; }
-  bool CanUseDrawingBufferSIWithoutCopyForLowLatency();
   void PageVisibilityChanged() override;
   void SizeChanged() override;
   scoped_refptr<StaticBitmapImage> PaintRenderingResultsToSnapshot(
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.cc b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
index 48cdb43..4edbe5a 100644
--- a/third_party/blink/renderer/modules/websockets/dom_websocket.cc
+++ b/third_party/blink/renderer/modules/websockets/dom_websocket.cc
@@ -255,7 +255,7 @@
   switch (result) {
     case WebSocketCommon::ConnectResult::kSuccess:
       DCHECK(!exception_state.HadException());
-      origin_string_ = SecurityOrigin::Create(common_.Url())->ToString();
+      origin_ = SecurityOrigin::Create(common_.Url());
       return;
 
     case WebSocketCommon::ConnectResult::kException:
@@ -511,8 +511,8 @@
   if (common_.GetState() != kOpen)
     return;
 
-  DCHECK(!origin_string_.IsNull());
-  event_queue_->Dispatch(MessageEvent::Create(msg, origin_string_));
+  DCHECK(origin_);
+  event_queue_->Dispatch(MessageEvent::Create(msg, origin_));
   NotifyWebSocketActivity();
 }
 
@@ -525,7 +525,7 @@
   DVLOG(1) << "WebSocket " << this << " DidReceiveBinaryMessage() " << size
            << " byte binary message";
   ReflectBufferedAmountConsumption();
-  DCHECK(!origin_string_.IsNull());
+  DCHECK(origin_);
 
   DCHECK_NE(common_.GetState(), kConnecting);
   if (common_.GetState() != kOpen)
@@ -539,14 +539,13 @@
       }
       auto* blob = MakeGarbageCollected<Blob>(
           BlobDataHandle::Create(std::move(blob_data), size));
-      event_queue_->Dispatch(MessageEvent::Create(blob, origin_string_));
+      event_queue_->Dispatch(MessageEvent::Create(blob, origin_));
       break;
     }
 
     case V8BinaryType::Enum::kArraybuffer:
       DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(data);
-      event_queue_->Dispatch(
-          MessageEvent::Create(array_buffer, origin_string_));
+      event_queue_->Dispatch(MessageEvent::Create(array_buffer, origin_));
       break;
   }
   NotifyWebSocketActivity();
diff --git a/third_party/blink/renderer/modules/websockets/dom_websocket.h b/third_party/blink/renderer/modules/websockets/dom_websocket.h
index 0857e03c..7fd04f9 100644
--- a/third_party/blink/renderer/modules/websockets/dom_websocket.h
+++ b/third_party/blink/renderer/modules/websockets/dom_websocket.h
@@ -52,6 +52,7 @@
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/timer.h"
 #include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/deque.h"
 #include "third_party/blink/renderer/platform/wtf/forward.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
@@ -246,7 +247,7 @@
 
   WebSocketCommon common_;
 
-  String origin_string_;
+  scoped_refptr<const SecurityOrigin> origin_;
 
   uint64_t buffered_amount_;
   // The consumed buffered amount that will be reflected to |buffered_amount_|
diff --git a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
index 684d0b46..60fa0d1 100644
--- a/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
+++ b/third_party/blink/renderer/platform/blink_platform_unittests_bundle_data.filelist
@@ -19,6 +19,7 @@
 ../../web_tests/external/wpt/fonts/CanvasTest-nospace.ttf
 ../../web_tests/external/wpt/fonts/CanvasTest.ttf
 ../../web_tests/external/wpt/fonts/GentiumPlus-R.woff
+../../web_tests/external/wpt/fonts/Lato-Bold.ttf
 ../../web_tests/external/wpt/fonts/Lato-Medium-Liga.ttf
 ../../web_tests/external/wpt/fonts/Lato-Medium.ttf
 ../../web_tests/external/wpt/fonts/Revalia.woff
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
index 0395a38..9d15b47 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.cc
@@ -1726,11 +1726,14 @@
   client_->DrawingBufferClientRestorePixelPackBufferBinding();
 }
 
-bool DrawingBuffer::SupportsConcurrentReadWrite() {
+bool DrawingBuffer::SupportsNoCopyExportForLowLatency() {
   if (!back_color_buffer_) {
     return false;
   }
 
+  // If the back buffer has concurrent R/W usage, then it means that (a) we are
+  // in low-latency mode, and (b) we determined that it is possible to support
+  // concurrent read/writes on the back buffer's SI.
   return back_color_buffer_->shared_image->usage().Has(
       gpu::SHARED_IMAGE_USAGE_CONCURRENT_READ_WRITE);
 }
diff --git a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
index 84c0116..05e3ce4 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/drawing_buffer.h
@@ -312,9 +312,9 @@
 
   bool UsingSwapChain() const { return using_swap_chain_; }
 
-  // Returns true if the drawing buffer supports being concurrently written to
-  // and read from.
-  bool SupportsConcurrentReadWrite();
+  // Returns true if the drawing buffer supports direct (no-copy) export for low
+  // latency (e.g., to the display compositor).
+  bool SupportsNoCopyExportForLowLatency();
 
   // Keep track of low latency buffer status.
   bool low_latency_enabled() const { return low_latency_enabled_; }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index e000334..4db5fca 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -1532,8 +1532,6 @@
       status: "stable",
       depends_on: ["PseudoElementsFocusable"],
     },
-
-
     {
       // Non-standard 'auto' keyword for the CSS resize property. Used for
       // selectively enable resize corner for textarea via UA stylesheet, but
@@ -2720,7 +2718,6 @@
       name: "HTMLElementScrollParent",
       status: "experimental",
     },
-
     // Return a natural width/height of zero from
     // HTMLImageElement.naturalWidth/Height for SVG images that don't have a
     // natural width/height set.
@@ -3223,7 +3220,6 @@
       name: "MessagePortCloseEvent",
       status: "test",
     },
-
     // This is enabled by default on Windows only. The only part that's
     // "experimental" is the support on other platforms.
     {
@@ -3336,7 +3332,6 @@
       },
       base_feature: "none",
     },
-
     {
       // This turns off all font antialiasing for tests unless it is
       // explicitly required and enabled using the
@@ -3419,6 +3414,13 @@
       status: "stable",
     },
     {
+      // Restrict popover invoker lookup to the same TreeScope as the element.
+      // This will be shipped in M142, and it can be removed in M144.
+      // See https://issues.chromium.org/issues/443031270.
+      name: "OpenPopoverInvokerRestrictToSameTreeScope",
+      status: "stable",
+    },
+    {
       name: "OrientationEvent",
       status: {"Android": "stable"},
     },
@@ -3442,7 +3444,6 @@
       name: "OriginPolicy",
       status: "experimental",
     },
-
     // Define a sample API for testing integration with the Origin Trials
     // Framework. The sample API is used in both unit and web tests for the
     // Origin Trials Framework. Do not change this flag to stable, as it exists
@@ -4174,6 +4175,13 @@
       status: "stable",
     },
     {
+      // Constrains text selections to stay within table cell boundaries
+      // (e.g., triple-click paragraph selection)
+      // See crbug.com/40852213.
+      name: "RestrictTableCellSelectionToBoundary",
+      status: "stable",
+    },
+    {
       // If enabled, makes the root scrollbars' foreground elements follow the
       // browser
       name: "RootScrollbarFollowsBrowserTheme",
@@ -4288,7 +4296,6 @@
       // https://github.com/WICG/view-transitions/blob/main/scoped-transitions.md
       name: "ScopedViewTransitions",
       status: "experimental"
-
     },
     {
       // https://github.com/w3c/window-management/issues/149
@@ -4438,7 +4445,6 @@
       name: "SelectedcontentelementAttribute",
       status: "test",
     },
-
     {
       // See https://crbug.com/40664519
       name: "SelectionAndFocusedVisiblePositionMatch",
@@ -4888,7 +4894,6 @@
       base_feature_status: "enabled",
       copied_from_base_feature_if: "overridden",
     },
-
     {
       name: "TestFeature",
       base_feature: "none",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 612f376..41591e2 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -9760,3 +9760,9 @@
 crbug.com/449751911 [ Debug Linux ] virtual/scalefactor200/external/wpt/largest-contentful-paint/animated/observe-animated-image.tentative.html [ Failure Pass ]
 # crbug.com/449751911 failure pass for linux debug, crbug.com/805756 for timeouts on all platforms.
 crbug.com/449751911 crbug.com/805756 external/wpt/html/semantics/tabular-data/processing-model-1/span-limits.html [ Failure Pass Timeout ]
+
+# Gardener 2025-10-10
+crbug.com/450592015 [ Mac12-arm64 ] external/wpt/webxr/idlharness.https.window.html [ Failure ]
+crbug.com/450592015 [ Mac13-arm64 ] external/wpt/webxr/idlharness.https.window.html [ Failure ]
+crbug.com/450592015 [ Mac14-arm64 ] external/wpt/webxr/idlharness.https.window.html [ Failure ]
+crbug.com/450592015 [ Mac15-arm64 ] external/wpt/webxr/idlharness.https.window.html [ Failure ]
\ No newline at end of file
diff --git a/third_party/blink/web_tests/editing/selection/5057506-2.html b/third_party/blink/web_tests/editing/selection/5057506-2.html
index deeaefc..62cb411 100644
--- a/third_party/blink/web_tests/editing/selection/5057506-2.html
+++ b/third_party/blink/web_tests/editing/selection/5057506-2.html
@@ -2,11 +2,7 @@
 <script src="../../resources/testharness.js"></script>
 <script src="../../resources/testharnessreport.js"></script>
 <p>This tests triple clicking after the last character in the last cell of a
-block table. The paragraph break (the space between the last character and the
-first character in the next paragraph) should be selected. Selection painting
-problems might prevent the paragraph break from appearing as selected even
-though it is. To test manually, triple click inside the table cell, after the
-last character, and hit delete.  Afterward, the table should contain only 'bar'.
+block table. The selection should be constrained within the table cell boundaries.
 </p>
 <div contenteditable="true">
 <table border="1"><tr><td width="100px"><span id="span">foo</span></td></tr></table>
@@ -36,7 +32,7 @@
     assert_false(selection.isCollapsed, 'isCollapsed');
     assert_equals(selection.anchorNode, span.firstChild, 'anchorNode');
     assert_equals(selection.anchorOffset, 0, 'anchorOffset');
-    assert_equals(selection.focusNode, document.getElementById('end'), 'focusNode');
-    assert_equals(selection.focusOffset, 0, 'focusOffset');
+    assert_equals(selection.focusNode, span.firstChild, 'focusNode');
+    assert_equals(selection.focusOffset, 3, 'focusOffset');
 });
 </script>
diff --git a/third_party/blink/web_tests/editing/selection/table-cell-triple-click.html b/third_party/blink/web_tests/editing/selection/table-cell-triple-click.html
new file mode 100644
index 0000000..7755c3ee
--- /dev/null
+++ b/third_party/blink/web_tests/editing/selection/table-cell-triple-click.html
@@ -0,0 +1,117 @@
+<!DOCTYPE html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../../resources/testdriver.js"></script>
+<script src="../../resources/testdriver-actions.js"></script>
+<script src="../../resources/testdriver-vendor.js"></script>
+<p>This test validates that triple-click selection in table cells is properly
+constrained to cell boundaries. When users triple-click text within a table cell,
+the selection should include only that cell's content, preventing unwanted table
+markup from being copied and ensuring clean copy/paste operations.
+</p>
+
+<style>
+table,
+td {
+  border: 1px solid black;
+}
+</style>
+
+<table id="testTable">
+<tbody><tr>
+  <td id="cell1">cell 1</td>
+  <td id="cell2">cell 2</td>
+  <td id="cell3">cell 3</td>
+</tr>
+<tr>
+  <td id="cell4">cell 4</td>
+  <td id="cell5">cell 5</td>
+  <td id="cell6">cell 6</td>
+</tr>
+<tr>
+  <td id="cell7">cell 7</td>
+  <td id="cell8">cell 8</td>
+  <td id="cell9">cell 9</td>
+</tr>
+</tbody></table>
+
+<br>
+<div contenteditable="true" id="pasteArea">paste content here</div>
+
+<script>
+
+async function testTripleClickInCell(cellId, expectedText, testDescription) {
+    assert_not_equals(window.eventSender, undefined, 'This test requires eventSender.');
+
+    const selection = window.getSelection();
+    const targetCell = document.getElementById(cellId);
+    const pasteArea = document.getElementById("pasteArea");
+
+    // Clear any existing selection
+    selection.removeAllRanges();
+
+    // Calculate position in the middle of the target cell
+    const rect = targetCell.getBoundingClientRect();
+    const x = rect.left + rect.width / 2;
+    const y = rect.top + rect.height / 2;
+
+    internals.settings.setEditingBehavior('win');
+
+    // Simulate triple-click on the target cell
+    eventSender.mouseMoveTo(x, y);
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+    eventSender.mouseDown();
+    eventSender.mouseUp();
+
+    // Verify selection is not collapsed
+    assert_false(selection.isCollapsed, 'Selection should not be collapsed after triple-click');
+
+    // Verify selection text content
+    const selectedText = selection.toString();
+    assert_equals(selectedText, expectedText, 'Selected text should be "' + expectedText + '"');
+
+    // Verify selection stays within the target cell
+    const range = selection.getRangeAt(0);
+    const startContainer = range.startContainer.nodeType === Node.TEXT_NODE ?
+                          range.startContainer.parentElement : range.startContainer;
+    const endContainer = range.endContainer.nodeType === Node.TEXT_NODE ?
+                        range.endContainer.parentElement : range.endContainer;
+
+    assert_true(targetCell.contains(startContainer), 'Selection start should be within target cell');
+    assert_true(targetCell.contains(endContainer), 'Selection end should be within target cell');
+
+    // Copy the selection using eventSender
+    eventSender.keyDown('Copy');
+
+    // Clear selection and focus on paste area
+    selection.removeAllRanges();
+    pasteArea.focus();
+    pasteArea.innerHTML = '';
+
+    // Paste using eventSender
+    eventSender.keyDown('Paste');
+
+    // Verify pasted content
+    const pastedContent = pasteArea.textContent.trim();
+    assert_equals(pastedContent, expectedText, 'Pasted content should be "' + expectedText + '" without table structure');
+
+    // Verify no HTML table structure was pasted
+    const pastedHTML = pasteArea.innerHTML;
+    assert_false(pastedHTML.includes('<table'), 'Pasted content should not contain table tags');
+    assert_false(pastedHTML.includes('<td'), 'Pasted content should not contain cell tags');
+    assert_false(pastedHTML.includes('<tr'), 'Pasted content should not contain row tags');
+    assert_false(pastedHTML.includes('\t'), 'Pasted content should not contain tab characters');
+}
+
+promise_test(async function() {
+    await testTripleClickInCell("cell2", "cell 2", "middle cell");
+}, 'Triple-click in table cell should select only cell content without table structure');
+
+promise_test(async function() {
+    await testTripleClickInCell("cell9", "cell 9", "last cell");
+}, 'Triple-click in last table cell should not extend beyond table boundaries');
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/does-not-move-when-on-non-focusgroup-item.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/does-not-move-when-on-non-focusgroup-item.html
index b9640310..d6bae237 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/does-not-move-when-on-non-focusgroup-item.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/does-not-move-when-on-non-focusgroup-item.html
@@ -13,11 +13,11 @@
 <div focusgroup="toolbar">
   <span id=item1 tabindex=0>item1</span>
   <span id=item2 tabindex=-1>item2</span>
-  <div>
-    <span id=nonitem1 tabindex=0>nonitem1</span>
-  </div>
 </div>
 
+<!-- Element outside focusgroup should not participate -->
+<span id=nonitem1 tabindex=0>nonitem1</span>
+
 <script>
 
   promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-focusgroup.html
similarity index 83%
rename from third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html
rename to third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-focusgroup.html
index c06db4b5..1c3a7ac 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-non-extending-focusgroup.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/horizontal/does-not-ascend-out-of-focusgroup.html
@@ -25,6 +25,6 @@
 
     await focusAndKeyPress(item2, kArrowLeft);
     assert_equals(document.activeElement, item2);
-  }, "When the focus is set on the first element of a non-extending focusgroup located inside another focusgroup, we should be able to ascend to that other focusgroup.");
+  }, "When the focus is set on an element in a nested focusgroup that doesn't support the navigation direction, focus should remain on that element and not ascend to the parent focusgroup.");
 
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-non-focusgroup-subtree.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-non-focusgroup-subtree.html
index 8f328fc..6a07936 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-non-focusgroup-subtree.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-non-focusgroup-subtree.html
@@ -1,6 +1,6 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
-<title>HTML Test: focusgroup - Focus moves to previous item, skipping over a subtree that isn't an extending focusgroup.</title>
+<title>HTML Test: focusgroup - Focus moves to previous item, skipping over a subtree that isn't in the parent focusgroup.</title>
 <link rel="author" title="Microsoft" href="http://www.microsoft.com/">
 <link rel="help" href="https://github.com/MicrosoftEdge/MSEdgeExplainers/blob/main/Focusgroup/explainer.md">
 <script src="/resources/testharness.js"></script>
@@ -12,7 +12,7 @@
 
 <div focusgroup="toolbar wrap">
   <span id=item1 tabindex=0>item1</span>
-  <div>
+  <div focusgroup="none">
     <span id=item2 tabindex=-1>item2</span>
     <span id=item3 tabindex=-1>item3</span>
   </div>
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-root-focusgroup.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-root-focusgroup.html
index 1091bf2..11b99d1e 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-root-focusgroup.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/skips-root-focusgroup.html
@@ -32,6 +32,6 @@
 
     await focusAndKeyPress(item4, kArrowLeft);
     assert_equals(document.activeElement, item1);
-  }, "When the focus is set on the last item of a focusgroup and the previous item is located past an other (non-extending) focusgroup subtree, a backward arrow key press should move the focus to that previous item without getting stuck in the other focusgroup.");
+  }, "When the focus is set on the last item of a focusgroup and the previous item is located past an other focusgroup subtree, a backward arrow key press should move the focus to that previous item without getting stuck in the other focusgroup.");
 
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-focusgroup.html
similarity index 83%
rename from third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html
rename to third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-focusgroup.html
index 8d72095..33be602 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-non-extending-focusgroup.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/backward-navigation/vertical/does-not-ascend-out-of-focusgroup.html
@@ -25,6 +25,6 @@
 
     await focusAndKeyPress(item2, kArrowUp);
     assert_equals(document.activeElement, item2);
-  }, "When the focus is set on the first element of a non-extending focusgroup located inside another focusgroup, we should be able to ascend to that other focusgroup.");
+  }, "When the focus is set on an element in a nested focusgroup that doesn't support the navigation direction, focus should remain on that element and not ascend to the parent focusgroup.");
 
 </script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/deeply-nested-items.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/deeply-nested-items.html
new file mode 100644
index 0000000..a8d7062
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/deeply-nested-items.html
@@ -0,0 +1,87 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Navigation works with deeply nested descendants</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <span id=item1 tabindex=0>Item 1</span>
+  <div class="container">
+    <div class="sub-container">
+      <div class="deep-container">
+        <span id=item2 tabindex=-1>Item 2 (deeply nested)</span>
+      </div>
+    </div>
+  </div>
+  <span>
+    <span>
+      <span id=item3 tabindex=-1>Item 3 (nested in spans)</span>
+    </span>
+  </span>
+  <div>
+    <p>Some text</p>
+    <div>
+      <span id=item4 tabindex=-1>Item 4 (nested)</span>
+    </div>
+  </div>
+  <span id=item5 tabindex=-1>Item 5</span>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should navigate to deeply nested button");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should navigate to button nested in spans");
+
+    await focusAndKeyPress(item3, kArrowRight);
+    assert_equals(document.activeElement, item4, "Should navigate to nested span");
+
+    await focusAndKeyPress(item4, kArrowRight);
+    assert_equals(document.activeElement, item5, "Should navigate to final span");
+  }, "Forward navigation should work with deeply nested focusgroup descendants");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    item5.focus();
+    await focusAndKeyPress(item5, kArrowLeft);
+    assert_equals(document.activeElement, item4, "Should navigate backward to nested input");
+
+    await focusAndKeyPress(item4, kArrowLeft);
+    assert_equals(document.activeElement, item3, "Should navigate backward to span nested in spans");
+
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item2, "Should navigate backward to deeply nested span");
+
+    await focusAndKeyPress(item2, kArrowLeft);
+    assert_equals(document.activeElement, item1, "Should navigate backward to first span");
+  }, "Backward navigation should work with deeply nested focusgroup descendants");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item2, "Vertical navigation should work with nested descendants");
+  }, "Vertical navigation should work with nested descendants");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/mixed-content-navigation.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/mixed-content-navigation.html
new file mode 100644
index 0000000..77059c50
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/mixed-content-navigation.html
@@ -0,0 +1,96 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Navigation with mixed focusable and non-focusable descendants</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <span id=item1 tabindex=0>Item 1</span>
+
+  <div class="section">
+    <h3>Section Title</h3>
+    <p>Some descriptive text that is not focusable</p>
+    <span id=item2 tabindex=-1>Item 2</span>
+
+    <div>
+      <span>More non-focusable content</span>
+      <div>
+        <span>Nested non-focusable</span>
+        <span id=item3 tabindex=-1>Item 3</span>
+        <span>More text</span>
+      </div>
+    </div>
+  </div>
+
+  <div class="another-section">
+    <ul>
+      <li>List item (not focusable)</li>
+      <li><span id=item4 tabindex=-1>Item 4</span></li>
+      <li>Another list item</li>
+    </ul>
+  </div>
+
+  <footer>
+    <p>Footer content</p>
+    <span id=item5 tabindex=-1>Item 5</span>
+  </footer>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should skip non-focusable content and navigate to item2");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should skip non-focusable nested content and navigate to item3");
+
+    await focusAndKeyPress(item3, kArrowRight);
+    assert_equals(document.activeElement, item4, "Should skip list content and navigate to focusable span");
+
+    await focusAndKeyPress(item4, kArrowRight);
+    assert_equals(document.activeElement, item5, "Should skip footer text and navigate to final span");
+  }, "Navigation should skip non-focusable descendants and only move between focusable items");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+
+    item5.focus();
+    await focusAndKeyPress(item5, kArrowLeft);
+    assert_equals(document.activeElement, item4, "Should navigate backward to link");
+
+    await focusAndKeyPress(item4, kArrowLeft);
+    assert_equals(document.activeElement, item3, "Should navigate backward to nested span");
+
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item2, "Should navigate backward to span");
+
+    await focusAndKeyPress(item2, kArrowLeft);
+    assert_equals(document.activeElement, item1, "Should navigate backward to first item");
+  }, "Backward navigation should skip non-focusable descendants");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item2, "Vertical navigation should work with mixed content");
+  }, "Vertical navigation should work correctly with mixed focusable/non-focusable content");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/simple-descendant-test.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/simple-descendant-test.html
new file mode 100644
index 0000000..3bcfcbe
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/simple-descendant-test.html
@@ -0,0 +1,35 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Simple descendant navigation test</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <button id=item1 tabindex=0>Item 1</button>
+  <div>
+    <button id=item2 tabindex=-1>Item 2 (nested)</button>
+  </div>
+  <button id=item3 tabindex=-1>Item 3</button>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should navigate to nested item2");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should navigate to item3");
+  }, "Simple descendant navigation should work");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/various-element-types.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/various-element-types.html
new file mode 100644
index 0000000..426d177
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/various-element-types.html
@@ -0,0 +1,120 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Various element types work as focusgroup descendants</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <span id=item1 tabindex=0>Item 1</span>
+  <div>
+    <span id=item2 tabindex=-1>Item 2 (nested)</span>
+  </div>
+  <section>
+    <div>
+      <span id=item3 tabindex=-1>Item 3 (in section)</span>
+    </div>
+  </section>
+  <article>
+    <span id=item4 tabindex=-1>Item 4 (in article)</span>
+  </article>
+  <div>
+    <span id=item5 tabindex=-1>Item 5 (deeply nested)</span>
+  </div>
+  <nav>
+    <div>
+      <span id=item6 tabindex=-1>Item 6 (in nav)</span>
+    </div>
+  </nav>
+  <div>
+    <div tabindex=-1 id=item7>Item 7 (focusable div)</div>
+  </div>
+  <details>
+    <summary id=item8 tabindex=-1>Item 8 (summary)</summary>
+    <p>Details content</p>
+  </details>
+  <div>
+    <span id=item9 tabindex=-1>Item 9 (final)</span>
+  </div>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var item5 = document.getElementById("item5");
+    var item6 = document.getElementById("item6");
+    var item7 = document.getElementById("item7");
+    var item8 = document.getElementById("item8");
+    var item9 = document.getElementById("item9");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should navigate to nested item");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should navigate to item in section");
+
+    await focusAndKeyPress(item3, kArrowRight);
+    assert_equals(document.activeElement, item4, "Should navigate to item in article");
+
+    await focusAndKeyPress(item4, kArrowRight);
+    assert_equals(document.activeElement, item5, "Should navigate to deeply nested item");
+
+    await focusAndKeyPress(item5, kArrowRight);
+    assert_equals(document.activeElement, item6, "Should navigate to item in nav");
+
+    await focusAndKeyPress(item6, kArrowRight);
+    assert_equals(document.activeElement, item7, "Should navigate to focusable div");
+
+    await focusAndKeyPress(item7, kArrowRight);
+    assert_equals(document.activeElement, item8, "Should navigate to summary");
+
+    await focusAndKeyPress(item8, kArrowRight);
+    assert_equals(document.activeElement, item9, "Should navigate to final item");
+  }, "Navigation should work with items in various container types");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item8 = document.getElementById("item8");
+    var item9 = document.getElementById("item9");
+
+    item9.focus();
+    await focusAndKeyPress(item9, kArrowLeft);
+    assert_equals(document.activeElement, item8, "Should navigate backward from final item");
+
+    var current = document.activeElement;
+    await focusAndKeyPress(current, kArrowLeft);
+    assert_equals(document.activeElement, item7, "Should navigate backward to focusable div");
+  }, "Backward navigation should work with various container types");
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+
+    await focusAndKeyPress(item1, kArrowDown);
+    assert_equals(document.activeElement, item2, "Vertical navigation should work with different container types");
+  }, "Vertical navigation should work with various container types");
+
+  promise_test(async t => {
+    var root = document.getElementById("root");
+    var expectedElements = [
+      "item1", "item2", "item3", "item4", "item5",
+      "item6", "item7", "item8", "item9"
+    ];
+
+    for (let elementId of expectedElements) {
+      var element = document.getElementById(elementId);
+      element.focus();
+      assert_equals(document.activeElement, element, `${elementId} should be focusable`);
+    }
+  }, "All items in different container types should be focusable within focusgroup");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/wrapping-with-descendants.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/wrapping-with-descendants.html
new file mode 100644
index 0000000..8edc542
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/descendant-navigation/wrapping-with-descendants.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Wrapping works correctly with nested descendants</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar wrap">
+  <div class="first-section">
+    <button id=first tabindex=0>First Item</button>
+  </div>
+  <div class="middle-section">
+    <div>
+      <div>
+        <button id=middle tabindex=-1>Middle Item (nested)</button>
+      </div>
+    </div>
+  </div>
+  <div class="last-section">
+    <span>
+      <button id=last tabindex=-1>Last Item</button>
+    </span>
+  </div>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var first = document.getElementById("first");
+    var middle = document.getElementById("middle");
+    var last = document.getElementById("last");
+
+    last.focus();
+    await focusAndKeyPress(last, kArrowRight);
+    assert_equals(document.activeElement, first, "Should wrap from last nested item to first item");
+  }, "Forward wrapping should work from nested descendants to first item");
+
+  promise_test(async t => {
+    var first = document.getElementById("first");
+    var middle = document.getElementById("middle");
+    var last = document.getElementById("last");
+
+    first.focus();
+    await focusAndKeyPress(first, kArrowLeft);
+    assert_equals(document.activeElement, last, "Should wrap from first item to last nested item");
+  }, "Backward wrapping should work from first item to nested descendants");
+
+  promise_test(async t => {
+    var first = document.getElementById("first");
+    var middle = document.getElementById("middle");
+    var last = document.getElementById("last");
+
+    first.focus();
+    await focusAndKeyPress(first, kArrowRight);
+    assert_equals(document.activeElement, middle, "Should navigate normally to middle nested item");
+
+    await focusAndKeyPress(middle, kArrowRight);
+    assert_equals(document.activeElement, last, "Should navigate normally to last nested item");
+  }, "Normal navigation should still work correctly with nested items");
+
+  promise_test(async t => {
+    var first = document.getElementById("first");
+    var last = document.getElementById("last");
+
+    last.focus();
+    await focusAndKeyPress(last, kArrowDown);
+    assert_equals(document.activeElement, first, "Vertical wrapping should work with nested descendants");
+  }, "Vertical wrapping should work correctly with nested descendants");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/does-not-move-when-on-non-item.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/does-not-move-when-on-non-item.html
index b28ad33..c2627de 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/does-not-move-when-on-non-item.html
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/forward-navigation/does-not-move-when-on-non-item.html
@@ -10,14 +10,15 @@
 <script src="/resources/testdriver-actions.js"></script>
 <script src="../resources/focusgroup-utils.js"></script>
 
+<!-- Element outside focusgroup should not participate -->
+<span id=nonitem1 tabindex=0>nonitem1</span>
+
 <div tabindex=-1 focusgroup="toolbar">
-  <div>
-    <span id=nonitem1 tabindex=0>nonitem1</span>
-  </div>
   <span id=item1 tabindex=0>item1</span>
   <span id=item2 tabindex=-1>item2</span>
 </div>
 
+
 <script>
 
   promise_test(async t => {
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/complex-nested-opt-out.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/complex-nested-opt-out.html
new file mode 100644
index 0000000..bd72e0e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/complex-nested-opt-out.html
@@ -0,0 +1,129 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Complex opt-out scenarios with nested structures</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <button id=item1 tabindex=0>Item 1</button>
+
+  <div>
+    <button id=item2 tabindex=-1>Item 2</button>
+
+    <div id=optout1 focusgroup="none">
+      <button id=optout_item1 tabindex=-1>Opted out 1</button>
+
+      <div>
+        <button id=optout_item2 tabindex=-1>Opted out 2 (nested)</button>
+
+        <!-- Nested focusgroup within opt-out should function independently and not participate in ancestor group -->
+        <div id=nested_in_optout focusgroup="menu">
+          <button id=nested_optout_item1 tabindex=-1>Nested in opt-out 1</button>
+          <button id=nested_optout_item2 tabindex=-1>Nested in opt-out 2</button>
+        </div>
+      </div>
+
+      <!-- Another opt-out within opt-out (redundant but valid) -->
+      <div id=optout2 focusgroup="none">
+        <button id=double_optout tabindex=-1>Double opt-out</button>
+      </div>
+    </div>
+
+    <button id=item3 tabindex=-1>Item 3</button>
+  </div>
+
+  <div>
+    <div>
+      <button id=item4 tabindex=-1>Item 4 (deeply nested)</button>
+    </div>
+  </div>
+</div>
+
+<script>
+  promise_test(async t => {
+    const item1 = document.getElementById("item1");
+    const item2 = document.getElementById("item2");
+    const item3 = document.getElementById("item3");
+    const item4 = document.getElementById("item4");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should navigate to item2");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should skip entire opted-out section (including nested scope) and navigate to item3");
+
+    await focusAndKeyPress(item3, kArrowRight);
+    assert_equals(document.activeElement, item4, "Should navigate to deeply nested item4");
+  }, "Outer focusgroup navigation skips opted-out subtree");
+
+  promise_test(async t => {
+    const optout_item1 = document.getElementById("optout_item1");
+    const optout_item2 = document.getElementById("optout_item2");
+    const double_optout = document.getElementById("double_optout");
+
+    optout_item1.focus();
+    await focusAndKeyPress(optout_item1, kArrowRight);
+    assert_equals(document.activeElement, optout_item1, "Arrow keys should not move within opted-out generic subtree");
+
+    optout_item2.focus();
+    await focusAndKeyPress(optout_item2, kArrowRight);
+    assert_equals(document.activeElement, optout_item2, "Arrow keys should not move within opted-out generic subtree (nested)");
+
+    double_optout.focus();
+    await focusAndKeyPress(double_optout, kArrowRight);
+    assert_equals(document.activeElement, double_optout, "Double opt-out still blocks navigation");
+  }, "Opt-out subtree blocks navigation for its own items");
+
+  promise_test(async t => {
+    const nested_scope = document.getElementById("nested_in_optout");
+    const nested_item1 = document.getElementById("nested_optout_item1");
+    const nested_item2 = document.getElementById("nested_optout_item2");
+
+    nested_item1.focus();
+    await focusAndKeyPress(nested_item1, kArrowRight);
+    assert_equals(document.activeElement, nested_item2, "Nested focusgroup should allow forward navigation inside opt-out subtree");
+
+    await focusAndKeyPress(nested_item2, kArrowLeft);
+    assert_equals(document.activeElement, nested_item1, "Nested focusgroup should allow backward navigation inside opt-out subtree");
+
+    await focusAndKeyPress(nested_item1, kArrowLeft);
+    assert_equals(document.activeElement, nested_item1, "Backward navigation inside nested scope should not jump to outer items");
+  }, "Nested focusgroup inside opted-out subtree still works internally");
+
+  promise_test(async t => {
+    const item2 = document.getElementById("item2");
+    const item3 = document.getElementById("item3");
+    const item4 = document.getElementById("item4");
+
+    item4.focus();
+    await focusAndKeyPress(item4, kArrowLeft);
+    assert_equals(document.activeElement, item3, "Should navigate backward to item3");
+
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item2, "Should skip opted-out section backward and navigate to item2");
+  }, "Backward outer navigation skips opted-out subtree");
+
+  promise_test(async t => {
+    const root = document.getElementById("root");
+    const allButtons = Array.from(root.querySelectorAll("button"));
+    const outerGroupButtons = allButtons.filter(btn => {
+      for (let n = btn.parentElement; n; n = n.parentElement) {
+        if (n.hasAttribute("focusgroup") && n.getAttribute("focusgroup") === "none")
+          return false;
+        if (n.id === "nested_in_optout")
+          return false;
+        if (n.id === "root")
+          break;
+      }
+      return true;
+    });
+    const ids = outerGroupButtons.map(b => b.id).sort();
+    assert_array_equals(ids, ["item1","item2","item3","item4"], "Outer scope should only include four non-opted-out items");
+  }, "Outer focusgroup membership excludes opted-out and nested scope items");
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/none-creates-barriers.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/none-creates-barriers.html
new file mode 100644
index 0000000..5a9e5f35
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/opt-out-barriers/none-creates-barriers.html
@@ -0,0 +1,75 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>HTML Test: focusgroup - Opt-out creates navigation barriers</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=root focusgroup="toolbar">
+  <button id=item1 tabindex=0>Item 1</button>
+  <button id=item2 tabindex=-1>Item 2</button>
+
+  <div id=optout focusgroup="none">
+    <button id=optout_item1 tabindex=-1>Opted out item 1</button>
+    <div>
+      <button id=optout_item2 tabindex=-1>Opted out item 2</button>
+    </div>
+  </div>
+
+  <button id=item3 tabindex=-1>Item 3</button>
+  <button id=item4 tabindex=-1>Item 4</button>
+</div>
+
+<script>
+
+  promise_test(async t => {
+    var item1 = document.getElementById("item1");
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var optout_item1 = document.getElementById("optout_item1");
+
+    await focusAndKeyPress(item1, kArrowRight);
+    assert_equals(document.activeElement, item2, "Should navigate to item2");
+
+    await focusAndKeyPress(item2, kArrowRight);
+    assert_equals(document.activeElement, item3, "Should skip opted-out section and navigate to item3");
+
+    assert_not_equals(document.activeElement, optout_item1, "Should not navigate to opted-out item");
+  }, "Navigation should skip elements in opted-out focusgroup subtree");
+
+  promise_test(async t => {
+    var item2 = document.getElementById("item2");
+    var item3 = document.getElementById("item3");
+    var item4 = document.getElementById("item4");
+    var optout_item1 = document.getElementById("optout_item1");
+
+    item4.focus();
+    await focusAndKeyPress(item4, kArrowLeft);
+    assert_equals(document.activeElement, item3, "Should navigate to item3");
+
+    await focusAndKeyPress(item3, kArrowLeft);
+    assert_equals(document.activeElement, item2, "Should skip opted-out section and navigate to item2");
+
+    assert_not_equals(document.activeElement, optout_item1, "Should not navigate to opted-out item from reverse");
+  }, "Backward navigation should skip elements in opted-out focusgroup subtree");
+
+  promise_test(async t => {
+    var optout_item1 = document.getElementById("optout_item1");
+    var optout_item2 = document.getElementById("optout_item2");
+
+    optout_item1.focus();
+    assert_equals(document.activeElement, optout_item1, "Should be able to manually focus opted-out item");
+
+    await focusAndKeyPress(optout_item1, kArrowRight);
+    assert_equals(document.activeElement, optout_item1, "Arrow keys should not work within opted-out section");
+
+    await focusAndKeyPress(optout_item1, kArrowDown);
+    assert_equals(document.activeElement, optout_item1, "Vertical arrow keys should not work within opted-out section");
+  }, "Arrow keys should not work within opted-out focusgroup sections");
+
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/resources/focusgroup-utils.js b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/resources/focusgroup-utils.js
index 9a1a14a..0cdc146 100644
--- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/resources/focusgroup-utils.js
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/resources/focusgroup-utils.js
@@ -13,3 +13,7 @@
   target.focus();
   return test_driver.send_keys(target, key);
 }
+
+function sendArrowKey(key) {
+  return new test_driver.Actions().keyDown(key).keyUp(key).send();
+}
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-items-basic.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-items-basic.html
new file mode 100644
index 0000000..e6fb928
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-items-basic.html
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>focusgroup: shadow DOM items navigation</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<!-- In the scoped focusgroup model the behavior token (e.g. toolbar) must be
+  the first token. The focusgroup scope includes the element with the
+  attribute and its shadow-inclusive descendants. To exercise cross shadow
+  boundary behavior, put the focusgroup on the shadow host itself. -->
+<div id=host focusgroup="toolbar inline"></div>
+
+<script>
+  function deepActiveElement(root = document) {
+    let a = root.activeElement;
+    while (a && a.shadowRoot && a.shadowRoot.activeElement) {
+      a = a.shadowRoot.activeElement;
+    }
+    return a;
+  }
+  promise_test(async t => {
+    const host = document.getElementById('host');
+    const sr = host.attachShadow({mode: 'open'});
+    sr.innerHTML = `
+      <button id=item1 tabindex=0>One</button>
+      <button id=item2 tabindex=-1>Two</button>
+      <button id=item3 tabindex=-1>Three</button>`;
+    const item1 = sr.getElementById('item1');
+    const item2 = sr.getElementById('item2');
+    const item3 = sr.getElementById('item3');
+
+    item1.focus();
+    assert_equals(sr.activeElement, item1, 'Initial focus on item1 (shadow)');
+    assert_equals(deepActiveElement(), item1, 'Deep active element is item1');
+    await sendArrowKey(kArrowRight);
+    assert_equals(sr.activeElement, item2, 'Advance to item2');
+    assert_equals(deepActiveElement(), item2, 'Deep active element is item2');
+
+    await sendArrowKey(kArrowRight);
+    assert_equals(sr.activeElement, item3, 'Advance to item3');
+    assert_equals(deepActiveElement(), item3, 'Deep active element is item3');
+
+    await sendArrowKey(kArrowRight);
+    assert_equals(sr.activeElement, item3, 'No wrap; remains on item3');
+    assert_equals(deepActiveElement(), item3, 'Deep active element remains item3');
+  }, 'Shadow host focusgroup scopes shadow root items for navigation');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-nested-scope.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-nested-scope.html
new file mode 100644
index 0000000..154793ee
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/focusgroup/tentative/shadow/shadow-nested-scope.html
@@ -0,0 +1,52 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>focusgroup: nested shadow focusgroup isolation</title>
+<link rel="author" title="Microsoft" href="http://www.microsoft.com/">
+<link rel="help" href="https://open-ui.org/components/scoped-focusgroup.explainer/">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="../resources/focusgroup-utils.js"></script>
+
+<div id=outer_fg focusgroup="toolbar inline">
+  <button id=outer1 tabindex=0>Outer 1</button>
+  <div id=shadow_host></div>
+  <button id=outer2 tabindex=-1>Outer 2</button>
+</div>
+
+<script>
+  function deepActiveElement(root = document) {
+    let a = root.activeElement;
+    while (a && a.shadowRoot && a.shadowRoot.activeElement) {
+      a = a.shadowRoot.activeElement;
+    }
+    return a;
+  }
+  promise_test(async t => {
+    const host = document.getElementById('shadow_host');
+    const sr = host.attachShadow({mode: 'open'});
+    sr.innerHTML = `
+      <div id=inner_fg focusgroup="menu inline">
+        <button id=inner1 tabindex=0>Inner 1</button>
+        <button id=inner2 tabindex=-1>Inner 2</button>
+      </div>`;
+    const outer1 = document.getElementById('outer1');
+    const outer2 = document.getElementById('outer2');
+    const inner1 = sr.getElementById('inner1');
+    const inner2 = sr.getElementById('inner2');
+
+    await focusAndKeyPress(outer1, kArrowRight);
+    assert_equals(document.activeElement, outer2, 'Outer navigation skips inner shadow scope');
+    assert_equals(deepActiveElement(), outer2, 'Deep active element is outer2 after outer navigation');
+
+    inner1.focus();
+    await sendArrowKey(kArrowRight);
+    assert_equals(sr.activeElement, inner2, 'Inner navigation advances');
+    assert_equals(deepActiveElement(), inner2, 'Deep active element is inner2');
+    await sendArrowKey(kArrowRight);
+    assert_equals(sr.activeElement, inner2, 'No wrap inside inner scope');
+    assert_equals(deepActiveElement(), inner2, 'Deep active element remains inner2');
+  }, 'Nested shadow focusgroup is isolated from outer scope navigation');
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandfor-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandfor-expected.txt
deleted file mode 100644
index f216433..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandfor-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Focusing elements inside a popover with a details element inside, using commandfor
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a details element inside, and the after button adjacent to invoker, using commandfor
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with delegatesfocus inside, using commandfor
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with a slotted button inside, using commandfor
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with custom-element with a slotted button, followed by a details element, where the after button is adjacent to the invoker, using commandfor
-  assert_equals: tab press should move to active element 2 expected "2" but got "after"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandforelement-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandforelement-expected.txt
deleted file mode 100644
index d4a3381c..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_commandforelement-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Focusing elements inside a popover with a details element inside, using commandforelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a details element inside, and the after button adjacent to invoker, using commandforelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with delegatesfocus inside, using commandforelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with a slotted button inside, using commandforelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with custom-element with a slotted button, followed by a details element, where the after button is adjacent to the invoker, using commandforelement
-  assert_equals: tab press should move to active element 2 expected "2" but got "after"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_imperative-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_imperative-expected.txt
deleted file mode 100644
index 93243f3..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_imperative-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Focusing elements inside a popover with a details element inside, using imperative
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a details element inside, and the after button adjacent to invoker, using imperative
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with delegatesfocus inside, using imperative
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with a slotted button inside, using imperative
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with custom-element with a slotted button, followed by a details element, where the after button is adjacent to the invoker, using imperative
-  assert_equals: tab press should move to active element 2 expected "2" but got "after"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_popovertargetelement-expected.txt b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_popovertargetelement-expected.txt
deleted file mode 100644
index e7b5535..0000000
--- a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-5_popovertargetelement-expected.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] Focusing elements inside a popover with a details element inside, using popovertargetelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a details element inside, and the after button adjacent to invoker, using popovertargetelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with delegatesfocus inside, using popovertargetelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with a custom-element with a slotted button inside, using popovertargetelement
-  assert_equals: tab press should move to close popover button expected "close" but got "after"
-[FAIL] Focusing elements inside a popover with custom-element with a slotted button, followed by a details element, where the after button is adjacent to the invoker, using popovertargetelement
-  assert_equals: tab press should move to active element 2 expected "2" but got "after"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-across-slot.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-across-slot.html
new file mode 100644
index 0000000..25ccdb4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-across-slot.html
@@ -0,0 +1,55 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Popover focus behaviors in form control elements</title>
+<meta name="timeout" content="long" />
+<link rel="author" title="Peng Zhou" href="mailto:zhoupeng.1996@bytedance.com">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/shadow-dom.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<div popover id="popover">
+  <div id="host">
+    <template shadowrootmode="open">
+      <div>
+        <div>
+          <div>
+            <slot></slot>
+            <button id="close">Close popover</button>
+          </div>
+        </div>
+      </div>
+    </template>
+    <div>
+      <input type="checkbox" id="target1" />
+      <input type="checkbox" id="target2" />
+    </div>
+  </div>
+</div>
+<button popovertarget="popover" id="invoker">Open popover</button>
+<button id="after">
+  This button is where focus should land after traversing this popover
+</button>
+
+<script>
+promise_test(async () => {
+  // Open popover
+  invoker.focus();
+  assert_equals(document.activeElement, invoker);
+  invoker.click();
+  assert_true(popover.matches(":popover-open"));
+
+  await assert_focus_navigation_bidirectional([
+    'invoker',
+    'target1',
+    'target2',
+    'host/close',
+    'after',
+  ]);
+});
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-form-control.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-form-control.html
new file mode 100644
index 0000000..9d7cbdf
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-form-control.html
@@ -0,0 +1,52 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Popover focus behaviors in form control elements</title>
+<meta name="timeout" content="long" />
+<link rel="author" title="Peng Zhou" href="mailto:zhoupeng.1996@bytedance.com">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/shadow-dom.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<div>
+  <button popovertarget="popover" id="invoker">Open popover</button>
+  <div popover id="popover">
+    <input type="checkbox" id="target1" />
+    <input type="checkbox" id="target2" />
+    <my-element id="host">
+      <template shadowrootmode="open">
+        <input type="checkbox" id="target3" />
+        <input type="checkbox" id="target4" />
+      </template>
+    </my-element>
+    <button id="close">Close popover</button>
+  </div>
+  <button id="after">
+    This button is where focus should land after traversing this popover
+  </button>
+</div>
+
+<script>
+promise_test(async () => {
+  // Open popover
+  invoker.focus();
+  invoker.click();
+  assert_true(popover.matches(":popover-open"));
+  assert_equals(document.activeElement, invoker);
+
+  await assert_focus_navigation_bidirectional([
+    'invoker',
+    'target1',
+    'target2',
+    'host/target3',
+    'host/target4',
+    'close',
+    'after',
+  ]);
+}, 'Focus navigation for form controls contained in a popover');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-shadow-dom.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-shadow-dom.html
new file mode 100644
index 0000000..a23bd7e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-shadow-dom.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Popover focus behaviors inside shadow DOM</title>
+<meta name="timeout" content="long" />
+<link rel="author" title="Peng Zhou" href="mailto:zhoupeng.1996@bytedance.com">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/shadow-dom.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<my-element id="host">
+  <template shadowrootmode="open">
+    <button popovertarget="popover" id="invoker">Open popover</button>
+    <div popover id="popover">
+      <input type="checkbox" id="target1" />
+      <input type="checkbox" id="target2" />
+      <button id="close">Close popover</button>
+    </div>
+    <button id="after">
+      This button is where focus should land after traversing this popover
+    </button>
+  </template>
+</my-element>
+
+<script>
+promise_test(async () => {
+  const shadowRoot = host.shadowRoot;
+  const invoker = shadowRoot.getElementById('invoker');
+  const popover = shadowRoot.getElementById('popover');
+  // Open popover
+  invoker.focus();
+  invoker.click();
+  assert_true(popover.matches(":popover-open"));
+  assert_equals(document.activeElement, host);
+  assert_equals(document.activeElement.shadowRoot.activeElement, invoker);
+
+  await assert_focus_navigation_bidirectional([
+    'host/invoker',
+    'host/target1',
+    'host/target2',
+    'host/close',
+    'host/after',
+  ]);
+}, 'Focus behavior of popover elements inside shadow DOM');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-slot.html b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-slot.html
new file mode 100644
index 0000000..40ff34b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/popovers/popover-focus-inside-slot.html
@@ -0,0 +1,50 @@
+<!doctype html>
+<meta charset="utf-8" />
+<title>Popover focus behaviors inside shadow DOM</title>
+<meta name="timeout" content="long" />
+<link rel="author" title="Peng Zhou" href="mailto:zhoupeng.1996@bytedance.com">
+<link rel=help href="https://open-ui.org/components/popover.research.explainer">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/resources/testdriver.js"></script>
+<script src="/resources/testdriver-actions.js"></script>
+<script src="/resources/testdriver-vendor.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/focus-utils.js"></script>
+<script src="/shadow-dom/focus-navigation/resources/shadow-dom.js"></script>
+<script src="resources/popover-utils.js"></script>
+
+<div>
+  <template shadowrootmode="open">
+    <slot name=invoker></slot>
+    <slot name=popover></slot>
+    <slot name=after></slot>
+  </template>
+  <button slot=invoker popovertarget="popover" id="invoker">Open
+       popover</button>
+  <div slot=popover popover id="popover">
+    <input type="checkbox" id="target1" />
+    <input type="checkbox" id="target2" />
+    <button id="close">Close popover</button>
+  </div>
+  <button slot=after id="after">
+    This button is where focus should land after traversing this popover
+  </button>
+</div>
+
+<script>
+promise_test(async () => {
+  // Open popover
+  invoker.focus();
+  invoker.click();
+  assert_true(popover.matches(":popover-open"));
+  assert_equals(document.activeElement, invoker);
+
+  await assert_focus_navigation_bidirectional([
+    'invoker',
+    'target1',
+    'target2',
+    'close',
+    'after',
+  ]);
+}, 'Focus behavior of popover elements inside slot');
+</script>
diff --git a/third_party/blink/web_tests/external/wpt/streams/OWNERS b/third_party/blink/web_tests/external/wpt/streams/OWNERS
index 0431035..4392ef47 100644
--- a/third_party/blink/web_tests/external/wpt/streams/OWNERS
+++ b/third_party/blink/web_tests/external/wpt/streams/OWNERS
@@ -1,2 +1 @@
-domenic@chromium.org
 ricea@chromium.org
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/matmul.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/matmul.https.any.js
index 0e13391..13aaccfe 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/matmul.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/matmul.https.any.js
@@ -13,17 +13,6 @@
 // MLOperand matmul(MLOperand a, MLOperand b);
 
 
-const getMatmulPrecisionTolerance = (graphResources) => {
-  const args = graphResources.operators[0].arguments;
-  const shapeA =
-      graphResources.inputs[args[0][Object.keys(args[0])[0]]].descriptor.shape;
-  const tolerance = shapeA[shapeA.length - 1] * 2;
-  const toleranceValueDict = {float32: tolerance, float16: tolerance};
-  const expectedDataType =
-      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
-  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
-};
-
 const matmulTests = [
   {
     'name': 'matmul float32 2D and 2D tensors',
@@ -1096,4 +1085,4 @@
 ];
 
 webnn_conformance_test(
-    matmulTests, buildAndExecuteGraph, getMatmulPrecisionTolerance);
+    matmulTests, buildAndExecuteGraph, getPrecisionTolerance);
diff --git a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/subgraph.https.any.js b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/subgraph.https.any.js
index 990aa45..190ad0b 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/subgraph.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/conformance_tests/subgraph.https.any.js
@@ -2524,6 +2524,58 @@
     }
   },
   {
+    'name': 'gatherElements + matmul',
+    'graph': {
+      'inputs': {
+        'gatherElementsInput': {
+          'data': [
+            -66.05901336669922, -68.9197006225586, -77.02045440673828,
+            -26.158037185668945, 89.0337142944336, -45.89653396606445,
+            43.84803771972656, 48.81806945800781, 51.79948425292969
+          ],
+          'descriptor': {shape: [3, 3], dataType: 'float32'}
+        },
+        'gatherElementsIndices': {
+          'data': [1, 0, 2, 2, 1, 0],
+          'descriptor': {shape: [2, 3], dataType: 'int32'},
+          'constant': true
+        },
+        'matmulB': {
+          'data': [
+            56.46701431274414,  99.86045837402344,  71.054931640625,
+            32.454383850097656, 17.310747146606445, 2.586275100708008,
+          ],
+          'descriptor': {shape: [3, 2], dataType: 'float32'}
+        },
+      },
+      'operators': [
+        {
+          'name': 'gatherElements',
+          'arguments': [
+            {'input': 'gatherElementsInput'}, {'indices': 'gatherElementsIndices'}
+          ],
+          'outputs': 'gatherElementsOutput'
+        },
+        {
+          'name': 'matmul',
+          'arguments': [
+            {'a': 'gatherElementsOutput'}, {'b': 'matmulB'}
+          ],
+          'outputs': 'matmulOutput'
+        }
+      ],
+      'expectedOutputs': {
+        'matmulOutput': {
+          'data': [
+            -5477.462890625, -4714.93212890625,
+            7468.97021484375, 7069.02294921875
+          ],
+          'descriptor': {shape: [2, 2], dataType: 'float32'}
+        }
+      }
+    }
+  },
+  {
     'name': 'float16 graph with float32 input and output',
     'graph': {
       'inputs': {
diff --git a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js
index 6b24f2d..8294130 100644
--- a/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js
+++ b/third_party/blink/web_tests/external/wpt/webnn/resources/utils.js
@@ -89,6 +89,10 @@
         toleranceValue += getGemmPrecisionTolerance(op, graphResources,
             intermediateOperands).value;
         break;
+      case 'matmul':
+        toleranceValue += getMatmulPrecisionTolerance(op, graphResources,
+            intermediateOperands).value;
+        break;
       case 'softmax':
         toleranceValue += getSoftmaxPrecisionTolerance(
                               op, graphResources, intermediateOperands)
@@ -1107,6 +1111,24 @@
   return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
 };
 
+const getMatmulPrecisionTolerance =
+    (op, graphResources, intermediateOperands) => {
+  const {inputs} = graphResources;
+  const args = op.arguments;
+  let shapeA;
+  const indexA = args[0][Object.keys(args[0])[0]];
+  if (inputs[indexA]) {
+    shapeA = inputs[indexA].descriptor.shape;
+  } else {
+    shapeA = intermediateOperands[indexA].shape;
+  }
+  const tolerance = shapeA[shapeA.length - 1] * 2;
+  const toleranceValueDict = {float32: tolerance, float16: tolerance};
+  const expectedDataType =
+      getExpectedDataTypeOfSingleOutput(graphResources.expectedOutputs);
+  return {metricType: 'ULP', value: toleranceValueDict[expectedDataType]};
+};
+
 const getConv2dPrecisionTolerance =
     (op, graphResources, intermediateOperands) => {
   // number of reduced input elements multiplied by filter and summed (a sliding
diff --git a/third_party/blink/web_tests/fast/forms/validation-bubble-appearance-viewport-bottom.html b/third_party/blink/web_tests/fast/forms/validation-bubble-appearance-viewport-bottom.html
new file mode 100644
index 0000000..d1337c1
--- /dev/null
+++ b/third_party/blink/web_tests/fast/forms/validation-bubble-appearance-viewport-bottom.html
@@ -0,0 +1,12 @@
+<!DOCTYPE html>
+<meta name="color-scheme" content="light dark">
+<script src="../../resources/run-after-layout-and-paint.js"></script>
+<p>Check if a validation bubble is shown at a correct position.</p>
+<input style="position:absolute; bottom:20px;">
+<script>
+runAfterLayoutAndPaint(() => {
+  const input = document.querySelector('input');
+  input.setCustomValidity('This is a test validation message.');
+  input.reportValidity();
+}, true);
+</script>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index d271520..dcaa6ae 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1775,6 +1775,7 @@
     method clone
     method constructor
     method formData
+    method getRetryOptions
     method json
     method text
 interface Response
diff --git a/third_party/blink/web_tests/platform/linux/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png b/third_party/blink/web_tests/platform/linux/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
new file mode 100644
index 0000000..d3b9690
--- /dev/null
+++ b/third_party/blink/web_tests/platform/linux/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png b/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
new file mode 100644
index 0000000..39fb23a
--- /dev/null
+++ b/third_party/blink/web_tests/platform/mac/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png b/third_party/blink/web_tests/platform/win/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
new file mode 100644
index 0000000..b53fcab
--- /dev/null
+++ b/third_party/blink/web_tests/platform/win/fast/forms/validation-bubble-appearance-viewport-bottom-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index e8ba040e..fb2649fb 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1918,6 +1918,7 @@
 [Worker]     method clone
 [Worker]     method constructor
 [Worker]     method formData
+[Worker]     method getRetryOptions
 [Worker]     method json
 [Worker]     method text
 [Worker] interface Response
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index f45d92c..fbd47d48 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -8264,6 +8264,7 @@
     method clone
     method constructor
     method formData
+    method getRetryOptions
     method json
     method text
 interface ResizeObserver
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index 4ecff831..ecc41b218 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1691,6 +1691,7 @@
 [Worker]     method clone
 [Worker]     method constructor
 [Worker]     method formData
+[Worker]     method getRetryOptions
 [Worker]     method json
 [Worker]     method text
 [Worker] interface Response
diff --git a/third_party/dawn b/third_party/dawn
index fd1225f..78fff7b 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit fd1225f5306e0f879ceed9f389e2f7d68488002c
+Subproject commit 78fff7bf05e787a29cfd37a037c2cb63a55e923a
diff --git a/third_party/depot_tools b/third_party/depot_tools
index e8e09ca..3008b57 160000
--- a/third_party/depot_tools
+++ b/third_party/depot_tools
@@ -1 +1 @@
-Subproject commit e8e09ca53f60e795fee64892aec3f8f3f997d362
+Subproject commit 3008b57e5d18ee9c92baf851dd33c61cfd6fad21
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 88892c1..719e4cb 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 88892c172e1091cf6163adffd0f094fbb5c56325
+Subproject commit 719e4cbccab5277c60c67869c06d2741cd0919be
diff --git a/third_party/fuzztest/src b/third_party/fuzztest/src
index 8491407..f505c8b 160000
--- a/third_party/fuzztest/src
+++ b/third_party/fuzztest/src
@@ -1 +1 @@
-Subproject commit 84914079865928884331819a7952c5d66c516ce5
+Subproject commit f505c8ba2faf9806900e72aeb52fa68ade30d8b7
diff --git a/third_party/skia b/third_party/skia
index ce23f01..1724cea 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit ce23f015d43b027ee200e6038b22c559fb459c2a
+Subproject commit 1724ceaf73c4616f06582d8ef7104da6e4d4792e
diff --git a/third_party/spirv-headers/src b/third_party/spirv-headers/src
index a516482..9268f30 160000
--- a/third_party/spirv-headers/src
+++ b/third_party/spirv-headers/src
@@ -1 +1 @@
-Subproject commit a5164829e8f0255392c481696b63763a5e80be3c
+Subproject commit 9268f3057354a2cb65991ba5f38b16d81e803692
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index 103f88b..b197e9d 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit 103f88b8d55f294ebfb66d188b718157f410ad45
+Subproject commit b197e9ddd86d6105721f0f2eb48298f0adffa4e6
diff --git a/third_party/vulkan-headers/src b/third_party/vulkan-headers/src
index f5fad0a2..33d7f51 160000
--- a/third_party/vulkan-headers/src
+++ b/third_party/vulkan-headers/src
@@ -1 +1 @@
-Subproject commit f5fad0a209a2e09eb5e622d930d5eade1a235b13
+Subproject commit 33d7f512583b8de44d1b6384aa1cf482f92e53e9
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index c5efe5a..6f5b5a4 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit c5efe5a2f1bbb905ee8e4ee0a29f62274f9ddee6
+Subproject commit 6f5b5a4b034768139ff4fd1d797f6955d16e0f86
diff --git a/third_party/webrtc b/third_party/webrtc
index 4c45016d..8799eb9 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 4c45016de25d27c0809ef4efcfc3165990534144
+Subproject commit 8799eb90b451d970ac637022ceeb9bbc3460f269
diff --git a/tools/android/build_speed/README.md b/tools/android/build_speed/README.md
index ca23a498..c1a8ef5 100644
--- a/tools/android/build_speed/README.md
+++ b/tools/android/build_speed/README.md
@@ -4,32 +4,164 @@
 
 ## Best Practices
 
-* Ensure that the workstation is not being used while running any benchmarks.
+- Ensure that the workstation is not being used while running any benchmarks.
   This helps increase the reproducibility of these benchmarks.
-* Avoid making code edits while a benchmark is running, since it may break
+- Avoid making code edits while a benchmark is running, since it may break
   in-progress builds.
 
 ## Tool: `benchmark.py`
 
-This script can be used to measure several benchmarks for build speed. Simply
-run `tools/android/build_speed/benchmark.py -h` to see example input/output and
-a list of available benchmarks and suites.
-
-Suites are a collection of benchmarks and can be passed by name the same way as
-any individual benchmark. This is convenient if you want to run a set of
-benchmarks one after the other. e.g. the `all_incremental` suite runs all
-incremental benchmarks in serial.
-
-Since most benchmarks require the full capacity and parallelism of the
-workstation, there is no option to run benchmarks in parallel.
+This script can be used to measure several benchmarks for build speed, such as
+GN generation time and incremental build times after various simulated code
+changes.
 
 This tool will modify certain source files in your current src repository during
 benchmarks. It will attempt to restore those files to their original content
 after completing all benchmarks.
 
+### Quick Start
+
+To run a common suite of incremental build benchmarks on an emulator, run:
+
+```bash
+tools/android/build_speed/benchmark.py all_incremental --emulator <your_avd_name>
+```
+
+Where `<your_avd_name>` can be a filename like:
+`android_30_google_apis_x86.textpb`.
+
+### Command-line Options
+
+```
+usage: benchmark.py [-h] [--bundle] [--test] [--no-server]
+                    [--no-incremental-install] [--no-component-build]
+                    [--build-64bit] [-r REPEAT] [-C OUTPUT_DIRECTORY]
+                    [--emulator EMULATOR] [--target TARGET] [-v] [-q] [--json]
+                    [-n]
+                    [BENCHMARK ...]
+
+Tool to run build benchmarks (e.g. incremental build time).
+
+Example Command:
+    tools/android/build_speed/benchmark.py all_incremental
+
+Example Output:
+    Summary
+    gn args: target_os="android" use_remoteexec=true incremental_install=true
+    gn_gen: 6.7s
+    chrome_nosig: 36.1s avg (35.9s, 36.3s)
+    chrome_sig: 38.9s avg (38.8s, 39.1s)
+    base_nosig: 41.0s avg (41.1s, 40.9s)
+    base_sig: 93.1s avg (93.1s, 93.2s)
+
+Note: This tool will make edits on files in your local repo. It will revert the
+      edits afterwards.
+
+Suites and Individual Benchmarks:
+    all_incremental
+    all_chrome_java
+    all_module_java
+    all_base_java
+    extra_incremental
+    chrome_nosig
+    chrome_sig
+    module_public_sig
+    module_internal_nosig
+    base_nosig
+    base_sig
+    turbine_headers
+    compile_java
+    errorprone
+    write_build_config
+    cta_test_sig
+
+positional arguments:
+  BENCHMARK             Names of benchmark(s) or suites(s) to run.
+
+options:
+  -h, --help            show this help message and exit
+  --bundle              Switch the default target from apk to bundle.
+  --test                Switch the default target to a test apk.
+  --no-server           Do not start a faster local dev server before running
+                        the test.
+  --no-incremental-install
+                        Do not use incremental install.
+  --no-component-build  Turn off component build.
+  --build-64bit         Build 64-bit by default, even with no emulator.
+  -r, --repeat REPEAT   Number of times to repeat the benchmark.
+  -C, --output-directory OUTPUT_DIRECTORY
+                        If outdir is not provided, will attempt to guess.
+  --emulator EMULATOR   Specify this to override the default emulator.
+  --target TARGET       Specify this to override the default target.
+  -v, --verbose         1 to print logging, 2 to print ninja output.
+  -q, --quiet           Do not print the summary.
+  --json                Output machine-readable output per benchmark.
+  -n, --dry-run         Do everything except the build/test/run steps, which
+                        will return random times.
+```
+
+### Usage
+
+To see all available options, benchmarks, and suites, run:
+
+```bash
+tools/android/build_speed/benchmark.py -h
+```
+
+You can run individual benchmarks or suites of benchmarks. Suites are a
+collection of benchmarks and can be passed by name the same way as any
+individual benchmark. This is convenient if you want to run a set of benchmarks
+one after the other. e.g. the `all_incremental` suite runs all incremental
+benchmarks in serial.
+
+To repeat a benchmark multiple times, use the `-r` or `--repeat` flag:
+
+```bash
+tools/android/build_speed/benchmark.py -r 3 chrome_sig
+```
+
+### Emulator
+
+Some benchmarks measure install and run times, which require a running Android
+emulator. Use the `--emulator` flag to specify the AVD config name for the
+emulator you want to use. The available emulator configs can be found in
+[`//tools/android/avd/proto`](../../../tools/android/avd/proto).
+
+If an emulator is required and not specified, the script will error.
+
+### Output
+
+The script outputs timings for different stages of the build process. For a
+benchmark named `example_benchmark`, you might see:
+
+- `example_benchmark_compile`: Time to compile the target after the code change.
+- `example_benchmark_install`: Time to install the target on the device.
+- `example_benchmark_run`: Time to run the test on the device (for test
+  targets).
+
+### Configuration
+
+You can customize the build configuration with various flags:
+
+- `--no-server`: Do not use the faster local development server.
+- `--no-incremental-install`: Disable incremental install.
+- `--bundle` or `--test`: Change the build target to a bundle or test APK
+  instead of the default APK.
+
+Since most benchmarks require the full capacity and parallelism of the
+workstation, there is no option to run benchmarks in parallel.
+
+### Running Tests
+
+To run the unit tests for this script, use the following command:
+
+```bash
+vpython3 tools/android/build_speed/benchmark_unittest.py
+```
+
 ## Future plans
 
-* Add a script to compare benchmarks between two revisions.
-* Add options to allow ninja tracing files to be stored and examined for each
+- Add a script to compare benchmarks between two revisions.
+- Add options to allow ninja tracing files to be stored and examined for each
   benchmark.
-* Separate out time used by ninja versus time used by build steps.
+- Separate out time used by ninja versus time used by build steps.
diff --git a/tools/android/build_speed/benchmark.py b/tools/android/build_speed/benchmark.py
index cd4dc2af..c92ce93 100755
--- a/tools/android/build_speed/benchmark.py
+++ b/tools/android/build_speed/benchmark.py
@@ -169,8 +169,8 @@
     ),
     Benchmark(
         name='module_public_sig',
-        from_string='INVALID_WINDOW_INDEX = -1',
-        to_string='INVALID_WINDOW_INDEX = -<sub>',
+        from_string='INVALID_WINDOW_ID = -1',
+        to_string='INVALID_WINDOW_ID = -<sub>',
         change_file=
         'chrome/browser/tabwindow/android/java/src/org/chromium/chrome/browser/tabwindow/TabWindowManager.java',  # pylint: disable=line-too-long
         can_install=True,
@@ -314,8 +314,11 @@
         logging.info('Stopped emulator.')
 
 
-def _run_and_time_cmd(cmd: List[str]) -> float:
+def _run_and_time_cmd(cmd: List[str], *, dry_run: bool) -> float:
     logging.debug('Running %s', cmd)
+    if dry_run:
+        logging.warning('Dry run, skipping and returning random time.')
+        return random.uniform(1.0, 10.0)
     start = time.time()
     try:
         # Since output can be verbose, only show it for debug/errors.
@@ -339,11 +342,12 @@
     return time.time() - start
 
 
-def _run_gn_gen(out_dir: pathlib.Path) -> float:
+def _run_gn_gen(out_dir: pathlib.Path, *, dry_run: bool) -> float:
     return _run_and_time_cmd(
         [sys.executable,
          str(_GN_PATH), 'gen', '-C',
-         str(out_dir)])
+         str(out_dir)],
+        dry_run=dry_run)
 
 
 def _terminate_build_server_if_needed(out_dir: pathlib.Path):
@@ -366,17 +370,17 @@
         raise Exception('Build server still running after waiting 5s.')
 
 
-def _compile(out_dir: pathlib.Path, target: str) -> float:
+def _compile(out_dir: pathlib.Path, target: str, *, dry_run: bool) -> float:
     cmd = gn_helpers.CreateBuildCommand(str(out_dir))
     try:
-        return _run_and_time_cmd(cmd + [target])
+        return _run_and_time_cmd(cmd + [target], dry_run=dry_run)
     finally:
         # This ensures that the build server does not affect subsequent runs.
         _terminate_build_server_if_needed(out_dir)
 
 
-def _run_install(out_dir: pathlib.Path, target: str,
-                 device_serial: str) -> float:
+def _run_install(out_dir: pathlib.Path, target: str, device_serial: str, *,
+                 dry_run: bool) -> float:
     # Example script path: out/Debug/bin/chrome_public_apk
     script_path = out_dir / 'bin' / target
     # Disable first run to get a more accurate timing of startup.
@@ -387,11 +391,11 @@
     ]
     if logging.getLogger().isEnabledFor(logging.DEBUG):
         cmd += ['-vv']
-    return _run_and_time_cmd(cmd)
+    return _run_and_time_cmd(cmd, dry_run=dry_run)
 
 
 def _run_test(out_dir: pathlib.Path, target: str, device_serial: str,
-              test_filter: str) -> float:
+              test_filter: str, *, dry_run: bool) -> float:
     # Example script path: out/Debug/bin/run_chrome_public_test_apk
     script_path = out_dir / 'bin' / f'run_{target}'
     cmd = [str(script_path), '--fast-local-dev', '--device', device_serial]
@@ -399,33 +403,43 @@
         cmd += ['-f', test_filter]
     if logging.getLogger().isEnabledFor(logging.DEBUG):
         cmd += ['-vv']
-    return _run_and_time_cmd(cmd)
+    return _run_and_time_cmd(cmd, dry_run=dry_run)
 
 
-def _execute_benchmark_stages(
-        benchmark: Benchmark, out_dir: pathlib.Path, target: str,
-        emulator: Optional[device_utils.DeviceUtils]
-) -> List[Tuple[str, float]]:
+def _execute_benchmark_stages(benchmark: Benchmark, out_dir: pathlib.Path,
+                              target: str,
+                              emulator: Optional[device_utils.DeviceUtils], *,
+                              dry_run: bool) -> List[Tuple[str, float]]:
     if benchmark.can_install or benchmark.can_run:
         assert emulator, f'An emulator is required for {benchmark}'
-    results = [(f'{benchmark.name}_compile', _compile(out_dir, target))]
+    results = [(f'{benchmark.name}_compile',
+                _compile(out_dir, target, dry_run=dry_run))]
     if benchmark.can_install:
         results.append((f'{benchmark.name}_install',
-                        _run_install(out_dir, target, emulator.serial)))
+                        _run_install(out_dir,
+                                     target,
+                                     emulator.serial,
+                                     dry_run=dry_run)))
     if benchmark.can_run:
         results.append((f'{benchmark.name}_run',
-                        _run_test(out_dir, target, emulator.serial,
-                                  benchmark.test_filter)))
+                        _run_test(out_dir,
+                                  target,
+                                  emulator.serial,
+                                  benchmark.test_filter,
+                                  dry_run=dry_run)))
     return results
 
 
-def _run_benchmark(
-        benchmark: Benchmark, out_dir: pathlib.Path, target: str,
-        emulator: Optional[device_utils.DeviceUtils]
-) -> List[Tuple[str, float]]:
+def _run_benchmark(benchmark: Benchmark, out_dir: pathlib.Path, target: str,
+                   emulator: Optional[device_utils.DeviceUtils], *,
+                   dry_run: bool) -> List[Tuple[str, float]]:
     # This ensures that the only change is the one that this script makes.
     logging.info('Prepping benchmark...')
-    results = _execute_benchmark_stages(benchmark, out_dir, target, emulator)
+    results = _execute_benchmark_stages(benchmark,
+                                        out_dir,
+                                        target,
+                                        emulator,
+                                        dry_run=dry_run)
     for name, elapsed in results:
         logging.info(f'Took {elapsed:.1f}s to prep {name}.')
     logging.info('Starting actual test...')
@@ -445,7 +459,11 @@
                 f'Need to update {benchmark.from_string} in '
                 f'{benchmark.change_file}')
             f.write(new_content)
-        return _execute_benchmark_stages(benchmark, out_dir, target, emulator)
+        return _execute_benchmark_stages(benchmark,
+                                         out_dir,
+                                         target,
+                                         emulator,
+                                         dry_run=dry_run)
 
 
 def _format_result(time_taken: List[float]) -> str:
@@ -469,7 +487,7 @@
 
 def run_benchmarks(benchmarks: List[str], gn_args: List[str],
                    output_directory: pathlib.Path, target: str, repeat: int,
-                   emulator_avd_name: Optional[str]) -> Dict:
+                   emulator_avd_name: Optional[str], *, dry_run: bool) -> Dict:
     args_gn_path = output_directory / 'args.gn'
     if emulator_avd_name is None:
         emulator_ctx = contextlib.nullcontext
@@ -483,7 +501,8 @@
             f.write('\n'.join(gn_args))
         for run_num in range(repeat):
             logging.info(f'Run number: {run_num + 1}')
-            timings['gn_gen'].append(_run_gn_gen(output_directory))
+            timings['gn_gen'].append(
+                _run_gn_gen(output_directory, dry_run=dry_run))
             for benchmark in _parse_benchmarks(benchmarks):
                 logging.info(f'Starting {benchmark.name}...')
                 # Start a fresh emulator for each benchmark to produce more
@@ -492,7 +511,8 @@
                     results = _run_benchmark(benchmark=benchmark,
                                              out_dir=output_directory,
                                              target=target,
-                                             emulator=emulator)
+                                             emulator=emulator,
+                                             dry_run=dry_run)
                 for name, elapsed in results:
                     logging.info(f'Completed {name}: {elapsed:.1f}s')
                     timings[name].append(elapsed)
@@ -569,6 +589,11 @@
     parser.add_argument('--json',
                         action='store_true',
                         help='Output machine-readable output per benchmark.')
+    parser.add_argument('-n',
+                        '--dry-run',
+                        action='store_true',
+                        help='Do everything except the build/test/run '
+                        'steps, which will return random times.')
     args = parser.parse_args()
 
     if args.output_directory:
@@ -621,8 +646,13 @@
     else:
         target = _TARGETS['apk']
 
-    results = run_benchmarks(args.benchmark, gn_args, out_dir, target,
-                             args.repeat, args.emulator)
+    results = run_benchmarks(args.benchmark,
+                             gn_args,
+                             out_dir,
+                             target,
+                             args.repeat,
+                             args.emulator,
+                             dry_run=args.dry_run)
 
     if args.json:
         json_results = []
diff --git a/tools/android/build_speed/benchmark_unittest.py b/tools/android/build_speed/benchmark_unittest.py
index 596b6bb..0c68face 100755
--- a/tools/android/build_speed/benchmark_unittest.py
+++ b/tools/android/build_speed/benchmark_unittest.py
@@ -50,7 +50,8 @@
                     out_dir,
                     'target',
                     repeat,
-                    emulator_avd_name='emulator.avd')
+                    emulator_avd_name='emulator.avd',
+                    dry_run=False)
                 self.assertEqual(timings['gn_gen'], [2.5])
                 self.assertEqual(timings['chrome_nosig_compile'], [5.5])
                 self.assertEqual(timings['chrome_nosig_install'], [3.0])
@@ -174,6 +175,19 @@
         ]
         self.assertEqual(parsed_json, expected_json)
 
+    @unittest.mock.patch('builtins.print')
+    @unittest.mock.patch('benchmark.run_benchmarks')
+    def test_main_dry_run(self, mock_run_benchmarks, mock_print):
+        with tempfile.TemporaryDirectory() as tmpdir:
+            constants.SetOutputDirectory(tmpdir)
+            with unittest.mock.patch(
+                    'sys.argv', ['benchmark.py', 'chrome_nosig', '--dry-run']):
+                benchmark.main()
+
+        # Verify run_benchmarks was called with dry_run=True
+        _args, kwargs = mock_run_benchmarks.call_args
+        self.assertTrue(kwargs['dry_run'])
+
 
 if __name__ == '__main__':
     unittest.main()
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 2645dfb..e4cae56 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -9388,6 +9388,7 @@
       label="HttpsFirstModeV2ForTypicallySecureUsers:enabled"/>
   <int value="-1721312279" label="RollBackModeB:enabled"/>
   <int value="-1721091680" label="ForceShowAppsCollections:enabled"/>
+  <int value="-1720816283" label="AndroidMediaInsertion:enabled"/>
   <int value="-1720654843"
       label="AutofillMoveLegalTermsAndIconForNewCardEnrollment:enabled"/>
   <int value="-1720576957" label="ThirdPartyStoragePartitioning:disabled"/>
@@ -17912,6 +17913,7 @@
   <int value="1309372374" label="AccessibilityUnifiedSnapshots:disabled"/>
   <int value="1309807376" label="IgnoreCSPInWebPaymentAPI:enabled"/>
   <int value="1310000273" label="ReleaseNotesNotificationAllChannels:disabled"/>
+  <int value="1310337425" label="AndroidMediaInsertion:disabled"/>
   <int value="1311443340" label="DriveFsChromeNetworking:enabled"/>
   <int value="1311506187" label="ClipboardCustomFormats:disabled"/>
   <int value="1311579438" label="FencedFrames:enabled"/>
diff --git a/ui/accessibility/ax_node_position.cc b/ui/accessibility/ax_node_position.cc
index 2d98c69e..af8e431 100644
--- a/ui/accessibility/ax_node_position.cc
+++ b/ui/accessibility/ax_node_position.cc
@@ -4,6 +4,7 @@
 
 #include "ui/accessibility/ax_node_position.h"
 
+#include "base/containers/fixed_flat_map.h"
 #include "build/build_config.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 #include "ui/base/buildflags.h"
diff --git a/ui/accessibility/ax_position.h b/ui/accessibility/ax_position.h
index d9612dc..371a1f1 100644
--- a/ui/accessibility/ax_position.h
+++ b/ui/accessibility/ax_position.h
@@ -23,7 +23,6 @@
 #include <vector>
 
 #include "base/containers/contains.h"
-#include "base/containers/fixed_flat_map.h"
 #include "base/containers/stack.h"
 #include "base/export_template.h"
 #include "base/i18n/break_iterator.h"
diff --git a/ui/android/OWNERS b/ui/android/OWNERS
index 9ed507ec2..08a20286 100644
--- a/ui/android/OWNERS
+++ b/ui/android/OWNERS
@@ -15,4 +15,8 @@
 wenyufu@chromium.org
 pnoland@chromium.org
 
+# for modaldialog
+per-file *modal_dialog*.*=jthiesen@chromium.org
+per-file *ModalDialog*.java=jthiesen@chromium.org
+
 per-file BUILD.gn=*
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/BasicListMenu.java b/ui/android/java/src/org/chromium/ui/listmenu/BasicListMenu.java
index bf5bc0c..4029ddf 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/BasicListMenu.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/BasicListMenu.java
@@ -148,14 +148,18 @@
         View hairline = mListMenuLayout.findViewById(R.id.menu_header_bottom_hairline);
 
         mContentModelList = data;
-        mContentAdapter = createAdapter(data, Set.of(), (model) -> callDelegate(delegate, model));
+        mContentAdapter =
+                createAdapter(data, Set.of(), (model, view) -> callDelegate(delegate, model, view));
         mContentListView = mListMenuLayout.findViewById(R.id.menu_list);
         mContentListView.setAdapter(mContentAdapter);
         mContentListView.setDivider(null);
 
         mHeaderModelList = new ModelList();
         mHeaderAdapter =
-                createAdapter(mHeaderModelList, Set.of(), (model) -> callDelegate(delegate, model));
+                createAdapter(
+                        mHeaderModelList,
+                        Set.of(),
+                        (model, view) -> callDelegate(delegate, model, view));
         mHeaderListView = mListMenuLayout.findViewById(R.id.menu_header);
         mHeaderListView.setAdapter(mHeaderAdapter);
 
@@ -259,8 +263,8 @@
                 drillDownOverrideValue);
     }
 
-    private void callDelegate(@Nullable Delegate delegate, PropertyModel model) {
-        if (delegate != null) delegate.onItemSelected(model);
+    private void callDelegate(@Nullable Delegate delegate, PropertyModel model, View view) {
+        if (delegate != null) delegate.onItemSelected(model, view);
         // We will run the runnables that are registered by the time this lambda
         // is called.
         for (Runnable r : mClickRunnables) {
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenu.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenu.java
index 1e93ecbb..e23dfa7a 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenu.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenu.java
@@ -18,7 +18,7 @@
     /** Delegate handling list item click event of {@link ListMenu}. */
     @FunctionalInterface
     interface Delegate {
-        void onItemSelected(PropertyModel item);
+        void onItemSelected(PropertyModel item, View view);
     }
 
     /**
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuCheckItemProperties.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuCheckItemProperties.java
index d1593904..9895b5f 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuCheckItemProperties.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuCheckItemProperties.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.ui.listmenu.ListMenuItemProperties.CLICK_LISTENER;
 import static org.chromium.ui.listmenu.ListMenuItemProperties.ENABLED;
+import static org.chromium.ui.listmenu.ListMenuItemProperties.KEY_LISTENER;
 import static org.chromium.ui.listmenu.ListMenuItemProperties.TITLE;
 
 import org.chromium.build.annotations.NullMarked;
@@ -17,5 +18,7 @@
 public class ListMenuCheckItemProperties {
     public static final WritableBooleanPropertyKey CHECKED = new WritableBooleanPropertyKey();
 
-    public static final PropertyKey[] ALL_KEYS = {TITLE, CLICK_LISTENER, ENABLED, CHECKED};
+    public static final PropertyKey[] ALL_KEYS = {
+        TITLE, CLICK_LISTENER, ENABLED, CHECKED, KEY_LISTENER
+    };
 }
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuFlyoutController.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuFlyoutController.java
index 4a44791..4de0696 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuFlyoutController.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuFlyoutController.java
@@ -141,13 +141,13 @@
                 // receive an {@code ACTION_HOVER_ENTER} event on the flyout view. If we faithfully
                 // follow these, the parent item momentarily loses the hover style, so we ignore the
                 // first exit event in case it's immediately followed by an enter event.
+                cancelFlyoutDelay(view);
                 mPendingHoverExitRunnable =
                         () -> {
                             if (item.model.get(IS_HIGHLIGHTED)) {
-                                updateHighlightPath(
+                                updateHighlights(
                                         highlightPath.subList(0, highlightPath.size() - 1));
                             }
-                            cancelFlyoutDelay(view);
                             mPendingHoverExitRunnable = null;
                         };
                 mHoverExitDelayHandler = view.getHandler();
@@ -167,13 +167,55 @@
         }
     }
 
+    /**
+     * Trigger flyout immediately without the delay, e.g. when keyboard is used to navigate flyout
+     * menus.
+     *
+     * @param item The ListItem that is the target of the focus event.
+     * @param view The View associated with the hovered ListItem.
+     * @param levelOfHoveredItem The depth of the item within the menu hierarchy (e.g., 0 for root
+     *     items, 1 for sub-menu items).
+     * @param highlightPath The complete list of items from the root of the menu to the currently
+     *     hovered {@code item}, inclusive.
+     */
+    public void enterFlyoutWithoutDelay(
+            ListItem item, View view, int levelOfHoveredItem, List<ListItem> highlightPath) {
+        updateHighlights(highlightPath);
+        cancelFlyoutDelay(view);
+        onFlyoutAfterDelay(item, view, levelOfHoveredItem);
+    }
+
+    /**
+     * Remove flyout windows with levels larger than or equal to {@code clearFromIndex} immediately,
+     * e.g. when keyboard is used to navigate flyout menus.
+     *
+     * @param clearFromIndex The minimum level of flyout popup to remove.
+     * @param view The View associated with the hovered ListItem.
+     * @param highlightPath The complete list of items from the root of the menu to the currently
+     *     hovered {@code item}, inclusive.
+     */
+    public void exitFlyoutWithoutDelay(
+            int clearFromIndex, View view, List<ListItem> highlightPath) {
+        // We do not dismiss the main, non-flyout popup here.
+        if (clearFromIndex == 0) {
+            return;
+        }
+
+        cancelFlyoutDelay(view);
+
+        // We need to remove hover from the popup currently in focus.
+        updateHighlights(highlightPath.subList(0, clearFromIndex - 1));
+
+        mFlyoutHandler.removeFlyoutWindows(clearFromIndex);
+    }
+
     private void onItemHovered(
             ListItem item,
             View view,
             int levelOfHoveredItem,
             @Nullable Boolean drillDownOverrideValue,
             List<ListItem> highlightPath) {
-        updateHighlightPath(highlightPath);
+        updateHighlights(highlightPath);
 
         if (shouldUseDrillDown(drillDownOverrideValue)) {
             return;
@@ -196,7 +238,16 @@
                 view.getContext().getResources().getInteger(R.integer.flyout_menu_delay_in_ms));
     }
 
-    private void updateHighlightPath(List<ListItem> highlightPath) {
+    /**
+     * Updates the highlight state of menu items based on the new hover path. The addition of flyout
+     * windows requires us to precisely control the hover states of the items. Specifically, when
+     * the user is hovering on an item inside a flyout popup, all of the ancestor items should
+     * remain highlighted, even when the hover itself is not on those items.
+     *
+     * @param highlightPath The list of {@link ListItem}s from the root to the currently hovered
+     *     item that should be highlighted.
+     */
+    private void updateHighlights(List<ListItem> highlightPath) {
         int forkIndex = -1;
 
         for (int i = 0; i < Math.min(mLastHighlightedPath.size(), highlightPath.size()); i++) {
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 c2697bec..55f9ab6 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuHost.java
@@ -244,6 +244,10 @@
         mRemovingPopups = false;
 
         mPopupMenus.subList(clearFromIndex, mPopupMenus.size()).clear();
+
+        if (mPopupMenus.size() > 0) {
+            setWindowFocus(mPopupMenus.get(mPopupMenus.size() - 1).popupWindow, true);
+        }
     }
 
     @Override
@@ -282,10 +286,22 @@
                                 })
                         .build();
 
+        assert mPopupMenus.size() > 0;
+        setWindowFocus(mPopupMenus.get(mPopupMenus.size() - 1).popupWindow, false);
+
+        setWindowFocus(popupMenu, true);
         popupMenu.show();
+
         mPopupMenus.add(new FlyoutPopupEntry(item, popupMenu));
     }
 
+    private void setWindowFocus(AnchoredPopupWindow popupWindow, boolean hasFocus) {
+        ViewGroup contentView = (ViewGroup) popupWindow.getContentView();
+        if (contentView == null) return;
+
+        ListMenuUtils.setWindowFocus(contentView, hasFocus);
+    }
+
     public Rect calculateFlyoutAnchorRect(View itemView) {
         int[] result = new int[2];
         itemView.getLocationOnScreen(result);
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuItemAdapter.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuItemAdapter.java
index 46afb3c..a2e0b1799 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuItemAdapter.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuItemAdapter.java
@@ -44,7 +44,8 @@
      * @param disabledTypes The type enums which should be disabled in the adapter (i.e. not
      *     keyboard-focusable or interactable).
      * @param delegate The {@link Delegate} used to handle menu clicks. If not provided, the item's
-     *     CLICK_LISTENER or listMenu's onMenuItemSelected method will be used.
+     *     CLICK_LISTENER or listMenu's onMenuItemSelected method will be used. If provided, both
+     *     will run.
      */
     public ListMenuItemAdapter(
             ModelList data, Collection<Integer> disabledTypes, @Nullable Delegate delegate) {
@@ -92,7 +93,7 @@
                     (v) -> {
                         if (mDelegate != null) {
                             // Delegate, if possible.
-                            mDelegate.onItemSelected(item.model);
+                            mDelegate.onItemSelected(item.model, v);
                         } else if (hasClickListener(item)) {
                             // The item had a click listener in the model, but none was bound by the
                             // ViewBinder, and there is no click delegate to use. In this case, call
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuRadioItemProperties.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuRadioItemProperties.java
index 395607f..4da9bc65 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuRadioItemProperties.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuRadioItemProperties.java
@@ -6,6 +6,7 @@
 
 import static org.chromium.ui.listmenu.ListMenuItemProperties.CLICK_LISTENER;
 import static org.chromium.ui.listmenu.ListMenuItemProperties.ENABLED;
+import static org.chromium.ui.listmenu.ListMenuItemProperties.KEY_LISTENER;
 import static org.chromium.ui.listmenu.ListMenuItemProperties.TITLE;
 
 import org.chromium.build.annotations.NullMarked;
@@ -17,5 +18,7 @@
 public class ListMenuRadioItemProperties {
     public static final WritableBooleanPropertyKey SELECTED = new WritableBooleanPropertyKey();
 
-    public static final PropertyKey[] ALL_KEYS = {TITLE, CLICK_LISTENER, ENABLED, SELECTED};
+    public static final PropertyKey[] ALL_KEYS = {
+        TITLE, CLICK_LISTENER, ENABLED, SELECTED, KEY_LISTENER
+    };
 }
diff --git a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuUtils.java b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuUtils.java
index 4fadd811..00772577 100644
--- a/ui/android/java/src/org/chromium/ui/listmenu/ListMenuUtils.java
+++ b/ui/android/java/src/org/chromium/ui/listmenu/ListMenuUtils.java
@@ -17,6 +17,7 @@
 import android.content.res.Resources;
 import android.os.SystemClock;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.ListView;
 
 import androidx.annotation.StringRes;
@@ -232,7 +233,9 @@
 
         // We add `HOVER_LISTENER` to items without submenus too because we might need to dismiss
         // open flyout popups.
-        if (flyoutController != null && item.model.containsKey(HOVER_LISTENER)) {
+        if (!ListMenuFlyoutController.shouldUseDrillDown(drillDownOverrideValue)
+                && flyoutController != null
+                && item.model.containsKey(HOVER_LISTENER)) {
             item.model.set(
                     HOVER_LISTENER,
                     (view, event) -> {
@@ -244,18 +247,46 @@
                                 drillDownOverrideValue,
                                 highlightPath);
                     });
+
+            View.OnKeyListener originalListener =
+                    item.model.get(org.chromium.ui.listmenu.ListMenuItemProperties.KEY_LISTENER);
+            item.model.set(
+                    org.chromium.ui.listmenu.ListMenuItemProperties.KEY_LISTENER,
+                    (view, keyCode, keyEvent) -> {
+                        if (isGoBackward(keyEvent)) {
+                            flyoutController.exitFlyoutWithoutDelay(
+                                    levelOfHoveredItem, view, highlightPath);
+                            return true;
+                        }
+
+                        if (originalListener != null) {
+                            return originalListener.onKey(view, keyCode, keyEvent);
+                        }
+
+                        // Return false because the listener has not consumed the event.
+                        return false;
+                    });
         }
 
         if (item.model.containsKey(SUBMENU_ITEMS)) {
             final View.OnClickListener existingListener = item.model.get(CLICK_LISTENER);
             item.model.set(
                     CLICK_LISTENER,
-                    (unusedView) -> {
+                    (view) -> {
                         if (existingListener != null) {
-                            existingListener.onClick(unusedView);
+                            existingListener.onClick(view);
                         }
-                        onItemWithSubmenuClicked(
-                                headerModelList, contentModelList, item, drillDownOverrideValue);
+                        if (ListMenuFlyoutController.shouldUseDrillDown(drillDownOverrideValue)) {
+                            onItemWithSubmenuClicked(
+                                    headerModelList,
+                                    contentModelList,
+                                    item,
+                                    drillDownOverrideValue);
+                        } else if (flyoutController != null) {
+                            // Allow for controlling flyout with keyboard for accessibility.
+                            flyoutController.enterFlyoutWithoutDelay(
+                                    item, view, levelOfHoveredItem, highlightPath);
+                        }
                     });
             for (ListItem submenuItem :
                     PropertyModel.getFromModelOrDefault(item.model, SUBMENU_ITEMS, List.of())) {
@@ -406,4 +437,23 @@
             mView.requestFocus();
         }
     }
+
+    /**
+     * Set the focus state for a given content view. This is to make sure that hover navigation,
+     * keyboard navigation and the combination of both work for flyout menus. We have to make sure
+     * that only the top flyout popup is focused, and that the {@code ListView} in the other popups
+     * don't get focus when the device exits touch mode due to e.g. keyboard activity.
+     *
+     * @param contentView The content view to change the focus settings for.
+     * @param hasFocus Whether this content view should have focus.
+     */
+    public static void setWindowFocus(ViewGroup contentView, boolean hasFocus) {
+        if (hasFocus) {
+            contentView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
+            contentView.requestFocus();
+        } else {
+            contentView.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
+            contentView.clearFocus();
+        }
+    }
 }
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 e1830fb..0b1ab5b5 100644
--- a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
@@ -1137,13 +1137,22 @@
     }
 
     /**
+     * Gets the content view of the {@link PopupWindow}.
+     *
+     * @return The content view.
+     */
+    public @Nullable View getContentView() {
+        return mContentView;
+    }
+
+    /**
      * Checks if the popup spec meets the minimal size requirements.
      *
      * <p>By default, this method ensures that the size is sufficient for users to see what they are
      * tapping. Popups can be very narrow (e.g. in landscape) and still be interactive. Use {@link
      * #setRequireTouchableSize(boolean)} to disable this check.
      *
-     * @return True iff the popup is large enough to be safely shown to users.
+     * @return True if the popup is large enough to be safely shown to users.
      */
     private boolean hasMinimalSize() {
         if (mAllowNonTouchableSize) {
diff --git a/ui/events/ash/keyboard_capability.h b/ui/events/ash/keyboard_capability.h
index 168a167d..0afbe11 100644
--- a/ui/events/ash/keyboard_capability.h
+++ b/ui/events/ash/keyboard_capability.h
@@ -11,7 +11,6 @@
 
 #include "ash/constants/ash_features.h"
 #include "base/containers/fixed_flat_map.h"
-#include "base/containers/fixed_flat_set.h"
 #include "base/containers/flat_map.h"
 #include "base/files/scoped_file.h"
 #include "ui/base/accelerators/accelerator.h"
diff --git a/ui/gtk/gtk_key_bindings_handler.cc b/ui/gtk/gtk_key_bindings_handler.cc
index 48c8397..e411dc3 100644
--- a/ui/gtk/gtk_key_bindings_handler.cc
+++ b/ui/gtk/gtk_key_bindings_handler.cc
@@ -7,6 +7,7 @@
 #include <array>
 
 #include "base/compiler_specific.h"
+#include "base/containers/fixed_flat_map.h"
 #include "base/logging.h"
 #include "ui/base/glib/gsettings.h"
 #include "ui/base/ime/text_edit_commands.h"
diff --git a/ui/gtk/gtk_key_bindings_handler.h b/ui/gtk/gtk_key_bindings_handler.h
index 90656b9..d08c9194 100644
--- a/ui/gtk/gtk_key_bindings_handler.h
+++ b/ui/gtk/gtk_key_bindings_handler.h
@@ -5,7 +5,6 @@
 #ifndef UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
 #define UI_GTK_GTK_KEY_BINDINGS_HANDLER_H_
 
-#include "base/containers/fixed_flat_map.h"
 #include "ui/base/glib/scoped_gobject.h"
 #include "ui/base/glib/scoped_gsignal.h"
 #include "ui/base/ime/linux/text_edit_command_auralinux.h"
diff --git a/ui/gtk/gtk_ui.h b/ui/gtk/gtk_ui.h
index 2922044..b37bfb3 100644
--- a/ui/gtk/gtk_ui.h
+++ b/ui/gtk/gtk_ui.h
@@ -12,7 +12,6 @@
 #include <unordered_map>
 #include <vector>
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/memory/raw_ptr.h"
 #include "printing/buildflags/buildflags.h"
 #include "ui/base/glib/scoped_gsignal.h"
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index 3020d65..298a774 100644
--- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -62,7 +62,7 @@
   // Use default display format since this should be compatible with most
   // devices.
   overlay_candidate.format =
-      viz::GetSharedImageFormat(display::DisplaySnapshot::PrimaryFormat());
+      display::DisplaySnapshot::PrimarySharedImageFormat();
 
   // The bounds rectangle of the candidate overlay buffer.
   overlay_candidate.buffer_size = bounds_rect.size();
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc
index a12f831..0f6a838 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -55,7 +55,7 @@
   // Use default display format since this should be compatible with most
   // devices.
   overlay_candidate.format =
-      viz::GetSharedImageFormat(display::DisplaySnapshot::PrimaryFormat());
+      display::DisplaySnapshot::PrimarySharedImageFormat();
 
   // The bounds rectangle of the candidate overlay buffer.
   overlay_candidate.buffer_size = bounds_rect.size();
diff --git a/ui/ozone/platform/wayland/host/dump_util.h b/ui/ozone/platform/wayland/host/dump_util.h
index 6a8b16c..a03ea4c 100644
--- a/ui/ozone/platform/wayland/host/dump_util.h
+++ b/ui/ozone/platform/wayland/host/dump_util.h
@@ -8,7 +8,6 @@
 #include <list>
 #include <string>
 
-#include "base/containers/fixed_flat_map.h"
 #include "base/strings/to_string.h"
 
 namespace ui {