diff --git a/DEPS b/DEPS
index 0f30bb6..10653225 100644
--- a/DEPS
+++ b/DEPS
@@ -295,11 +295,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': 'd001483ef1f2440291ad1fa8c15b897b7be0e72f',
+  'src_internal_revision': 'f8e36dcd08ab67bfc9e717b3ed315fef7e8e6cba',
   # 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': '1e07a4b16973cf716cb40b72dd969e961f4dd950',
+  'skia_revision': '3ba7657e8745bffd1c6263d5555be935afbc0df9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -307,7 +307,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': 'a38ac25bd93c1fdaf393e2513f9c254b493e18bb',
+  'angle_revision': '2a18fdbf4c8c20e37734611064d21a83658f6236',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -351,7 +351,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '57a873045016c7866a298f5e9faa830e6ec24cf9',
+  'freetype_revision': 'e07e56c7f106b600262ab653d696b7b57f320127',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
@@ -391,7 +391,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': '55154436a9c71fc62179638710b405c99e80ef54',
+  'devtools_frontend_revision': 'acd68d2f092a2e674894c9d389c96e39beec1aa2',
   # 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.
@@ -415,7 +415,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': '156136ebb43d383a3833545598023dd366085166',
+  'dawn_revision': '45b5634e70a3a6d61f3704f308d7a419e7db532d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -523,7 +523,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'compiler_rt_revision': '9c6d38aa28100761bc2d6dcd2a590a37f8519adf',
+  'compiler_rt_revision': '57196dd146582915c955f6d388e31aea93220c51',
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
@@ -1508,7 +1508,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    'c6f37b2a1ac4f90393eff3c734ca926a8e602153',
+    '7b3b66843fe0c37489709a09bf6e4c57c6087f53',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -2867,7 +2867,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@bf024288c340597e8421df8db06c2de12c25bf31',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@5912cbdd295c2bacb5798432a7b1cac9d20c0725',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@93231001597dad1149a5d035af30eda50b9e6b6c',
   '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@c9aad99f9276817f18f72a4696239237c83cb775',
@@ -2875,8 +2875,8 @@
   'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@75ad707a587e1469fb53a901b9b68fe9f6fbc11f',
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@c913466fdc5004584890f89ff91121bdb2ffd4ba',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@60b640cb931814fcc6dabe4fc61f4738c56579f6',
-  'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@ae56bd6e65d9faa731150e931cb35f0d895223bc',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@84b023ac42601ff51ea6094dc2c18ca62960b25d',
+  'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@49ac28931f28bffaa3cd73dc4ad997284d574962',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@f7ceb1d01a292846db77ec87786be84d6fd568d9',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21',
@@ -2921,7 +2921,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '2fe2d5190bd3d8766759e3a7de2b648d5ce96aee',
+    Var('webrtc_git') + '/src.git' + '@' + '9909b30d5e3c104d4dce7d066fc8422eef1dcc59',
 
   # 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': 'chromeos_internal/apps/help_app/app',
-        'version': 'CTDlv1ivZiL2YbKkLKyrIf6V149_sKW0ZdPI3x804YgC',
+        'version': 'nu99RnP4WrMIbyKDSQ4AuIaXEqIGYHZ6_nRK1EPhFZIC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3065,7 +3065,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'AdXzD30R0jed2FtB_0vPwg_W4vqaJwxeQ9mMl9ZXqq0C',
+        'version': 'zl3WjF8rNKkrpjHL28zwf14BmBHTh-E6TLAkRyIqiywC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4707,7 +4707,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        'caa545d88ae49b674a6d9542f80c5514d0cfc18e',
+        'a5c6f36c55a93150abaf43134d5c40dc42112f9d',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/base/android/java/src/org/chromium/base/DeviceInfo.java b/base/android/java/src/org/chromium/base/DeviceInfo.java
index 4ca7a9e5..cbe45d9 100644
--- a/base/android/java/src/org/chromium/base/DeviceInfo.java
+++ b/base/android/java/src/org/chromium/base/DeviceInfo.java
@@ -68,14 +68,14 @@
     }
 
     public static String getGmsVersionCode() {
-        return sGmsVersionCodeForTesting == null
-                ? getInstance().mIDeviceInfo.gmsVersionCode
-                : sGmsVersionCodeForTesting;
+        return getInstance().mIDeviceInfo.gmsVersionCode;
     }
 
     @CalledByNativeForTesting
     public static void setGmsVersionCodeForTest(@JniType("std::string") String gmsVersionCode) {
         sGmsVersionCodeForTesting = gmsVersionCode;
+        // Every time we call getInstance in a test we reconstruct the mIDeviceInfo object, so we
+        // don't need to set mIDeviceInfo's copy here as it'll just get reconstructed.
         ResettersForTesting.register(() -> sGmsVersionCodeForTesting = null);
     }
 
@@ -138,6 +138,9 @@
                 gmsPackageInfo != null
                         ? String.valueOf(packageVersionCode(gmsPackageInfo))
                         : "gms versionCode not available.";
+        if (sGmsVersionCodeForTesting != null) {
+            mIDeviceInfo.gmsVersionCode = sGmsVersionCodeForTesting;
+        }
 
         Context appContext = ContextUtils.getApplicationContext();
         PackageManager pm = appContext.getPackageManager();
diff --git a/base/files/file_util_posix.cc b/base/files/file_util_posix.cc
index 84e81af..76681ad4 100644
--- a/base/files/file_util_posix.cc
+++ b/base/files/file_util_posix.cc
@@ -1298,7 +1298,7 @@
     // |base| must be a subpath of |path|, so all components should match.
     // If these CHECKs fail, look at the test that base is a parent of
     // path at the top of this function.
-    CHECK(ip != path_components.end(), base::NotFatalUntil::M125);
+    CHECK(ip != path_components.end());
     DCHECK(*ip == *ib);
   }
 
diff --git a/base/logging.cc b/base/logging.cc
index 26ba1a2..b8eee13 100644
--- a/base/logging.cc
+++ b/base/logging.cc
@@ -33,7 +33,6 @@
 #include "base/functional/callback.h"
 #include "base/immediate_crash.h"
 #include "base/no_destructor.h"
-#include "base/not_fatal_until.h"
 #include "base/path_service.h"
 #include "base/pending_task.h"
 #include "base/posix/eintr_wrapper.h"
@@ -550,13 +549,13 @@
 
 #if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
   if (settings.log_file) {
-    CHECK(settings.log_file_path.empty(), base::NotFatalUntil::M127);
+    CHECK(settings.log_file_path.empty());
     g_log_file = settings.log_file;
     return true;
   }
 #endif  // BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_WIN)
 
-  CHECK(!settings.log_file_path.empty(), base::NotFatalUntil::M127)
+  CHECK(!settings.log_file_path.empty())
       << "LOG_TO_FILE set but no log_file_path!";
 
   if (!g_log_file_name) {
diff --git a/base/memory/shared_memory_tracker.cc b/base/memory/shared_memory_tracker.cc
index 576b786..b90dc3d 100644
--- a/base/memory/shared_memory_tracker.cc
+++ b/base/memory/shared_memory_tracker.cc
@@ -62,11 +62,8 @@
     const SharedMemoryMapping& mapping) {
   AutoLock hold(usages_lock_);
   const auto it = usages_.find(mapping.mapped_memory().data());
-  // TODO(pbos): When removing this NotFatalUntil, use erase(it) below. We can't
-  // do that now because if this CHECK is actually failing there'd be a memory
-  // bug.
-  CHECK(it != usages_.end(), base::NotFatalUntil::M125);
-  usages_.erase(mapping.mapped_memory().data());
+  CHECK(it != usages_.end());
+  usages_.erase(it);
 }
 
 SharedMemoryTracker::SharedMemoryTracker() {
diff --git a/base/message_loop/message_pump_epoll.cc b/base/message_loop/message_pump_epoll.cc
index d99f576..008728bb5 100644
--- a/base/message_loop/message_pump_epoll.cc
+++ b/base/message_loop/message_pump_epoll.cc
@@ -421,12 +421,12 @@
 
   const int fd = interest->params().fd;
   auto entry_it = entries_.find(fd);
-  CHECK(entry_it != entries_.end(), base::NotFatalUntil::M125);
+  CHECK(entry_it != entries_.end());
 
   EpollEventEntry& entry = entry_it->second;
   auto& interests = entry.interests;
   auto* it = std::ranges::find(interests, interest);
-  CHECK(it != interests.end(), base::NotFatalUntil::M125);
+  CHECK(it != interests.end());
   interests.erase(it);
 
   if (interests.empty()) {
diff --git a/base/metrics/statistics_recorder.cc b/base/metrics/statistics_recorder.cc
index 93d3804..6f612b3 100644
--- a/base/metrics/statistics_recorder.cc
+++ b/base/metrics/statistics_recorder.cc
@@ -374,7 +374,7 @@
   EnsureGlobalRecorderWhileLocked();
 
   auto iter = top_->observers_.find(hash);
-  CHECK(iter != top_->observers_.end(), base::NotFatalUntil::M125);
+  CHECK(iter != top_->observers_.end());
 
   auto result = iter->second->RemoveObserver(observer);
   if (result ==
diff --git a/base/sampling_heap_profiler/poisson_allocation_sampler.cc b/base/sampling_heap_profiler/poisson_allocation_sampler.cc
index 7cb9296..1bd644d 100644
--- a/base/sampling_heap_profiler/poisson_allocation_sampler.cc
+++ b/base/sampling_heap_profiler/poisson_allocation_sampler.cc
@@ -484,7 +484,7 @@
   ScopedMuteThreadSamples no_reentrancy_scope;
   AutoLock lock(mutex_);
   auto it = std::ranges::find(observers_, observer);
-  CHECK(it != observers_.end(), base::NotFatalUntil::M125);
+  CHECK(it != observers_.end());
   observers_.erase(it);
 
   // Stop the profiler if there are no more observers. Setting/resetting
diff --git a/base/strings/string_util_impl_helpers.h b/base/strings/string_util_impl_helpers.h
index b032e133..7bdfd17 100644
--- a/base/strings/string_util_impl_helpers.h
+++ b/base/strings/string_util_impl_helpers.h
@@ -497,7 +497,7 @@
   result.reserve(total_size);
 
   auto iter = parts.begin();
-  CHECK(iter != parts.end(), base::NotFatalUntil::M125);
+  CHECK(iter != parts.end());
   result.append(*iter);
   UNSAFE_TODO(++iter);
 
diff --git a/base/task/common/checked_lock_impl.cc b/base/task/common/checked_lock_impl.cc
index eefd52e..172a754 100644
--- a/base/task/common/checked_lock_impl.cc
+++ b/base/task/common/checked_lock_impl.cc
@@ -51,7 +51,7 @@
   void RecordRelease(const CheckedLockImpl* const lock) {
     LockVector* acquired_locks = GetAcquiredLocksOnCurrentThread();
     const auto iter_at_lock = std::ranges::find(*acquired_locks, lock);
-    CHECK(iter_at_lock != acquired_locks->end(), base::NotFatalUntil::M125);
+    CHECK(iter_at_lock != acquired_locks->end());
     acquired_locks->erase(iter_at_lock);
   }
 
diff --git a/base/task/sequence_manager/sequence_manager_impl_unittest.cc b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
index f91e5562..6bed549 100644
--- a/base/task/sequence_manager/sequence_manager_impl_unittest.cc
+++ b/base/task/sequence_manager/sequence_manager_impl_unittest.cc
@@ -4721,8 +4721,7 @@
   }
 
   ~PostTaskWhenDeleted() {
-    CHECK(tasks_alive_->find(full_name()) != tasks_alive_->end(),
-          base::NotFatalUntil::M125);
+    CHECK(tasks_alive_->contains(full_name()));
     tasks_alive_->erase(full_name());
     tasks_deleted_->push_back(full_name());
 
diff --git a/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc b/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
index 1290d0ad9..9ecaabd3 100644
--- a/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
+++ b/base/task/thread_pool/pooled_single_thread_task_runner_manager.cc
@@ -857,7 +857,7 @@
     }
 
     auto worker_iter = std::ranges::find(workers_, worker);
-    CHECK(worker_iter != workers_.end(), base::NotFatalUntil::M125);
+    CHECK(worker_iter != workers_.end());
     worker_to_destroy = std::move(*worker_iter);
     workers_.erase(worker_iter);
   }
diff --git a/base/task/thread_pool/thread_group_impl.cc b/base/task/thread_pool/thread_group_impl.cc
index e87bd15..cad8c8e 100644
--- a/base/task/thread_pool/thread_group_impl.cc
+++ b/base/task/thread_pool/thread_group_impl.cc
@@ -615,7 +615,7 @@
 
   // Remove the worker from |workers_|.
   auto worker_iter = std::ranges::find(outer_->workers_, worker);
-  CHECK(worker_iter != outer_->workers_.end(), base::NotFatalUntil::M125);
+  CHECK(worker_iter != outer_->workers_.end());
   outer_->workers_.erase(worker_iter);
 }
 
diff --git a/base/task/thread_pool/worker_thread_set.cc b/base/task/thread_pool/worker_thread_set.cc
index 2653d4a..65101fd 100644
--- a/base/task/thread_pool/worker_thread_set.cc
+++ b/base/task/thread_pool/worker_thread_set.cc
@@ -59,7 +59,7 @@
   DCHECK(!IsEmpty());
   DCHECK_NE(worker, *set_.begin());
   auto it = set_.find(const_cast<WorkerThread*>(worker));
-  CHECK(it != set_.end(), base::NotFatalUntil::M125);
+  CHECK(it != set_.end());
   DCHECK_NE(TimeTicks(), (*it)->GetLastUsedTime());
   set_.erase(it);
 }
diff --git a/base/threading/hang_watcher.cc b/base/threading/hang_watcher.cc
index cf3657b9..28a767d6 100644
--- a/base/threading/hang_watcher.cc
+++ b/base/threading/hang_watcher.cc
@@ -1104,7 +1104,7 @@
       &std::unique_ptr<internal::HangWatchState>::get);
 
   // Thread should be registered to get unregistered.
-  CHECK(it != watch_states_.end(), base::NotFatalUntil::M125);
+  CHECK(it != watch_states_.end());
 
   watch_states_.erase(it);
 }
diff --git a/base/threading/thread_id_name_manager.cc b/base/threading/thread_id_name_manager.cc
index 2ee7ca1..3cb0db3 100644
--- a/base/threading/thread_id_name_manager.cc
+++ b/base/threading/thread_id_name_manager.cc
@@ -128,13 +128,11 @@
   AutoLock locked(lock_);
   auto handle_to_name_iter = thread_handle_to_interned_name_.find(handle);
 
-  CHECK(handle_to_name_iter != thread_handle_to_interned_name_.end(),
-        base::NotFatalUntil::M125);
+  CHECK(handle_to_name_iter != thread_handle_to_interned_name_.end());
   thread_handle_to_interned_name_.erase(handle_to_name_iter);
 
   auto id_to_handle_iter = thread_id_to_handle_.find(id);
-  CHECK(id_to_handle_iter != thread_id_to_handle_.end(),
-        base::NotFatalUntil::M125);
+  CHECK(id_to_handle_iter != thread_id_to_handle_.end());
   // The given |id| may have been re-used by the system. Make sure the
   // mapping points to the provided |handle| before removal.
   if (id_to_handle_iter->second != handle) {
diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
index 4004a5b..706f0f3 100644
--- a/build/config/BUILDCONFIG.gn
+++ b/build/config/BUILDCONFIG.gn
@@ -279,6 +279,11 @@
   _default_toolchain = "//build/toolchain/aix:$target_cpu"
 } else if (target_os == "zos") {
   _default_toolchain = "//build/toolchain/zos:$target_cpu"
+} else if (target_os == "emscripten") {
+  # Because it's too hard to remove all targets from //BUILD.gn that do not work with it.
+  assert(
+      false,
+      "emscripten is not a supported target_os. It is available only as secondary toolchain.")
 } else {
   assert(false, "Unsupported target_os: $target_os")
 }
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index a83f75b..59942a3 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -206,7 +206,7 @@
   # Set to true to use icf, Identical Code Folding.
   use_icf = (is_posix || is_fuchsia) && !is_debug && !using_sanitizer &&
             !use_clang_coverage && current_os != "zos" &&
-            !(is_android && use_order_profiling) && use_lld
+            !(is_android && use_order_profiling) && use_lld && !is_wasm
 }
 
 if (is_android) {
@@ -723,6 +723,20 @@
     ldflags += [ "-fexperimental-relative-c++-abi-vtables" ]
   }
 
+  if (is_wasm) {
+    ldflags += [
+      "-s",
+      "ALLOW_MEMORY_GROWTH=1",
+      "-s",
+      "LLD_REPORT_UNDEFINED=1",
+    ]
+
+    if (is_official_build) {
+      cflags += [ "-flto=full" ]
+      ldflags += [ "-flto=full" ]
+    }
+  }
+
   # Add flags for link-time optimization. These flags enable
   # optimizations/transformations that require whole-program visibility at link
   # time, so they need to be applied to all translation units, and we may end up
@@ -3006,6 +3020,9 @@
 
     # All configs using /DEBUG should include this:
     configs += [ ":win_pdbaltpath" ]
+  } else if (is_wasm) {
+    cflags = [ "-gseparate-dwarf" ]
+    ldflags = [ "-gseparate-dwarf" ]
   } else {
     cflags = []
     if (is_apple && enable_dsyms) {
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
index 4a5abb94..8d97e75 100644
--- a/build/config/mac/mac_sdk.gni
+++ b/build/config/mac/mac_sdk.gni
@@ -8,6 +8,7 @@
 import("//build/toolchain/rbe.gni")
 import("//build/toolchain/siso.gni")
 import("//build/toolchain/toolchain.gni")
+import("//build_overrides/build.gni")
 
 # Allow Android builds on macOS
 assert(current_os == "mac" || current_toolchain == default_toolchain ||
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index ce642da..44dbc84d 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -5,10 +5,6 @@
 # Toolchain-related configuration that may be needed outside the context of the
 # toolchain() rules themselves.
 
-import("//build/config/cast.gni")
-import("//build/config/chrome_build.gni")
-import("//build_overrides/build.gni")
-
 declare_args() {
   # If this is set to true, we use the revision in the llvm repo to determine
   # the CLANG_REVISION to use, instead of the version hard-coded into
@@ -36,17 +32,6 @@
   toolchain_allows_use_partition_alloc_as_malloc = true
 }
 
-if (generate_linker_map) {
-  assert(is_official_build || is_castos || is_cast_android,
-         "Linker map files should only be generated when is_official_build = " +
-             "true or is_castos = true or is_cast_android = true")
-  assert(current_os == "android" || current_os == "linux" ||
-             target_os == "android" || target_os == "linux" ||
-             target_os == "chromeos",
-         "Linker map files should only be generated for Android, Linux, " +
-             "or ChromeOS.")
-}
-
 declare_args() {
   if (llvm_android_mainline) {  # https://crbug.com/1481060
     clang_version = "17"
diff --git a/build/toolchain/wasm/BUILD.gn b/build/toolchain/wasm/BUILD.gn
index 51d5066..4b4d65c8 100644
--- a/build/toolchain/wasm/BUILD.gn
+++ b/build/toolchain/wasm/BUILD.gn
@@ -4,12 +4,16 @@
 
 import("//build/toolchain/gcc_toolchain.gni")
 
+declare_args() {
+  # Path to emsdk directory.
+  emscripten_path = "//third_party/emsdk/upstream/emscripten/"
+}
+
 # This WASM toolchain is NOT to be used to build any Chromium code,
 # i.e. tests and samples are currently fine.
 # Usage of this toolchain requires getting explicit approval from
 # build/OWNERS.
 gcc_toolchain("wasm") {
-  emscripten_path = "//third_party/emsdk/upstream/emscripten/"
   _suffix = ""
   if (host_os == "win") {
     _suffix = ".bat"
@@ -43,5 +47,8 @@
     use_custom_libcxx_for_host = false
   }
   executable_extension = ".html"
-  link_outputs = [ "{{output_dir}}/{{target_output_name}}.wasm" ]
+  link_outputs = [
+    "{{output_dir}}/{{target_output_name}}.wasm",
+    "{{output_dir}}/{{target_output_name}}.wasm.debug.wasm",
+  ]
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java
index c1f5f53..d3833dc 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabAnimationHostView.java
@@ -38,10 +38,8 @@
 /** Host view for the new background tab animation. */
 public class NewBackgroundTabAnimationHostView extends FrameLayout {
     /* package */ static final long CROSS_FADE_DURATION_MS = 150L;
-    private static final long PATH_ARC_DURATION_MS = 300L;
-    private static final long NEW_PATH_ARC_DURATION_MS = 400L;
-    private static final long LINK_SCALE_DURATION_MS = 160L;
-    private static final long NEW_LINK_SCALE_DURATION_MS = 192L;
+    private static final long PATH_ARC_DURATION_MS = 400L;
+    private static final long LINK_SCALE_DURATION_MS = 192L;
     private static final long TRANSLATE_DELAY_DURATION_MS = 100L;
     private static final long SHRINK_DELAY_DURATION_MS = 50L;
 
@@ -95,13 +93,11 @@
         target[1] -= Math.round(mLinkIcon.getHeight() / 2f);
 
         // TODO(crbug.com/419065710): Clean up versions.
-        boolean isNewDuration = ChromeFeatureList.sShowNewTabAnimationsNewDuration.getValue();
         @NewTabAnim int version = ChromeFeatureList.sShowNewTabAnimationsVersion.getValue();
-        long pathDuration = isNewDuration ? NEW_PATH_ARC_DURATION_MS : PATH_ARC_DURATION_MS;
 
-        AnimatorSet transitionAnimator = getTransitionAnimator(isNewDuration);
+        AnimatorSet transitionAnimator = getTransitionAnimator();
         ObjectAnimator pathAnimator =
-                getPathArcAnimator(originX, originY, target[0], target[1], pathDuration, version);
+                getPathArcAnimator(originX, originY, target[0], target[1], version);
         AnimatorSet backgroundAnimation = new AnimatorSet();
         AnimatorSet fakeTabSwitcherAnimator;
 
@@ -126,7 +122,7 @@
                     .with(fakeTabSwitcherAnimator)
                     .after(pathAnimator);
         } else {
-            transitionAnimator.setStartDelay(pathDuration - CROSS_FADE_DURATION_MS);
+            transitionAnimator.setStartDelay(PATH_ARC_DURATION_MS - CROSS_FADE_DURATION_MS);
             fakeTabSwitcherAnimator =
                     mFakeTabSwitcherButton.getTranslateAnimator(
                             NewBackgroundTabFakeTabSwitcherButton.TranslateDirection.UP);
@@ -212,33 +208,24 @@
      * @param originY y-coordinate for the start point.
      * @param finalX x-coordinate for the end point.
      * @param finalY y-coordinate for the end point.
-     * @param duration Animation duration in ms.
      * @param version The {@link NewTabAnim} animation version.
      */
     private ObjectAnimator getPathArcAnimator(
-            float originX,
-            float originY,
-            float finalX,
-            float finalY,
-            long duration,
-            @NewTabAnim int version) {
+            float originX, float originY, float finalX, float finalY, @NewTabAnim int version) {
         boolean isClockwise = mIsTopToolbar ? (originX >= finalX) : (originX <= finalX);
 
         ObjectAnimator animator =
                 ViewCurvedMotionAnimatorFactory.build(
                         mLinkIcon, originX, originY, finalX, finalY, isClockwise);
-        animator.setDuration(duration);
+        animator.setDuration(PATH_ARC_DURATION_MS);
 
-        Interpolator pathInterpolator;
-        pathInterpolator =
+        Interpolator pathInterpolator =
                 switch (version) {
+                    case NewTabAnim.M137 -> Interpolators
+                            .NEW_BACKGROUND_TAB_ANIMATION_PATH_INTERPOLATOR;
                     case NewTabAnim.BOUNCE -> Interpolators
                             .NEW_BACKGROUND_TAB_ANIMATION_SECOND_PATH_INTERPOLATOR;
-                    case NewTabAnim.DECELERATE,
-                            NewTabAnim.BOUNCE_DECELERATE,
-                            NewTabAnim.BOUNCE_DECELERATE_WITH_DELAY -> Interpolators
-                            .EMPHASIZED_DECELERATE;
-                    default -> Interpolators.NEW_BACKGROUND_TAB_ANIMATION_PATH_INTERPOLATOR;
+                    default -> Interpolators.EMPHASIZED_DECELERATE;
                 };
         animator.setInterpolator(pathInterpolator);
 
@@ -256,7 +243,7 @@
     /**
      * Returns the {@link AnimatorSet} for the transition between the Link icon and the Tab icon.
      */
-    private AnimatorSet getTransitionAnimator(boolean isNewDuration) {
+    private AnimatorSet getTransitionAnimator() {
         AnimatorSet animatorSet = new AnimatorSet();
         ObjectAnimator fadeAnimator = ObjectAnimator.ofFloat(mLinkIcon, View.ALPHA, 1f, 0f);
 
@@ -267,8 +254,7 @@
             ObjectAnimator scaleXAnimator = ObjectAnimator.ofFloat(mLinkIcon, View.SCALE_X, 1f, 0f);
             ObjectAnimator scaleYAnimator = ObjectAnimator.ofFloat(mLinkIcon, View.SCALE_Y, 1f, 0f);
             animatorSet.playTogether(scaleXAnimator, scaleYAnimator, fadeAnimator);
-            animatorSet.setDuration(
-                    isNewDuration ? NEW_LINK_SCALE_DURATION_MS : LINK_SCALE_DURATION_MS);
+            animatorSet.setDuration(LINK_SCALE_DURATION_MS);
             animatorSet.setInterpolator(Interpolators.STANDARD_INTERPOLATOR);
         } else {
             AnimatorSet fakeTabSwitcherAnimator = mFakeTabSwitcherButton.getScaleFadeAnimator();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java
index 2f1bbb7..02b98f4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/NewBackgroundTabFakeTabSwitcherButton.java
@@ -24,7 +24,6 @@
 
 import org.chromium.build.BuildConfig;
 import org.chromium.chrome.R;
-import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.theme.ThemeUtils;
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable;
 import org.chromium.chrome.browser.toolbar.TabSwitcherDrawable.TabSwitcherDrawableLocation;
@@ -46,8 +45,7 @@
  */
 public class NewBackgroundTabFakeTabSwitcherButton extends FrameLayout implements RunOnNextLayout {
     @VisibleForTesting /* package */ static final long TRANSLATE_DURATION_MS = 200L;
-    @VisibleForTesting /* package */ static final long SHRINK_DURATION_MS = 250L;
-    @VisibleForTesting /* package */ static final long NEW_SHRINK_DURATION_MS = 300L;
+    @VisibleForTesting /* package */ static final long SHRINK_DURATION_MS = 300L;
     @VisibleForTesting /* package */ static final long SCALE_DOWN_DURATION_MS = 50L;
 
     @IntDef({
@@ -133,10 +131,7 @@
 
         AnimatorSet animatorSet = new AnimatorSet();
         animatorSet.playTogether(scaleXAnimator, scaleYAnimator);
-        animatorSet.setDuration(
-                ChromeFeatureList.sShowNewTabAnimationsNewDuration.getValue()
-                        ? NEW_SHRINK_DURATION_MS
-                        : SHRINK_DURATION_MS);
+        animatorSet.setDuration(SHRINK_DURATION_MS);
 
         animatorSet.addListener(
                 new AnimatorListenerAdapter() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java
index 516aff6..6e09216d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/crash/ChromePureJavaExceptionReporter.java
@@ -52,6 +52,19 @@
     /**
      * Asynchronously report and upload the stack trace as if it was a crash.
      *
+     * @param msg The message to report.
+     * @param isWarning Whether the message should be treated as a warning.
+     */
+    public static void reportJavaExceptionFromMsg(String msg, boolean isWarning) {
+        if (isWarning) {
+            msg = "This is not a crash. " + msg;
+        }
+        reportJavaException(new Throwable(msg));
+    }
+
+    /**
+     * Asynchronously report and upload the stack trace as if it was a crash.
+     *
      * @param exception The exception to report.
      */
     public static void reportJavaException(Throwable exception) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java
index d6ca88a..eae5cd3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/hub/NewTabAnimationUtils.java
@@ -48,6 +48,7 @@
      * <p>These numbers match with the "version" feature param for ShowNewTabAnimations.
      */
     @IntDef({
+        NewTabAnim.M137,
         NewTabAnim.BOUNCE,
         NewTabAnim.DECELERATE,
         NewTabAnim.BOUNCE_DECELERATE,
@@ -56,6 +57,7 @@
     @Target(ElementType.TYPE_USE)
     @Retention(RetentionPolicy.SOURCE)
     public @interface NewTabAnim {
+        int M137 = 0;
         int BOUNCE = 1;
         int DECELERATE = 2;
         int BOUNCE_DECELERATE = 3;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
index a108169..3be8fe6d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/RootUiCoordinator.java
@@ -1900,7 +1900,9 @@
                 hasEdgeToEdgeController,
                 isSupportedConfiguration,
                 callSite,
-                (info) -> ChromePureJavaExceptionReporter.reportJavaException(new Throwable(info)));
+                (info) ->
+                        ChromePureJavaExceptionReporter.reportJavaExceptionFromMsg(
+                                info, /* isWarning= */ true));
     }
 
     /** Create a bottom chin for Edge-to-Edge. */
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index b92cef7..6b3d5529 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -4385,6 +4385,9 @@
   <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_ADVANCED_CONFIG_SELECT_DRIVER" desc="Label for the file selector to manually select a PPD file from the user's file system.">
     Alternatively, select printer PPD. <ph name="LINK_BEGIN">&lt;a&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
   </message>
+  <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANAGED_PRINTER_PPD" desc="Label for the text box displaying a path to the used PPD file for the active printer.">
+    Printer PPD
+  </message>
   <message name="IDS_SETTINGS_PRINTING_CUPS_PRINTER_SELECT_DRIVER" desc="Label for the file selector to manually select a PPD file from the user's file system.">
     or select PPD. <ph name="LINK_BEGIN">&lt;a&gt;</ph>Learn more<ph name="LINK_END">&lt;/a&gt;</ph>
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANAGED_PRINTER_PPD.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANAGED_PRINTER_PPD.png.sha1
new file mode 100644
index 0000000..7504c0a
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_PRINTING_CUPS_PRINTER_MANAGED_PRINTER_PPD.png.sha1
@@ -0,0 +1 @@
+22a0a883d053078e8d6a43fe9e24923b2097f875
\ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 62f3fc4..256d81e 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -1242,6 +1242,17 @@
      std::size(kTextSafetyClassifierNoRetractParams), nullptr},
 };
 
+const FeatureEntry::FeatureParam kPageActionsMigrationParams[] = {
+    {"lens_overlay", "true"},       {"translate", "true"},
+    {"memory_saver", "true"},       {"price_insights", "true"},
+    {"offer_notification", "true"}, {"intent_picker", "true"},
+    {"file_system_access", "true"},
+};
+const FeatureEntry::FeatureVariation kPageActionsMigrationVariations[] = {
+    {"with all migrated page actions enabled", kPageActionsMigrationParams,
+     std::size(kPageActionsMigrationParams), nullptr},
+};
+
 const FeatureEntry::FeatureParam kPageContentAnnotationsContentParams[] = {
     {"annotate_title_instead_of_page_content", "false"},
     {"extract_related_searches", "true"},
@@ -3757,35 +3768,24 @@
         {" - all windowing modes", kAuxiliaryNavigationStaysInBrowserOn,
          std::size(kAuxiliaryNavigationStaysInBrowserOn), nullptr}};
 
-const FeatureEntry::FeatureParam kShowNewTabAnimationsNewDurationOnly[] = {
-    {"version", "0"},
-    {"new-duration", "true"}};
 const FeatureEntry::FeatureParam kShowNewTabAnimationsBounce[] = {
-    {"version", "1"},
-    {"new-duration", "true"}};
+    {"version", "1"}};
 const FeatureEntry::FeatureParam kShowNewTabAnimationsDecelerate[] = {
-    {"version", "2"},
-    {"new-duration", "true"}};
+    {"version", "2"}};
 const FeatureEntry::FeatureParam kShowNewTabAnimationsBounceDecelerate[] = {
-    {"version", "3"},
-    {"new-duration", "true"}};
-const FeatureEntry::FeatureParam
-    kShowNewTabAnimationsBounceDecelerateWithDelay[] = {
-        {"version", "4"},
-        {"new-duration", "true"}};
+    {"version", "3"}};
+const FeatureEntry::FeatureParam kShowNewTabAnimationsM137[] = {
+    {"version", "0"}};
 const FeatureEntry::FeatureVariation kShowNewTabAnimationsVariations[] = {
-    {"- Use new duration only", kShowNewTabAnimationsNewDurationOnly,
-     std::size(kShowNewTabAnimationsNewDurationOnly), nullptr},
     {"- Bouncy GTS icon with delay", kShowNewTabAnimationsBounce,
      std::size(kShowNewTabAnimationsBounce), nullptr},
     {"- Bouncy GTS icon with decelerate arc",
      kShowNewTabAnimationsBounceDecelerate,
      std::size(kShowNewTabAnimationsBounceDecelerate), nullptr},
-    {"- Bouncy GTS icon with decelerate arc and delay",
-     kShowNewTabAnimationsBounceDecelerateWithDelay,
-     std::size(kShowNewTabAnimationsBounceDecelerateWithDelay), nullptr},
     {"- Decelerate arc", kShowNewTabAnimationsDecelerate,
      std::size(kShowNewTabAnimationsDecelerate), nullptr},
+    {"- M137 with new duration", kShowNewTabAnimationsM137,
+     std::size(kShowNewTabAnimationsM137), nullptr},
 };
 
 #endif  // BUILDFLAG(IS_ANDROID)
@@ -11229,6 +11229,11 @@
     {"infinite-tabs-freezing", flag_descriptions::kInfiniteTabsFreezingName,
      flag_descriptions::kInfiniteTabsFreezingDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(performance_manager::features::kInfiniteTabsFreezing)},
+
+    {"memory-purge-on-freeze-limit",
+     flag_descriptions::kMemoryPurgeOnFreezeLimitName,
+     flag_descriptions::kMemoryPurgeOnFreezeLimitDescription, kOsDesktop,
+     FEATURE_VALUE_TYPE(blink::features::kMemoryPurgeOnFreezeLimit)},
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 #if BUILDFLAG(IS_WIN)
@@ -12592,6 +12597,18 @@
      FEATURE_VALUE_TYPE(::features::kAccessibilityManifestV3EspeakNGTts)},
 #endif
 
+#if BUILDFLAG(IS_ANDROID)
+    {"mvc-update-view-when-model-changed",
+     flag_descriptions::kMvcUpdateViewWhenModelChangedName,
+     flag_descriptions::kMvcUpdateViewWhenModelChangedDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(chrome::android::kMvcUpdateViewWhenModelChanged)},
+#endif  // BUILDFLAG(IS_ANDROID)
+
+    {"page-actions-migration", flag_descriptions::kPageActionsMigrationName,
+     flag_descriptions::kPageActionsMigrationDescription, kOsDesktop,
+     FEATURE_WITH_PARAMS_VALUE_TYPE(features::kPageActionsMigration,
+                                    kPageActionsMigrationVariations,
+                                    "PageActionsMigration")},
     // Add new entries above this line.
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/actor/BUILD.gn b/chrome/browser/actor/BUILD.gn
index 037378a..ac5ec46b 100644
--- a/chrome/browser/actor/BUILD.gn
+++ b/chrome/browser/actor/BUILD.gn
@@ -45,6 +45,7 @@
     "tools/wait_tool.h",
   ]
   public_deps = [
+    ":types",
     "//base",
     "//chrome/browser:browser_public_dependencies",
     "//components/optimization_guide/content/browser",
@@ -66,6 +67,14 @@
   ]
 }
 
+# This target contains only type definitions that may be depended on by other
+# headers without depending on all of :actor.
+# This avoids dependency cycles.
+source_set("types") {
+  sources = [ "task_id.h" ]
+  public_deps = [ "//base" ]
+}
+
 source_set("test_support") {
   testonly = true
   sources = [
diff --git a/chrome/browser/actor/actor_coordinator.cc b/chrome/browser/actor/actor_coordinator.cc
index 125c05d..6d24eeca 100644
--- a/chrome/browser/actor/actor_coordinator.cc
+++ b/chrome/browser/actor/actor_coordinator.cc
@@ -116,7 +116,7 @@
 };
 
 // static
-ActorCoordinator::TaskId::Generator ActorCoordinator::Task::id_generator_;
+TaskId::Generator ActorCoordinator::Task::id_generator_;
 
 ActorCoordinator::Action::Action(const BrowserAction& action,
                                  ActionResultCallback callback)
@@ -169,6 +169,21 @@
   task_state_.reset();
 }
 
+void ActorCoordinator::PauseTask() {
+  if (!task_state_) {
+    return;
+  }
+
+  if (task_state_->current_action) {
+    CompleteAction(
+        MakeResult(mojom::ActionResultCode::kTaskPaused, "Task was paused"));
+  }
+}
+
+tabs::TabInterface* ActorCoordinator::GetTabOfCurrentTask() const {
+  return task_state_ ? task_state_->tab.get() : nullptr;
+}
+
 bool ActorCoordinator::HasTask() const {
   return !!task_state_;
 }
diff --git a/chrome/browser/actor/actor_coordinator.h b/chrome/browser/actor/actor_coordinator.h
index 18e9e1f..b78b4bc0 100644
--- a/chrome/browser/actor/actor_coordinator.h
+++ b/chrome/browser/actor/actor_coordinator.h
@@ -13,6 +13,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/types/id_type.h"
+#include "chrome/browser/actor/task_id.h"
 #include "chrome/browser/actor/tools/tool_controller.h"
 #include "chrome/common/actor.mojom-forward.h"
 #include "components/tabs/public/tab_interface.h"
@@ -75,9 +76,15 @@
                  StartTaskCallback callback,
                  std::optional<tabs::TabHandle> tab_handle);
 
-  // Stops the currently running task, if one is active. Callbacks for
+  // Stops the current task, if it's active. Callbacks for
   // in-progress actions are invoked.
   void StopTask();
+  // Pauses the current task, if it's active. Callbacks for in-progress actions
+  // are invoked.
+  void PauseTask();
+
+  // Returns the tab associated with the current task if it exists.
+  tabs::TabInterface* GetTabOfCurrentTask() const;
 
   // Returns true if a task is currently active.
   bool HasTask() const;
@@ -96,8 +103,6 @@
 
  private:
   class NewTabWebContentsObserver;
-  struct Task;
-  using TaskId = base::IdType32<Task>;
 
   // Starts a new task, after validating there isn't already a task being
   // initialized or in progress.
@@ -152,6 +157,8 @@
 
     TaskId id;
 
+    // TODO(mcnee): Ensure this task can't outlive the tab, then stop using weak
+    // ptr.
     base::WeakPtr<tabs::TabInterface> tab;
     ToolController tool_controller;
 
diff --git a/chrome/browser/actor/actor_features.cc b/chrome/browser/actor/actor_features.cc
index 7ea17d9..fb0d7387 100644
--- a/chrome/browser/actor/actor_features.cc
+++ b/chrome/browser/actor/actor_features.cc
@@ -13,7 +13,7 @@
 
 BASE_FEATURE(kGlicActionAllowlist,
              "GlicActionAllowlist",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE_PARAM(std::string,
                    kAllowlist,
diff --git a/chrome/browser/actor/actor_task.h b/chrome/browser/actor/actor_task.h
index a52ed48d..56d2aee 100644
--- a/chrome/browser/actor/actor_task.h
+++ b/chrome/browser/actor/actor_task.h
@@ -23,11 +23,19 @@
   // Once state leaves kCreated it should never go back. One state enters
   // kFinished it should never change. We may want to add a kCancelled in the
   // future, TBD.
-  enum class State { kCreated, kActing, kReflecting, kFinished };
+  enum class State {
+    kCreated,
+    kActing,
+    kReflecting,
+    kPausedByClient,
+    kFinished
+  };
 
   State GetState() const;
   void SetState(State state);
 
+  bool IsPaused() const { return GetState() == State::kPausedByClient; }
+
   ActorCoordinator* GetActorCoordinator() const;
 
  private:
diff --git a/chrome/browser/actor/task_id.h b/chrome/browser/actor/task_id.h
new file mode 100644
index 0000000..b94f2e4
--- /dev/null
+++ b/chrome/browser/actor/task_id.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 CHROME_BROWSER_ACTOR_TASK_ID_H_
+#define CHROME_BROWSER_ACTOR_TASK_ID_H_
+
+#include "base/types/id_type.h"
+
+namespace actor {
+
+using TaskId = base::IdType32<class TaskIdTag>;
+
+static_assert(TaskId(0).is_null(), "0 must be a null TaskId");
+
+}  // namespace actor
+
+#endif  // CHROME_BROWSER_ACTOR_TASK_ID_H_
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
index 2b9e8c2..e64d972 100644
--- a/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
+++ b/chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.cc
@@ -24,7 +24,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/strcat.h"
 #include "base/task/bind_post_task.h"
 #include "base/task/thread_pool.h"
@@ -1053,8 +1052,7 @@
             kClearBrowsingData);
   }
 
-  CHECK(deferred_disable_passwords_auto_signin_cb_.is_null(),
-        base::NotFatalUntil::M125);
+  CHECK(deferred_disable_passwords_auto_signin_cb_.is_null());
   if ((remove_mask & content::BrowsingDataRemover::DATA_TYPE_COOKIES) &&
       !filter_builder->PartitionedCookiesOnly()) {
     // Unretained() is safe, this is only executed in OnTasksComplete() if the
diff --git a/chrome/browser/chrome_resource_bundle_helper.cc b/chrome/browser/chrome_resource_bundle_helper.cc
index ce767eb..2c437e5 100644
--- a/chrome/browser/chrome_resource_bundle_helper.cc
+++ b/chrome/browser/chrome_resource_bundle_helper.cc
@@ -65,15 +65,10 @@
 std::string InitResourceBundleAndDetermineLocale(PrefService* local_state,
                                                  bool is_running_tests) {
 #if BUILDFLAG(IS_ANDROID)
-  // In order for SetLoadSecondaryLocalePaks() to work ResourceBundle must
-  // not have been created yet.
+  // In order for DetectAndSetLoadSecondaryLocalePaks() to work ResourceBundle
+  // must not have been created yet.
   DCHECK(!ui::ResourceBundle::HasSharedInstance());
-  // Auto-detect based on en-US whether secondary locale .pak files exist.
-  bool in_split = false;
-  bool log_error = false;
-  ui::SetLoadSecondaryLocalePaks(
-      !ui::GetPathForAndroidLocalePakWithinApk("en-US", in_split, log_error)
-           .empty());
+  ui::DetectAndSetLoadSecondaryLocalePaks();
 #endif
 
   std::string preferred_locale;
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
index e38a1bc..f85f061f 100644
--- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
+++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.cc
@@ -266,6 +266,23 @@
   return true;
 }
 
+bool GetValue(const base::Value& value, FunctionCallEvent* event) {
+  if (!value.is_dict()) {
+    return false;
+  }
+
+  std::optional<int> name = value.GetDict().FindInt("name");
+  if (name) {
+    event->name = *name;
+  }
+
+  std::optional<int> context = value.GetDict().FindInt("context");
+  if (context) {
+    event->context = *context;
+  }
+  return true;
+}
+
 template <typename T>
 struct StorageTraits {
   using StorageType = T;
@@ -459,6 +476,8 @@
   d->RegisterHandler("recordKeyDown", &Delegate::RecordKeyDown, delegate);
   d->RegisterHandler("recordSettingAccess", &Delegate::RecordSettingAccess,
                      delegate);
+  d->RegisterHandler("recordFunctionCall", &Delegate::RecordFunctionCall,
+                     delegate);
   d->RegisterHandler("registerPreference", &Delegate::RegisterPreference,
                      delegate);
   d->RegisterHandlerWithCallback("getPreferences",
diff --git a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
index d3caa806..a5d49c8 100644
--- a/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
+++ b/chrome/browser/devtools/devtools_embedder_message_dispatcher.h
@@ -24,6 +24,7 @@
 struct ChangeEvent;
 struct KeyDownEvent;
 struct SettingAccessEvent;
+struct FunctionCallEvent;
 
 /**
  * Dispatcher for messages sent from the DevTools frontend running in an
@@ -127,6 +128,7 @@
     virtual void RecordChange(const ChangeEvent& event) = 0;
     virtual void RecordKeyDown(const KeyDownEvent& event) = 0;
     virtual void RecordSettingAccess(const SettingAccessEvent& event) = 0;
+    virtual void RecordFunctionCall(const FunctionCallEvent& event) = 0;
     virtual void Reattach(DispatchCallback callback) = 0;
     virtual void ReadyForTest() = 0;
     virtual void ConnectionReady() = 0;
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index a3f1e1c..533c3a7 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -2155,6 +2155,18 @@
           .SetSessionId(session_id_for_logging_.GetLowForSerialization()));
 }
 
+void DevToolsUIBindings::RecordFunctionCall(const FunctionCallEvent& event) {
+  if (!MaybeStartLogging()) {
+    return;
+  }
+  metrics::structured::StructuredMetricsClient::Record(
+      metrics::structured::events::v2::dev_tools::FunctionCall()
+          .SetName(event.name)
+          .SetContext(event.context)
+          .SetTimeSinceSessionStart(GetTimeSinceSessionStart().InMilliseconds())
+          .SetSessionId(session_id_for_logging_.GetLowForSerialization()));
+}
+
 void DevToolsUIBindings::DeviceCountChanged(int count) {
   CallClientMethod("DevToolsAPI", "deviceCountUpdated", base::Value(count));
 }
diff --git a/chrome/browser/devtools/devtools_ui_bindings.h b/chrome/browser/devtools/devtools_ui_bindings.h
index dca492dd..09580c9e 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.h
+++ b/chrome/browser/devtools/devtools_ui_bindings.h
@@ -218,6 +218,7 @@
   void RecordChange(const ChangeEvent& event) override;
   void RecordKeyDown(const KeyDownEvent& event) override;
   void RecordSettingAccess(const SettingAccessEvent& event) override;
+  void RecordFunctionCall(const FunctionCallEvent& event) override;
   void RegisterPreference(const std::string& name,
                           const RegisterOptions& options) override;
   void GetPreferences(DispatchCallback callback) override;
diff --git a/chrome/browser/devtools/visual_logging.h b/chrome/browser/devtools/visual_logging.h
index 22233576..b6dd8e8 100644
--- a/chrome/browser/devtools/visual_logging.h
+++ b/chrome/browser/devtools/visual_logging.h
@@ -64,6 +64,11 @@
   int string_value = -1;
 };
 
+struct FunctionCallEvent {
+  int name = -1;
+  int context = -1;
+};
+
 enum SessionTags {
   kUserSignedIn = 1 << 0,
   kDevToolsGetAiEnterprisePolicyDisabled = 1 << 1,
diff --git a/chrome/browser/enterprise/client_certificates/client_certificates_browsertest.cc b/chrome/browser/enterprise/client_certificates/client_certificates_browsertest.cc
deleted file mode 100644
index 734396ef..0000000
--- a/chrome/browser/enterprise/client_certificates/client_certificates_browsertest.cc
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/strings/stringprintf.h"
-#include "base/test/metrics/histogram_tester.h"
-#include "base/test/test_future.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/browser/enterprise/client_certificates/certificate_provisioning_service_factory.h"
-#include "chrome/browser/enterprise/test/management_context_mixin.h"
-#include "chrome/browser/policy/chrome_browser_policy_connector.h"
-#include "chrome/browser/profiles/profile.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/test/base/chrome_test_utils.h"
-#include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "chrome/test/base/platform_browser_test.h"
-#include "components/enterprise/browser/controller/chrome_browser_cloud_management_controller.h"
-#include "components/enterprise/client_certificates/core/certificate_provisioning_service.h"
-#include "components/enterprise/client_certificates/core/client_identity.h"
-#include "components/enterprise/client_certificates/core/features.h"
-#include "components/policy/core/common/policy_switches.h"
-#include "components/policy/policy_constants.h"
-#include "components/policy/test_support/embedded_policy_test_server.h"
-#include "content/public/test/browser_test.h"
-#include "crypto/scoped_fake_unexportable_key_provider.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace client_certificates {
-
-using ManagementContextMixin = enterprise::test::ManagementContextMixin;
-using ManagementContext = enterprise::test::ManagementContext;
-
-namespace {
-
-constexpr char kProfileIssuerCommonName[] = "Profile Root CA";
-constexpr char kBrowserIssuerCommonName[] = "Browser Root CA";
-
-}  // namespace
-
-class ClientCertificateBrowserTest : public MixinBasedInProcessBrowserTest,
-                                     public testing::WithParamInterface<bool> {
- protected:
-  ClientCertificateBrowserTest() {
-    management_mixin_ = ManagementContextMixin::Create(
-        &mixin_host_, this,
-        {
-            .is_cloud_user_managed = is_profile_scenario(),
-            .is_cloud_machine_managed = !is_profile_scenario(),
-            .affiliated = false,
-        });
-  }
-
-  void SetUpInProcessBrowserTestFixture() override {
-    test_dm_server_ = std::make_unique<policy::EmbeddedPolicyTestServer>();
-    ASSERT_TRUE(test_dm_server_->Start());
-
-    policy::ChromeBrowserPolicyConnector::EnableCommandLineSupportForTesting();
-    base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
-    command_line->AppendSwitchASCII(policy::switches::kDeviceManagementUrl,
-                                    test_dm_server_->GetServiceURL().spec());
-
-    MixinBasedInProcessBrowserTest::SetUpInProcessBrowserTestFixture();
-  }
-
-  void SetUserPolicy(bool enable_provisioning) {
-    base::flat_map<std::string, std::optional<base::Value>> policy_values;
-    policy_values.insert(
-        {policy::key::kProvisionManagedClientCertificateForUser,
-         base::Value(enable_provisioning ? 1 : 0)});
-
-    management_mixin()->SetCloudUserPolicies(std::move(policy_values));
-  }
-
-  void SetBrowserPolicy(bool enable_provisioning) {
-    base::flat_map<std::string, std::optional<base::Value>> policy_values;
-    policy_values.insert(
-        {policy::key::kProvisionManagedClientCertificateForBrowser,
-         base::Value(enable_provisioning ? 1 : 0)});
-
-    management_mixin()->SetCloudMachinePolicies(std::move(policy_values));
-  }
-
-  void EnablePolicyAndWaitForIdentity() {
-    CertificateProvisioningService* provisioning_service;
-    if (is_profile_scenario()) {
-      SetUserPolicy(true);
-      provisioning_service =
-          CertificateProvisioningServiceFactory::GetForProfile(
-              browser()->profile());
-    } else {
-      SetBrowserPolicy(true);
-      provisioning_service = g_browser_process->browser_policy_connector()
-                                 ->chrome_browser_cloud_management_controller()
-                                 ->GetCertificateProvisioningService();
-    }
-
-    ASSERT_TRUE(provisioning_service);
-
-    base::test::TestFuture<std::optional<ClientIdentity>> test_future;
-    provisioning_service->GetManagedIdentity(test_future.GetCallback());
-
-    VerifyIdentity(test_future.Get());
-  }
-
-  void VerifyIdentity(const std::optional<ClientIdentity>& managed_identity) {
-    ASSERT_TRUE(managed_identity);
-    ASSERT_TRUE(managed_identity->is_valid());
-
-    // Verify that the right cert was created based on the root CA's CN.
-    auto& cert = managed_identity->certificate;
-    EXPECT_EQ(cert->issuer().common_name, is_profile_scenario()
-                                              ? kProfileIssuerCommonName
-                                              : kBrowserIssuerCommonName);
-  }
-
-  ManagementContextMixin* management_mixin() { return management_mixin_.get(); }
-
-  base::HistogramTester& histogram_tester() { return histogram_tester_; }
-
-  bool is_profile_scenario() const { return GetParam(); }
-
- private:
-  base::HistogramTester histogram_tester_;
-  std::unique_ptr<policy::EmbeddedPolicyTestServer> test_dm_server_;
-  crypto::ScopedFakeUnexportableKeyProvider scoped_key_provider_;
-  std::unique_ptr<ManagementContextMixin> management_mixin_;
-};
-
-IN_PROC_BROWSER_TEST_P(ClientCertificateBrowserTest, CreateNewIdentity) {
-  EnablePolicyAndWaitForIdentity();
-  histogram_tester().ExpectUniqueSample(
-      base::StringPrintf(
-          "Enterprise.ClientCertificate.%s.Provisioning.CertificateCreation."
-          "Outcome",
-          is_profile_scenario() ? "Profile" : "Browser"),
-      true, 1);
-}
-
-IN_PROC_BROWSER_TEST_P(ClientCertificateBrowserTest, PRE_LoadExistingIdentity) {
-  EnablePolicyAndWaitForIdentity();
-}
-
-IN_PROC_BROWSER_TEST_P(ClientCertificateBrowserTest, LoadExistingIdentity) {
-  EnablePolicyAndWaitForIdentity();
-  histogram_tester().ExpectUniqueSample(
-      base::StringPrintf(
-          "Enterprise.ClientCertificate.%s.Provisioning.ExistingIdentity."
-          "Outcome",
-          is_profile_scenario() ? "Profile" : "Browser"),
-      true, 1);
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    /* no prefix */,
-    ClientCertificateBrowserTest,
-    testing::Bool());
-
-}  // namespace client_certificates
diff --git a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog.cc b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog.cc
index 97a159c..968d702 100644
--- a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog.cc
+++ b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog.cc
@@ -254,15 +254,8 @@
   scoped_ignore_input_events_ =
       top_web_contents->IgnoreInputEvents(std::nullopt);
 
-  if (auto* tab_interface =
-          tabs::TabInterface::MaybeGetFromContents(top_web_contents);
-      tab_interface && tab_interface->CanShowModalUI()) {
-    tab_interface->GetTabFeatures()
-        ->tab_dialog_manager()
-        ->ShowDialogAndBlockTabInteraction(widget_.get());
-  } else {
-    widget_->Show();
-  }
+  constrained_window::ShowModalDialog(widget_->GetNativeWindow(),
+                                      top_web_contents);
 }
 
 void DesktopDataControlsDialog::CloseDialog(
diff --git a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_browsertest.cc b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_browsertest.cc
index b3cd98fb..463d639 100644
--- a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_browsertest.cc
+++ b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_browsertest.cc
@@ -6,6 +6,7 @@
 
 #include "base/functional/callback_helpers.h"
 #include "chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_factory.h"
+#include "chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_test_helper.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_commands.h"
@@ -29,9 +30,18 @@
 
   // DialogBrowserTest:
   void ShowUi(const std::string& name) override {
+    helper_ = std::make_unique<DesktopDataControlsDialogTestHelper>(type());
     DesktopDataControlsDialogFactory::GetInstance()->ShowDialogIfNeeded(
         browser()->tab_strip_model()->GetActiveWebContents(), type());
   }
+
+  void DismissUi() override {
+    helper_->CloseDialogWithoutBypass();
+    helper_->WaitForDialogToClose();
+  }
+
+ private:
+  std::unique_ptr<DesktopDataControlsDialogTestHelper> helper_;
 };
 
 class DesktopDataControlsDialogTest : public InProcessBrowserTest,
diff --git a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_test_helper.h b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_test_helper.h
index 00e80f32..0ac280e 100644
--- a/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_test_helper.h
+++ b/chrome/browser/enterprise/data_controls/desktop_data_controls_dialog_test_helper.h
@@ -18,7 +18,7 @@
  public:
   explicit DesktopDataControlsDialogTestHelper(
       DataControlsDialog::Type expected_dialog_type);
-  ~DesktopDataControlsDialogTestHelper();
+  virtual ~DesktopDataControlsDialogTestHelper();
 
   // DesktopDataControlsDialog::TestObserver:
   void OnConstructed(DesktopDataControlsDialog* dialog,
diff --git a/chrome/browser/enterprise/test/browser/management_context_mixin_browser.cc b/chrome/browser/enterprise/test/browser/management_context_mixin_browser.cc
index a601cdb..a1c1ecd8 100644
--- a/chrome/browser/enterprise/test/browser/management_context_mixin_browser.cc
+++ b/chrome/browser/enterprise/test/browser/management_context_mixin_browser.cc
@@ -10,6 +10,7 @@
 #include "chrome/browser/policy/chrome_browser_policy_connector.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/test/base/in_process_browser_test.h"
+#include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h"
 #include "components/enterprise/browser/enterprise_switches.h"
 #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h"
 #include "components/policy/core/common/cloud/mock_cloud_policy_client.h"
@@ -43,10 +44,7 @@
     InProcessBrowserTestMixinHost* host,
     InProcessBrowserTest* test_base,
     ManagementContext management_context)
-    : ManagementContextMixin(host, test_base, std::move(management_context)) {
-  // Fake the OS' device ID.
-  browser_dm_token_storage_.SetClientId(kBrowserClientId);
-}
+    : ManagementContextMixin(host, test_base, std::move(management_context)) {}
 
 ManagementContextMixinBrowser::~ManagementContextMixinBrowser() = default;
 
@@ -81,6 +79,14 @@
   }
 }
 
+void ManagementContextMixinBrowser::SetUpInProcessBrowserTestFixture() {
+  browser_dm_token_storage_ =
+      std::make_unique<policy::FakeBrowserDMTokenStorage>();
+
+  policy::BrowserDMTokenStorage::SetForTesting(browser_dm_token_storage_.get());
+  ManagementContextMixin::SetUpInProcessBrowserTestFixture();
+}
+
 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
 void ManagementContextMixinBrowser::SetUpDefaultCommandLine(
     base::CommandLine* command_line) {
@@ -91,8 +97,11 @@
 
 void ManagementContextMixinBrowser::ManageCloudMachine() {
   ManagementContextMixin::ManageCloudMachine();
-  browser_dm_token_storage_.SetEnrollmentToken(kEnrollmentToken);
-  browser_dm_token_storage_.SetDMToken(kBrowserDmToken);
+  CHECK(browser_dm_token_storage_);
+  browser_dm_token_storage_->SetEnrollmentToken(kEnrollmentToken);
+  browser_dm_token_storage_->SetClientId(kBrowserClientId);
+  browser_dm_token_storage_->EnableStorage(true);
+  browser_dm_token_storage_->SetDMToken(kBrowserDmToken);
 }
 
 void ManagementContextMixinBrowser::SetCloudMachinePolicies(
diff --git a/chrome/browser/enterprise/test/browser/management_context_mixin_browser.h b/chrome/browser/enterprise/test/browser/management_context_mixin_browser.h
index 8ca8df7c..25415c3 100644
--- a/chrome/browser/enterprise/test/browser/management_context_mixin_browser.h
+++ b/chrome/browser/enterprise/test/browser/management_context_mixin_browser.h
@@ -10,7 +10,6 @@
 #include "build/branding_buildflags.h"
 #include "chrome/browser/enterprise/test/management_context_mixin.h"
 #include "chrome/test/base/mixin_based_in_process_browser_test.h"
-#include "components/enterprise/browser/controller/fake_browser_dm_token_storage.h"
 
 namespace policy {
 class FakeBrowserDMTokenStorage;
@@ -37,6 +36,9 @@
   // InProcessBrowserTestMixin:
   void SetUpOnMainThread() override;
 
+  // ManagementContextMixin:
+  void SetUpInProcessBrowserTestFixture() override;
+
 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
   void SetUpDefaultCommandLine(base::CommandLine* command_line) override;
 #endif
@@ -48,7 +50,7 @@
       override;
 
  private:
-  policy::FakeBrowserDMTokenStorage browser_dm_token_storage_;
+  std::unique_ptr<policy::FakeBrowserDMTokenStorage> browser_dm_token_storage_;
 };
 
 }  // namespace enterprise::test
diff --git a/chrome/browser/enterprise/test/management_context_mixin.cc b/chrome/browser/enterprise/test/management_context_mixin.cc
index 3282170..17d5889 100644
--- a/chrome/browser/enterprise/test/management_context_mixin.cc
+++ b/chrome/browser/enterprise/test/management_context_mixin.cc
@@ -94,8 +94,6 @@
   user_policy_data->add_user_affiliation_ids(user_customer_id);
   user_policy_data->set_username(kTestUserEmail);
   user_policy_data->set_gaia_id(kTestUserId);
-  user_policy_data->set_device_id(kProfileClientId);
-  user_policy_data->set_request_token(kProfileDmToken);
   return user_policy_data;
 }
 
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 0b9e273..9760d9dd 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -6480,6 +6480,11 @@
     "expiry_milestone": -1
   },
   {
+    "name": "memory-purge-on-freeze-limit",
+    "owners": [ "fdoray@chromium.org", "catan-team@chromium.org" ],
+    "expiry_milestone": 142
+  },
+  {
     "name": "merchant-trust",
     "owners": [ "tommasin@chromium.org", "privacy-on-the-web@google.com" ],
     "expiry_milestone": 145
@@ -6572,6 +6577,11 @@
     "expiry_milestone": 96
   },
   {
+    "name": "mvc-update-view-when-model-changed",
+    "owners": [ "acondor@chromium.org" ],
+    "expiry_milestone": 139
+  },
+  {
     "name": "nav-bar-color-animation",
     "owners": [ "clhager@google.com", "wenyufu@chromium.org","twellington@chromium.org" ],
     "expiry_milestone": 150
@@ -7413,6 +7423,11 @@
     "expiry_milestone": 150
   },
   {
+    "name": "page-actions-migration",
+    "owners": [ "alsan@google.com", "chrome-desktop-ui-waterloo@google.com" ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "page-content-annotations",
     "owners": [ "sophiechang@chromium.org", "mcrouse@chromium.org", "chrome-intelligence-core@google.com"],
     "expiry_milestone": 150
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index 8914d1b3..49841ddd 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -1173,6 +1173,14 @@
     "Enables the 'enterpictureinpicture' MediaSessionAction to allow websites "
     "to register an action handler for entering picture-in-picture.";
 
+#if BUILDFLAG(IS_ANDROID)
+const char kMvcUpdateViewWhenModelChangedName[] =
+    "MVC Update View when Model Changed";
+const char kMvcUpdateViewWhenModelChangedDescription[] =
+    "Performance optimization to the MVC framework where a View is only "
+    "updated when the corresponding Model changes.";
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 const char kCodeBasedRBDName[] = "Code-based RBD";
 const char kCodeBasedRBDDescription[] = "Enables the Code-based RBD.";
 
@@ -3135,6 +3143,10 @@
 const char kOverscrollHistoryNavigationDescription[] =
     "History navigation in response to horizontal overscroll.";
 
+const char kPageActionsMigrationName[] = "Page actions migration";
+const char kPageActionsMigrationDescription[] =
+    "Enables a new internal framework for driving page actions behavior.";
+
 const char kPageContentAnnotationsName[] = "Page content annotations";
 const char kPageContentAnnotationsDescription[] =
     "Enables page content to be annotated on-device.";
@@ -5528,6 +5540,12 @@
     "functionality (e.g. playing audio, handling a video call) are not "
     "eligible for freezing.";
 
+const char kMemoryPurgeOnFreezeLimitName[] = "Memory Purge on Freeze Limit";
+const char kMemoryPurgeOnFreezeLimitDescription[] =
+    "Do not purge memory in renderers with frozen pages more than once per "
+    "backgrounded interval, to minimize overhead when pages are periodically "
+    "unfrozen. To be enabled with memory-purge-on-freeze-limit.";
+
 const char kKeyboardLockPromptName[] = "Keyboard Lock prompt";
 const char kKeyboardLockPromptDescription[] =
     "Requesting to use the keyboard lock API causes a permission prompt to be "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 7d390644..776cd1f 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -321,7 +321,7 @@
 
 extern const char kClearInstanceInfoWhenClosedIntentionallyName[];
 extern const char kClearInstanceInfoWhenClosedIntentionallyDescription[];
-#endif
+#endif  // !BUILDFLAG(IS_ANDROID)
 
 extern const char kEnableBenchmarkingName[];
 extern const char kEnableBenchmarkingDescription[];
@@ -359,6 +359,11 @@
 extern const char kMediaSessionEnterPictureInPictureName[];
 extern const char kMediaSessionEnterPictureInPictureDescription[];
 
+#if BUILDFLAG(IS_ANDROID)
+extern const char kMvcUpdateViewWhenModelChangedName[];
+extern const char kMvcUpdateViewWhenModelChangedDescription[];
+#endif  // !BUILDFLAG(IS_ANDROID)
+
 extern const char kEnableDrDcName[];
 extern const char kEnableDrDcDescription[];
 
@@ -1812,6 +1817,9 @@
 extern const char kOverscrollHistoryNavigationName[];
 extern const char kOverscrollHistoryNavigationDescription[];
 
+extern const char kPageActionsMigrationName[];
+extern const char kPageActionsMigrationDescription[];
+
 extern const char kPageContentAnnotationsName[];
 extern const char kPageContentAnnotationsDescription[];
 
@@ -3243,6 +3251,9 @@
 extern const char kInfiniteTabsFreezingName[];
 extern const char kInfiniteTabsFreezingDescription[];
 
+extern const char kMemoryPurgeOnFreezeLimitName[];
+extern const char kMemoryPurgeOnFreezeLimitDescription[];
+
 extern const char kKeyboardLockPromptName[];
 extern const char kKeyboardLockPromptDescription[];
 
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 8b5d39a..8adadbe1 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
@@ -1587,10 +1587,8 @@
             sDisableBottomControlsStackerYOffsetDispatching =
                     sBottomBrowserControlsRefactor.newBooleanParam(
                             "disable_bottom_controls_stacker_y_offset", false);
-    public static final MutableBooleanParamWithSafeDefault sShowNewTabAnimationsNewDuration =
-            sShowNewTabAnimations.newBooleanParam("new-duration", false);
     public static final MutableIntParamWithSafeDefault sShowNewTabAnimationsVersion =
-            sShowNewTabAnimations.newIntParam("version", 0);
+            sShowNewTabAnimations.newIntParam("version", 4);
     public static final MutableIntParamWithSafeDefault sTabSwitcherColorBlendAnimateDurationMs =
             sTabSwitcherColorBlendAnimate.newIntParam("animation_duration_ms", 240);
     public static final MutableIntParamWithSafeDefault sTabSwitcherColorBlendAnimateInterpolator =
diff --git a/chrome/browser/gesturenav/android/tab_on_back_gesture_handler.cc b/chrome/browser/gesturenav/android/tab_on_back_gesture_handler.cc
index 868e133..d74101b 100644
--- a/chrome/browser/gesturenav/android/tab_on_back_gesture_handler.cc
+++ b/chrome/browser/gesturenav/android/tab_on_back_gesture_handler.cc
@@ -61,7 +61,7 @@
 
   is_in_progress_ = true;
   content::WebContents* web_contents = tab_android_->web_contents();
-  CHECK(web_contents, base::NotFatalUntil::M123);
+  CHECK(web_contents);
   AssertHasWindowAndCompositor(web_contents);
 
   ui::BackGestureEvent back_gesture(progress);
diff --git a/chrome/browser/glic/BUILD.gn b/chrome/browser/glic/BUILD.gn
index 51a70054..d2eac20 100644
--- a/chrome/browser/glic/BUILD.gn
+++ b/chrome/browser/glic/BUILD.gn
@@ -75,6 +75,7 @@
     "//ui/webui",
   ]
   deps = [
+    "//chrome/browser/actor:types",
     "//chrome/common",
     "//components/user_education/common",
   ]
diff --git a/chrome/browser/glic/glic_keyed_service.cc b/chrome/browser/glic/glic_keyed_service.cc
index e995442..6e90279 100644
--- a/chrome/browser/glic/glic_keyed_service.cc
+++ b/chrome/browser/glic/glic_keyed_service.cc
@@ -378,10 +378,25 @@
                          std::move(callback));
 }
 
-void GlicKeyedService::StopActorTask() {
+void GlicKeyedService::StopActorTask(actor::TaskId task_id) {
   CHECK(base::FeatureList::IsEnabled(features::kGlicActor));
   CHECK(actor_controller_);
-  actor_controller_->StopTask();
+  actor_controller_->StopTask(task_id);
+}
+
+void GlicKeyedService::PauseActorTask(actor::TaskId task_id) {
+  CHECK(base::FeatureList::IsEnabled(features::kGlicActor));
+  CHECK(actor_controller_);
+  actor_controller_->PauseTask(task_id);
+}
+
+void GlicKeyedService::ResumeActorTask(
+    actor::TaskId task_id,
+    const mojom::GetTabContextOptions& context_options,
+    glic::mojom::WebClientHandler::ResumeActorTaskCallback callback) {
+  CHECK(base::FeatureList::IsEnabled(features::kGlicActor));
+  CHECK(actor_controller_);
+  actor_controller_->ResumeTask(task_id, context_options, std::move(callback));
 }
 
 bool GlicKeyedService::IsActorCoordinatorActingOnTab(
diff --git a/chrome/browser/glic/glic_keyed_service.h b/chrome/browser/glic/glic_keyed_service.h
index 77a72dca..337e3dca3 100644
--- a/chrome/browser/glic/glic_keyed_service.h
+++ b/chrome/browser/glic/glic_keyed_service.h
@@ -12,6 +12,7 @@
 #include "base/containers/flat_set.h"
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/actor/task_id.h"
 #include "chrome/browser/glic/host/context/glic_focused_tab_manager.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
 #include "components/keyed_service/core/keyed_service.h"
@@ -200,7 +201,12 @@
       const mojom::GetTabContextOptions& options,
       mojom::WebClientHandler::ActInFocusedTabCallback callback);
 
-  void StopActorTask();
+  void StopActorTask(actor::TaskId task_id);
+  void PauseActorTask(actor::TaskId task_id);
+  void ResumeActorTask(
+      actor::TaskId task_id,
+      const mojom::GetTabContextOptions& context_options,
+      glic::mojom::WebClientHandler::ResumeActorTaskCallback callback);
 
   // Returns true if the associated ActorCoordinator is active on the given
   // `tab`. This can be used by callers to customize certain behaviour that
diff --git a/chrome/browser/glic/glic_user_status_browsertest.cc b/chrome/browser/glic/glic_user_status_browsertest.cc
index b3c8607..32829c6 100644
--- a/chrome/browser/glic/glic_user_status_browsertest.cc
+++ b/chrome/browser/glic/glic_user_status_browsertest.cc
@@ -72,7 +72,8 @@
          {features::kTabstripComboButton, {}},
          {features::kGlicRollout, {}},
          {features::kGlicUserStatusCheck,
-          {{features::kGlicUserStatusRequestDelay.name, "200ms"}}}},
+          {{features::kGlicUserStatusRequestDelay.name, "200ms"},
+           {features::kGlicUserStatusRequestDelayJitter.name, "0"}}}},
         {/* disabled_features */});
 
     RegisterGeminiSettingsPrefs(pref_service_.registry());
diff --git a/chrome/browser/glic/glic_user_status_fetcher.cc b/chrome/browser/glic/glic_user_status_fetcher.cc
index bca219e..4bd0508 100644
--- a/chrome/browser/glic/glic_user_status_fetcher.cc
+++ b/chrome/browser/glic/glic_user_status_fetcher.cc
@@ -105,7 +105,7 @@
   if (next_update_time <= base::Time::Now()) {
     UpdateUserStatus();
   } else {
-    ScheduleUserStatusUpdate(next_update_time);
+    ScheduleUserStatusUpdate(next_update_time - base::Time::Now());
   }
 }
 
@@ -219,9 +219,19 @@
 }
 
 void GlicUserStatusFetcher::ScheduleUserStatusUpdate(
-    base::Time next_update_time) {
+    base::TimeDelta time_to_next_update) {
+  // Calculate a random offset for the delay. The range of the offset will be
+  // from [1- jitter*random_multiplier, 1 + jitter*random_multiplier).
+  // random_multiplier is in the range [-1,1) by (base::RandDouble() - 0.5)* 2.
+  const double jitter_factor =
+      1 + features::kGlicUserStatusRequestDelayJitter.Get() *
+              (base::RandDouble() - 0.5) * 2;
+
+  base::Time scheduled_time =
+      base::Time::Now() + jitter_factor * time_to_next_update;
+
   refresh_status_timer_.Start(
-      FROM_HERE, next_update_time,
+      FROM_HERE, scheduled_time,
       base::BindOnce(&GlicUserStatusFetcher::UpdateUserStatus,
                      base::Unretained(this)));
 }
@@ -250,8 +260,7 @@
   CancelUserStatusUpdateIfNeeded();
 
   // schedule next run regardless.
-  ScheduleUserStatusUpdate(base::Time::Now() +
-                           features::kGlicUserStatusRequestDelay.Get());
+  ScheduleUserStatusUpdate(features::kGlicUserStatusRequestDelay.Get());
 
   auto account_info = GetGaiaIdHashForPrimaryAccount(profile_);
 
diff --git a/chrome/browser/glic/glic_user_status_fetcher.h b/chrome/browser/glic/glic_user_status_fetcher.h
index 0d7216f..ead3b2e 100644
--- a/chrome/browser/glic/glic_user_status_fetcher.h
+++ b/chrome/browser/glic/glic_user_status_fetcher.h
@@ -69,7 +69,7 @@
   void InvalidateCachedStatus();
   void UpdateUserStatus();
   void UpdateUserStatusIfNeeded();
-  void ScheduleUserStatusUpdate(base::Time next_update_time);
+  void ScheduleUserStatusUpdate(base::TimeDelta time_to_next_update);
   void CancelUserStatusUpdateIfNeeded();
 
   void SetGlicUserStatusUrlForTest(GURL test_url) { endpoint_ = test_url; }
diff --git a/chrome/browser/glic/host/glic.mojom b/chrome/browser/glic/host/glic.mojom
index c945994..f6a3048 100644
--- a/chrome/browser/glic/host/glic.mojom
+++ b/chrome/browser/glic/host/glic.mojom
@@ -395,15 +395,33 @@
   //
   // Actions can only be executed in a tab after act task has been started.  An
   // act task is started by calling this function with a Navigate BrowserAction
-  // on a tab without an active task.
+  // on a tab without an active task. It is an error to act with a paused task.
   // TODO(crbug.com/407860715): Add an explicit method for starting a task.
   ActInFocusedTab(array<uint8> action_proto, GetTabContextOptions options)
       => (ActInFocusedTabResult result);
 
-  // Immediately stops the actor from taking any further actions and exits
-  // acting mode. Any in flight actions are canceled and their callbacks will be
-  // (asynchronously) invoked. No-op if the actor doesn't have an active task.
-  StopActorTask();
+  // Immediately stops the actor from taking any further actions associated with
+  // the given id and exits acting mode. Any in flight actions are canceled and
+  // their callbacks will be (asynchronously) invoked. No-op if a task with the
+  // given id does not exist. An id of 0 refers to the most recent task.
+  StopActorTask(int32 task_id);
+
+  // Pauses the task associated with the given id. Any restrictions on the tab
+  // which would prevent user interaction with it are lifted. ResumeActorTask
+  // restores these restrictions, and allows for further actions. Any in flight
+  // actions are canceled and their callbacks will be (asynchronously) invoked.
+  // No-op if a task with the given id does not exist. An id of 0 refers to the
+  // most recent task.
+  PauseActorTask(int32 task_id);
+
+  // Resumes a paused task associated with the given id, allowing for further
+  // actions. Any restrictions on the tab lifted by PauseActorTask are
+  // reimposed. After resumption, computes the context of the tab associated
+  // with the task according to the given `context_options` and returns the
+  // result. Returns an error if the task doesn't exist or is not paused. An id
+  // of 0 refers to the most recent task.
+  ResumeActorTask(int32 task_id, GetTabContextOptions context_options)
+      => (GetContextResult result);
 
   // Resize the widget hosting the WebUI to the given size.
   // If `duration` is 0 or less, instantly resize, otherwise run an animation.
diff --git a/chrome/browser/glic/host/glic_actor_controller.cc b/chrome/browser/glic/host/glic_actor_controller.cc
index f4f06be..0111fb9 100644
--- a/chrome/browser/glic/host/glic_actor_controller.cc
+++ b/chrome/browser/glic/host/glic_actor_controller.cc
@@ -43,7 +43,13 @@
 
   base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
       FROM_HERE, base::BindOnce(std::move(callback), std::move(result)));
-  return;
+}
+
+void PostTaskForActionResultCallback(
+    actor::ActorCoordinator::ActionResultCallback callback,
+    actor::mojom::ActionResultPtr result) {
+  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE, base::BindOnce(std::move(callback), std::move(result)));
 }
 
 void OnGetContextFromFocusedTab(
@@ -64,6 +70,12 @@
   std::move(callback).Run(std::move(result));
 }
 
+void MaybeWarnMultiTaskNotImplemented(actor::TaskId task_id) {
+  if (task_id) {
+    NOTIMPLEMENTED() << "Multi-task not implemented.";
+  }
+}
+
 }  // namespace
 
 GlicActorController::GlicActorController(Profile* profile) : profile_(profile) {
@@ -103,17 +115,66 @@
   ActImpl(focused_tab_data, action, options, std::move(callback));
 }
 
-void GlicActorController::StopTask() {
-  if (!GetActorCoordinator()) {
+// TODO(mcnee): Determine if we need additional mechanisms, within the browser,
+// to stop a task.
+void GlicActorController::StopTask(actor::TaskId task_id) {
+  MaybeWarnMultiTaskNotImplemented(task_id);
+  if (!GetActorCoordinator() ||
+      actor_task_->GetState() == actor::ActorTask::State::kFinished) {
     return;
   }
   GetActorCoordinator()->StopTask();
   actor_task_->SetState(actor::ActorTask::State::kFinished);
 }
 
+void GlicActorController::PauseTask(actor::TaskId task_id) {
+  MaybeWarnMultiTaskNotImplemented(task_id);
+  if (!GetActorCoordinator() ||
+      actor_task_->GetState() == actor::ActorTask::State::kFinished) {
+    return;
+  }
+  GetActorCoordinator()->PauseTask();
+  actor_task_->SetState(actor::ActorTask::State::kPausedByClient);
+}
+
+void GlicActorController::ResumeTask(
+    actor::TaskId task_id,
+    const mojom::GetTabContextOptions& context_options,
+    glic::mojom::WebClientHandler::ResumeActorTaskCallback callback) {
+  MaybeWarnMultiTaskNotImplemented(task_id);
+  if (!GetActorCoordinator() ||
+      actor_task_->GetState() == actor::ActorTask::State::kFinished) {
+    std::move(callback).Run(mojom::GetContextResult::NewErrorReason(
+        std::string("task does not exist")));
+    return;
+  }
+
+  if (!actor_task_->IsPaused()) {
+    std::move(callback).Run(mojom::GetContextResult::NewErrorReason(
+        std::string("task is not paused")));
+    return;
+  }
+
+  tabs::TabInterface* tab_of_resumed_task =
+      GetActorCoordinator()->GetTabOfCurrentTask();
+  if (!tab_of_resumed_task) {
+    std::move(callback).Run(mojom::GetContextResult::NewErrorReason(
+        std::string("tab does not exist")));
+    return;
+  }
+
+  actor_task_->SetState(actor::ActorTask::State::kReflecting);
+  // TODO(mcnee): Refactor to make it clear we're specifying the tab to get the
+  // context for, not glic's concept of a focused tab.
+  GetContextFromFocusedTab(
+      FocusedTabData{tab_of_resumed_task->GetContents()->GetWeakPtr()},
+      context_options, std::move(callback));
+}
+
 bool GlicActorController::IsActorCoordinatorActingOnTab(
     const content::WebContents* tab) const {
-  return GetActorCoordinator() && GetActorCoordinator()->HasTaskForTab(tab);
+  return GetActorCoordinator() && GetActorCoordinator()->HasTaskForTab(tab) &&
+         actor_task_->GetState() != actor::ActorTask::State::kFinished;
 }
 
 actor::ActorCoordinator& GlicActorController::GetActorCoordinatorForTesting() {
@@ -148,10 +209,20 @@
     const optimization_guide::proto::BrowserAction& action,
     const mojom::GetTabContextOptions& options,
     mojom::WebClientHandler::ActInFocusedTabCallback callback) const {
-  GetActorCoordinator()->Act(
-      action,
+  actor::ActorCoordinator::ActionResultCallback action_callback =
       base::BindOnce(&GlicActorController::OnActionFinished, GetWeakPtr(),
-                     focused_tab_data, options, std::move(callback)));
+                     focused_tab_data, options, std::move(callback));
+
+  if (actor_task_->IsPaused()) {
+    VLOG(1) << "Unable to perform action: task is paused";
+    PostTaskForActionResultCallback(
+        std::move(action_callback),
+        actor::MakeResult(actor::mojom::ActionResultCode::kError,
+                          "Task is paused"));
+    return;
+  }
+
+  GetActorCoordinator()->Act(action, std::move(action_callback));
 }
 
 void GlicActorController::OnActionFinished(
diff --git a/chrome/browser/glic/host/glic_actor_controller.h b/chrome/browser/glic/host/glic_actor_controller.h
index 6d9e2506..dd8c200 100644
--- a/chrome/browser/glic/host/glic_actor_controller.h
+++ b/chrome/browser/glic/host/glic_actor_controller.h
@@ -7,6 +7,7 @@
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/weak_ptr.h"
+#include "chrome/browser/actor/task_id.h"
 #include "chrome/browser/glic/host/context/glic_tab_data.h"
 #include "chrome/browser/glic/host/glic.mojom.h"
 #include "chrome/browser/profiles/profile.h"
@@ -42,7 +43,12 @@
            const mojom::GetTabContextOptions& options,
            mojom::WebClientHandler::ActInFocusedTabCallback callback);
 
-  void StopTask();
+  void StopTask(actor::TaskId task_id);
+  void PauseTask(actor::TaskId task_id);
+  void ResumeTask(
+      actor::TaskId task_id,
+      const mojom::GetTabContextOptions& context_options,
+      glic::mojom::WebClientHandler::ResumeActorTaskCallback callback);
 
   bool IsActorCoordinatorActingOnTab(const content::WebContents* tab) const;
 
diff --git a/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc b/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
index 258eb02..a2dfdec 100644
--- a/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
+++ b/chrome/browser/glic/host/glic_actor_controller_interactive_uitest.cc
@@ -160,15 +160,75 @@
                  WaitForWebContentsReady(new_tab_id, task_url));
   }
 
-  // Stops a running task by calling the glic StopActingTask API.
+  // After invoking APIs that don't return promises, we round trip to both the
+  // client and host to make sure the call has made it to the browser.
+  auto RoundTrip() {
+    return Steps(InAnyContext(WithElement(
+                     kGlicContentsElementId,
+                     [](ui::TrackedElement* el) {
+                       content::WebContents* glic_contents =
+                           AsInstrumentedWebContents(el)->web_contents();
+                       ASSERT_TRUE(content::ExecJs(glic_contents, "true;"));
+                     })),
+                 InAnyContext(WithElement(
+                     kGlicHostElementId, [](ui::TrackedElement* el) {
+                       content::WebContents* webui_contents =
+                           AsInstrumentedWebContents(el)->web_contents();
+                       ASSERT_TRUE(content::ExecJs(webui_contents, "true;"));
+                     })));
+  }
+
+  // Stops a running task by calling the glic StopActorTask API.
   auto StopActorTask() {
-    return Steps(InAnyContext(
-        WithElement(kGlicContentsElementId, [](ui::TrackedElement* el) {
+    return Steps(InAnyContext(WithElement(
+                     kGlicContentsElementId,
+                     [](ui::TrackedElement* el) {
+                       content::WebContents* glic_contents =
+                           AsInstrumentedWebContents(el)->web_contents();
+                       constexpr std::string_view script =
+                           "client.browser.stopActorTask(0);";
+                       ASSERT_TRUE(content::ExecJs(glic_contents, script));
+                     })),
+                 RoundTrip());
+  }
+
+  // Pauses a running task by calling the glic PauseActorTask API.
+  auto PauseActorTask() {
+    return Steps(InAnyContext(WithElement(
+                     kGlicContentsElementId,
+                     [](ui::TrackedElement* el) {
+                       content::WebContents* glic_contents =
+                           AsInstrumentedWebContents(el)->web_contents();
+                       constexpr std::string_view script =
+                           "client.browser.pauseActorTask(0);";
+                       ASSERT_TRUE(content::ExecJs(glic_contents, script));
+                     })),
+                 RoundTrip());
+  }
+
+  // Resumes a paused task by calling the glic ResumeActorTask API.
+  auto ResumeActorTask(base::Value::Dict context_options, bool expected) {
+    return Steps(InAnyContext(CheckElement(
+        kGlicContentsElementId,
+        [context_options =
+             std::move(context_options)](ui::TrackedElement* el) mutable {
           content::WebContents* glic_contents =
               AsInstrumentedWebContents(el)->web_contents();
-          std::string script = "client.browser.stopActorTask();";
-          ASSERT_TRUE(content::ExecJs(glic_contents, std::move(script)));
-        })));
+          std::string script = content::JsReplace(
+              R"js(
+                              (async () => {
+                                try {
+                                  await client.browser.resumeActorTask(0, $1);
+                                  return true;
+                                } catch (err) {
+                                  return false;
+                                }
+                              })();
+                            )js",
+              std::move(context_options));
+          return content::EvalJs(glic_contents, script).ExtractBool();
+        },
+        expected)));
   }
 
   // Returns a callback that builds an encoded proto for a click action on a
@@ -276,6 +336,20 @@
     }));
   }
 
+  auto CheckHasTaskForTab(ui::ElementIdentifier tab, bool expected) {
+    return Steps(InAnyContext(CheckElement(
+        tab,
+        [](ui::TrackedElement* el) {
+          content::WebContents* tab_contents =
+              AsInstrumentedWebContents(el)->web_contents();
+          const auto* glic_service =
+              GlicKeyedService::Get(tab_contents->GetBrowserContext());
+          return glic_service &&
+                 glic_service->IsActorCoordinatorActingOnTab(tab_contents);
+        },
+        expected)));
+  }
+
  private:
   int32_t SearchAnnotatedPageContent(std::string_view label) {
     CHECK(annotated_page_content_)
@@ -409,13 +483,15 @@
       GetPageContextFromFocusedTab(),
       ExecuteAction(ClickActionProvider(kClickableButtonLabel),
                     UpdatedContextOptions()),
-      WaitForJsResult(kNewActorTabId, "() => button_clicked"), StopActorTask(),
+      WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+      CheckHasTaskForTab(kNewActorTabId, true), StopActorTask(),
       // TODO(crbug.com/409558980): Expect kTargetNotFound since that's
       // currently the error returned anytime a tool fails but in the future we
       // should add an error code for "NoActiveTask".
       ExecuteAction(ClickActionProvider(kClickableButtonLabel),
                     UpdatedContextOptions(),
-                    glic::mojom::ActInFocusedTabErrorReason::kTargetNotFound));
+                    glic::mojom::ActInFocusedTabErrorReason::kTargetNotFound),
+      CheckHasTaskForTab(kNewActorTabId, false));
 }
 
 // Ensure that a task can be started after a previous task was stopped.
@@ -448,6 +524,115 @@
       WaitForJsResult(kThirdTabId, "() => button_clicked"), StopActorTask());
 }
 
+// Ensure that a task can be paused and that further actions fail.
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest, PauseActorTask) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  constexpr std::string_view kClickableButtonLabel = "clickable";
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(
+      InitializeWithOpenGlicWindow(),
+      StartActorTaskInNewTab(task_url, kNewActorTabId),
+      GetPageContextFromFocusedTab(),
+      ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                    UpdatedContextOptions()),
+      WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+      CheckHasTaskForTab(kNewActorTabId, true), PauseActorTask(),
+      // TODO(crbug.com/409558980): Expect kTargetNotFound since that's
+      // currently the error returned anytime a tool fails but in the future we
+      // should add an error code for "NoActiveTask".
+      ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                    UpdatedContextOptions(),
+                    glic::mojom::ActInFocusedTabErrorReason::kTargetNotFound),
+      // Unlike stopping, pausing keeps the task.
+      CheckHasTaskForTab(kNewActorTabId, true));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest, PauseThenStopActorTask) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  constexpr std::string_view kClickableButtonLabel = "clickable";
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(InitializeWithOpenGlicWindow(),
+                  StartActorTaskInNewTab(task_url, kNewActorTabId),
+                  GetPageContextFromFocusedTab(),
+                  ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                                UpdatedContextOptions()),
+                  WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+                  PauseActorTask(), CheckHasTaskForTab(kNewActorTabId, true),
+                  StopActorTask(), CheckHasTaskForTab(kNewActorTabId, false));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest, PauseAlreadyPausedActorTask) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  constexpr std::string_view kClickableButtonLabel = "clickable";
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(InitializeWithOpenGlicWindow(),
+                  StartActorTaskInNewTab(task_url, kNewActorTabId),
+                  GetPageContextFromFocusedTab(),
+                  ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                                UpdatedContextOptions()),
+                  WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+                  PauseActorTask(), PauseActorTask(),
+                  CheckHasTaskForTab(kNewActorTabId, true));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest, PauseThenResumeActorTask) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  constexpr std::string_view kClickableButtonLabel = "clickable";
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(
+      InitializeWithOpenGlicWindow(),
+      StartActorTaskInNewTab(task_url, kNewActorTabId),
+      GetPageContextFromFocusedTab(),
+      ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                    UpdatedContextOptions()),
+      WaitForJsResult(kNewActorTabId, "() => button_clicked"),
+      ExecuteJs(kNewActorTabId, "() => { button_clicked = false; }"),
+      PauseActorTask(), ResumeActorTask(UpdatedContextOptions(), true),
+      CheckHasTaskForTab(kNewActorTabId, true),
+      ExecuteAction(ClickActionProvider(kClickableButtonLabel),
+                    UpdatedContextOptions()),
+      WaitForJsResult(kNewActorTabId, "() => button_clicked"));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest, ResumeActorTaskWithoutATask) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(InitializeWithOpenGlicWindow(),
+                  StartActorTaskInNewTab(task_url, kNewActorTabId),
+                  StopActorTask(), CheckHasTaskForTab(kNewActorTabId, false),
+                  // Once a task is stopped, it can't be resumed.
+                  ResumeActorTask(UpdatedContextOptions(), false));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorControllerUiTest,
+                       ResumeActorTaskWhenAlreadyResumed) {
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  RunTestSequence(InitializeWithOpenGlicWindow(),
+                  StartActorTaskInNewTab(task_url, kNewActorTabId),
+                  PauseActorTask(),
+                  ResumeActorTask(UpdatedContextOptions(), true),
+                  ResumeActorTask(UpdatedContextOptions(), false));
+}
+
 class GlicActorControllerWithActorDisabledUiTest
     : public test::InteractiveGlicTest {
  public:
diff --git a/chrome/browser/glic/host/glic_page_handler.cc b/chrome/browser/glic/host/glic_page_handler.cc
index 8e2c31e..812e524 100644
--- a/chrome/browser/glic/host/glic_page_handler.cc
+++ b/chrome/browser/glic/host/glic_page_handler.cc
@@ -17,6 +17,7 @@
 #include "base/time/time.h"
 #include "base/timer/timer.h"
 #include "base/version_info/version_info.h"
+#include "chrome/browser/actor/task_id.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/contextual_cueing/contextual_cueing_features.h"
 #include "chrome/browser/enterprise/browser_management/management_service_factory.h"
@@ -469,13 +470,34 @@
     glic_service_->ActInFocusedTab(action_proto, *options, std::move(callback));
   }
 
-  void StopActorTask() override {
+  void StopActorTask(int32_t task_id) override {
     if (!base::FeatureList::IsEnabled(features::kGlicActor)) {
       receiver_.ReportBadMessage(
           "StopActorTask cannot be called without GlicActor enabled.");
       return;
     }
-    glic_service_->StopActorTask();
+    glic_service_->StopActorTask(actor::TaskId(task_id));
+  }
+
+  void PauseActorTask(int32_t task_id) override {
+    if (!base::FeatureList::IsEnabled(features::kGlicActor)) {
+      receiver_.ReportBadMessage(
+          "PauseActorTask cannot be called without GlicActor enabled.");
+      return;
+    }
+    glic_service_->PauseActorTask(actor::TaskId(task_id));
+  }
+
+  void ResumeActorTask(int32_t task_id,
+                       glic::mojom::GetTabContextOptionsPtr context_options,
+                       ResumeActorTaskCallback callback) override {
+    if (!base::FeatureList::IsEnabled(features::kGlicActor)) {
+      receiver_.ReportBadMessage(
+          "ResumeActorTask cannot be called without GlicActor enabled.");
+      return;
+    }
+    glic_service_->ResumeActorTask(actor::TaskId(task_id), *context_options,
+                                   std::move(callback));
   }
 
   void CaptureScreenshot(CaptureScreenshotCallback callback) override {
diff --git a/chrome/browser/profiles/BUILD.gn b/chrome/browser/profiles/BUILD.gn
index 7b8ab5eb..2c049b7 100644
--- a/chrome/browser/profiles/BUILD.gn
+++ b/chrome/browser/profiles/BUILD.gn
@@ -299,6 +299,7 @@
     deps += [
       "//chrome/browser/commerce/merchant_viewer:merchant_viewer_data_manager",
       "//chrome/browser/fast_checkout",
+      "//chrome/browser/password_manager/android/one_time_passwords:backend",
       "//components/commerce/core:merchant_signal_db_proto",
       "//components/payments/content/browser_binding:browser_bound_keys_deleter_factory",
     ]
diff --git a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
index 613f200..85af536 100644
--- a/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
+++ b/chrome/browser/profiles/chrome_browser_main_extra_parts_profiles.cc
@@ -292,6 +292,7 @@
 #include "chrome/browser/fast_checkout/fast_checkout_capabilities_fetcher_factory.h"
 #include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "chrome/browser/media/android/cdm/media_drm_origin_id_manager_factory.h"
+#include "chrome/browser/password_manager/android/one_time_passwords/android_sms_otp_backend_factory.h"
 #include "chrome/browser/privacy_sandbox/privacy_sandbox_activity_types_factory.h"
 #include "chrome/browser/search_resumption/start_suggest_service_factory.h"
 #include "chrome/browser/signin/signin_manager_android_factory.h"
@@ -666,6 +667,9 @@
 #endif
   AffiliationServiceFactory::GetInstance();
   AiDataKeyedServiceFactory::GetInstance();
+#if BUILDFLAG(IS_ANDROID)
+  AndroidSmsOtpBackendFactory::GetInstance();
+#endif
   AnnouncementNotificationServiceFactory::GetInstance();
 #if BUILDFLAG(IS_CHROMEOS)
   app_list::AppListSyncableServiceFactory::GetInstance();
diff --git a/chrome/browser/resources/glic/glic_api/glic_api.ts b/chrome/browser/resources/glic/glic_api/glic_api.ts
index 903c06e..2a0eac8e 100644
--- a/chrome/browser/resources/glic/glic_api/glic_api.ts
+++ b/chrome/browser/resources/glic/glic_api/glic_api.ts
@@ -183,15 +183,56 @@
    * Inform Chrome about an action. Chrome Takes an action based on the
    * action proto and returns new context based on the tab context options.
    *
+   * Attempts to act while the associated task is stopped/paused will be
+   * rejected.
+   *
    * @throws {ActInFocusedTabError} on failure.
    */
   actInFocusedTab?
       (params: ActInFocusedTabParams): Promise<ActInFocusedTabResult>;
 
   /**
-   * Stops an actor task in the browser if one exists. No-op otherwise.
+   * Stops the actor task with the given ID in the browser if it exists. No-op
+   * otherwise.
+   *
+   * Stopping a task removes all actor related restrictions from the associated
+   * tab. Any in progress actions are canceled and the associated Promises are
+   * rejected.
+   *
+   * If the task ID is not provided or 0, the most recent task is stopped.
+   *
+   * @todo Require callers to provide a valid ID.
    */
-  stopActorTask?(): void;
+  stopActorTask?(taskId?: number): void;
+
+  /**
+   * Pauses the actor task with the given ID in the browser if it exists. No-op
+   * otherwise.
+   *
+   * Pausing a task removes actor related restrictions that prevent the user
+   * from interacting with the associated tab. Any in progress actions are
+   * canceled and the associated Promises are rejected.
+   *
+   * If the task ID is 0, the most recent task is paused.
+   *
+   * @todo Require callers to provide a valid ID.
+   */
+  pauseActorTask?(taskId: number): void;
+
+  /**
+   * Resumes a previously paused actor task with the given ID.
+   *
+   * Returns the tab context at the time of resumption, based on the provided
+   * context options.
+   *
+   * If the task ID is 0, the most recent task is resumed.
+   *
+   * @throws {Error} on failure.
+   *
+   * @todo Require callers to provide a valid ID.
+   */
+  resumeActorTask?(taskId: number, tabContextOptions: TabContextOptions):
+      Promise<TabContextResult>;
 
   /**
    * Requests the host to capture a screenshot. The choice of the screenshot
diff --git a/chrome/browser/resources/glic/glic_api_impl/glic_api_client.ts b/chrome/browser/resources/glic/glic_api_impl/glic_api_client.ts
index 69b4c0f..38b1c29 100644
--- a/chrome/browser/resources/glic/glic_api_impl/glic_api_client.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/glic_api_client.ts
@@ -240,6 +240,8 @@
     if (!state.enableActInFocusedTab) {
       this.actInFocusedTab = undefined;
       this.stopActorTask = undefined;
+      this.pauseActorTask = undefined;
+      this.resumeActorTask = undefined;
     }
 
     if (state.alwaysDetachedMode) {
@@ -345,8 +347,20 @@
         context.actInFocusedTabResult);
   }
 
-  stopActorTask?(): void {
-    this.sender.requestNoResponse('glicBrowserStopActorTask', undefined);
+  stopActorTask?(taskId?: number): void {
+    this.sender.requestNoResponse(
+        'glicBrowserStopActorTask', {taskId: taskId ?? 0});
+  }
+
+  pauseActorTask?(taskId: number): void {
+    this.sender.requestNoResponse('glicBrowserPauseActorTask', {taskId});
+  }
+
+  async resumeActorTask?(taskId: number, tabContextOptions: TabContextOptions):
+      Promise<TabContextResult> {
+    const response = await this.sender.requestWithResponse(
+        'glicBrowserResumeActorTask', {taskId, tabContextOptions});
+    return convertTabContextResultFromPrivate(response.tabContextResult);
   }
 
   async resizeWindow(
diff --git a/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts b/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts
index 9fdaa36..2a3f211c 100644
--- a/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/glic_api_host.ts
@@ -363,8 +363,28 @@
     };
   }
 
-  glicBrowserStopActorTask(): void {
-    this.handler.stopActorTask();
+  glicBrowserStopActorTask(request: {taskId: number}): void {
+    this.handler.stopActorTask(request.taskId);
+  }
+
+  glicBrowserPauseActorTask(request: {taskId: number}): void {
+    this.handler.pauseActorTask(request.taskId);
+  }
+
+  async glicBrowserResumeActorTask(
+      request: {taskId: number, tabContextOptions: TabContextOptions},
+      extras: ResponseExtras):
+      Promise<{tabContextResult: TabContextResultPrivate}> {
+    const {result: {errorReason, tabContext}} =
+        await this.handler.resumeActorTask(
+            request.taskId,
+            tabContextOptionsFromClient(request.tabContextOptions));
+    if (!tabContext) {
+      throw new Error(`resumeActorTask failed: ${errorReason}`);
+    }
+    return {
+      tabContextResult: tabContextToClient(tabContext, extras),
+    };
   }
 
   async glicBrowserResizeWindow(request: {
diff --git a/chrome/browser/resources/glic/glic_api_impl/request_types.ts b/chrome/browser/resources/glic/glic_api_impl/request_types.ts
index ad9e336..b476bfa 100644
--- a/chrome/browser/resources/glic/glic_api_impl/request_types.ts
+++ b/chrome/browser/resources/glic/glic_api_impl/request_types.ts
@@ -79,7 +79,25 @@
       actInFocusedTabResult: ActInFocusedTabResultPrivate,
     },
   };
-  glicBrowserStopActorTask: {};
+  glicBrowserStopActorTask: {
+    request: {
+      taskId: number,
+    },
+  };
+  glicBrowserPauseActorTask: {
+    request: {
+      taskId: number,
+    },
+  };
+  glicBrowserResumeActorTask: {
+    request: {
+      taskId: number,
+      tabContextOptions: TabContextOptions,
+    },
+    response: {
+      tabContextResult: TabContextResultPrivate,
+    },
+  };
   glicBrowserCaptureScreenshot: {
     response: {
       screenshot: Screenshot,
@@ -292,6 +310,8 @@
     GetContextFromFocusedTab: 0,
     ActInFocusedTab: 0,
     StopActorTask: 0,
+    PauseActorTask: 0,
+    ResumeActorTask: 0,
     CaptureScreenshot: 0,
     ResizeWindow: 0,
     EnableDragResize: 0,
diff --git a/chrome/browser/subresource_filter/subresource_filter_history_observer.cc b/chrome/browser/subresource_filter/subresource_filter_history_observer.cc
index 2ab87e1..9b9625a 100644
--- a/chrome/browser/subresource_filter/subresource_filter_history_observer.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_history_observer.cc
@@ -5,7 +5,6 @@
 #include "chrome/browser/subresource_filter/subresource_filter_history_observer.h"
 
 #include "base/check.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
 #include "url/gurl.h"
 
@@ -14,8 +13,8 @@
         settings_manager,
     history::HistoryService* history_service)
     : settings_manager_(settings_manager) {
-  CHECK(settings_manager_, base::NotFatalUntil::M129);
-  CHECK(history_service, base::NotFatalUntil::M129);
+  CHECK(settings_manager_);
+  CHECK(history_service);
   history_observation_.Observe(history_service);
 }
 
diff --git a/chrome/browser/ui/browser_window/browser_window_features.cc b/chrome/browser/ui/browser_window/browser_window_features.cc
index 4dce6d3..57e4a41 100644
--- a/chrome/browser/ui/browser_window/browser_window_features.cc
+++ b/chrome/browser/ui/browser_window/browser_window_features.cc
@@ -248,6 +248,19 @@
             std::make_unique<extensions::Mv2DisabledDialogController>(browser);
       }
     }
+
+    if (features::HasTabSearchToolbarButton()) {
+      // TODO(crbug.com/360163254): We should really be using
+      // Browser::GetBrowserView, which always returns a non-null BrowserView
+      // in production, but this crashes during unittests using
+      // BrowserWithTestWindowTest; these should eventually be refactored.
+      if (BrowserView* browser_view =
+              BrowserView::GetBrowserViewForBrowser(browser)) {
+        tab_search_toolbar_button_controller_ =
+            std::make_unique<TabSearchToolbarButtonController>(
+                browser_view, browser_view->GetTabSearchBubbleHost());
+      }
+    }
   }
 
   if (browser->is_type_normal() || browser->is_type_app()) {
@@ -306,11 +319,6 @@
           std::make_unique<media_router::CastBrowserController>(
               browser_view->browser());
     }
-
-    if (features::HasTabSearchToolbarButton()) {
-      tab_search_toolbar_button_controller_ =
-          std::make_unique<TabSearchToolbarButtonController>(browser_view);
-    }
   }
 
   if (download::IsDownloadBubbleEnabled()) {
diff --git a/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc b/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
index 7e60460..29bd876 100644
--- a/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
+++ b/chrome/browser/ui/commerce/commerce_ui_tab_helper.cc
@@ -259,7 +259,10 @@
 
     tab_interface->GetTabFeatures()
         ->commerce_price_insights_page_action_view_controller()
-        ->UpdatePageActionIcon();
+        ->UpdatePageActionIcon(
+            ShouldShowPriceInsightsIconView(),
+            ShouldExpandPageActionIcon(PageActionIconType::kPriceInsights),
+            GetPriceInsightsIconLabelTypeForPage());
     return;
   }
 
diff --git a/chrome/browser/ui/plus_addresses/BUILD.gn b/chrome/browser/ui/plus_addresses/BUILD.gn
index a53f242..06292ad 100644
--- a/chrome/browser/ui/plus_addresses/BUILD.gn
+++ b/chrome/browser/ui/plus_addresses/BUILD.gn
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/chrome_build.gni")
 import("//build/config/ui.gni")
 
 assert(toolkit_views || is_android)
diff --git a/chrome/browser/ui/tabs/tab_group_model.cc b/chrome/browser/ui/tabs/tab_group_model.cc
index 238e4076..7206aa7 100644
--- a/chrome/browser/ui/tabs/tab_group_model.cc
+++ b/chrome/browser/ui/tabs/tab_group_model.cc
@@ -35,7 +35,7 @@
 }
 
 TabGroup* TabGroupModel::GetTabGroup(const tab_groups::TabGroupId& id) const {
-  CHECK(ContainsTabGroup(id), base::NotFatalUntil::M127);
+  CHECK(ContainsTabGroup(id));
   return groups_.find(id)->second.get();
 }
 
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc
index db4d689..bed2c0f 100644
--- a/chrome/browser/ui/tabs/tab_strip_model.cc
+++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -3099,8 +3099,7 @@
     int add_types,
     std::optional<tab_groups::TabGroupId> group) {
   if (group_model_ && group.has_value()) {
-    CHECK(group_model_->ContainsTabGroup(group.value()),
-          base::NotFatalUntil::M129);
+    CHECK(group_model_->ContainsTabGroup(group.value()));
   }
 
   delegate()->WillAddWebContents(tab->GetContents());
@@ -4460,8 +4459,8 @@
 std::optional<tab_groups::TabGroupId> TabStripModel::GetGroupToAssign(
     int index,
     int to_position) {
-  CHECK(ContainsIndex(index), base::NotFatalUntil::M129);
-  CHECK(ContainsIndex(to_position), base::NotFatalUntil::M129);
+  CHECK(ContainsIndex(index));
+  CHECK(ContainsIndex(to_position));
 
   tabs::TabInterface* tab_to_move = GetTabAtIndex(index);
 
diff --git a/chrome/browser/ui/toasts/BUILD.gn b/chrome/browser/ui/toasts/BUILD.gn
index ede7d8f..f10d2c1 100644
--- a/chrome/browser/ui/toasts/BUILD.gn
+++ b/chrome/browser/ui/toasts/BUILD.gn
@@ -4,6 +4,7 @@
 
 assert(is_win || is_mac || is_linux || is_chromeos)
 
+import("//build/config/chrome_build.gni")
 import("//build/config/ui.gni")
 
 source_set("toasts") {
diff --git a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
index b6fa197..648d49d 100644
--- a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
+++ b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.cc
@@ -13,16 +13,16 @@
 #include "chrome/common/chrome_features.h"
 
 TabSearchToolbarButtonController::TabSearchToolbarButtonController(
-    BrowserView* browser_view)
-    : browser_view_(browser_view) {}
+    BrowserView* browser_view,
+    TabSearchBubbleHost* tab_search_bubble_host)
+    : browser_view_(browser_view) {
+  tab_search_bubble_host_observation_.Observe(tab_search_bubble_host);
+}
 
 TabSearchToolbarButtonController::~TabSearchToolbarButtonController() = default;
 
 void TabSearchToolbarButtonController::OnBubbleInitializing() {
-  bubble_showing_ = true;
-  auto* tab_search_action_item = actions::ActionManager::Get().FindAction(
-      kActionTabSearch,
-      browser_view_->browser()->browser_actions()->root_action_item());
+  actions::ActionItem* tab_search_action_item = GetTabSearchActionItem();
   tab_search_action_item->SetIsShowingBubble(true);
   PinnedToolbarActionsContainer* pinned_toolbar_actions_container =
       browser_view_->toolbar()->pinned_toolbar_actions_container();
@@ -36,10 +36,7 @@
 }
 
 void TabSearchToolbarButtonController::OnBubbleDestroying() {
-  bubble_showing_ = false;
-  auto* tab_search_action_item = actions::ActionManager::Get().FindAction(
-      kActionTabSearch,
-      browser_view_->browser()->browser_actions()->root_action_item());
+  actions::ActionItem* tab_search_action_item = GetTabSearchActionItem();
   tab_search_action_item->SetIsShowingBubble(false);
   PinnedToolbarActionsContainer* pinned_toolbar_actions_container =
       browser_view_->toolbar()->pinned_toolbar_actions_container();
@@ -74,7 +71,7 @@
   PinnedToolbarActionsContainer* pinned_toolbar_actions_container =
       browser_view_->toolbar()->pinned_toolbar_actions_container();
 
-  if (bubble_showing_ ||
+  if (GetTabSearchActionItem()->GetIsShowingBubble() ||
       pinned_toolbar_actions_container->IsActionPinned(kActionTabSearch)) {
     return;
   }
@@ -82,3 +79,10 @@
   pinned_toolbar_actions_container->ShowActionEphemerallyInToolbar(
       kActionTabSearch, false);
 }
+
+actions::ActionItem*
+TabSearchToolbarButtonController::GetTabSearchActionItem() {
+  return actions::ActionManager::Get().FindAction(
+      kActionTabSearch,
+      browser_view_->browser()->browser_actions()->root_action_item());
+}
diff --git a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.h b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.h
index 9f364030..0f4d1d4 100644
--- a/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.h
+++ b/chrome/browser/ui/toolbar/pinned_toolbar/tab_search_toolbar_button_controller.h
@@ -7,13 +7,19 @@
 
 #include "base/memory/raw_ptr.h"
 #include "base/memory/weak_ptr.h"
+#include "base/scoped_observation.h"
 #include "chrome/browser/ui/views/tab_search_bubble_host.h"
 
+namespace actions {
+class ActionItem;
+}  // namespace actions
+
 class BrowserView;
 
 class TabSearchToolbarButtonController : public TabSearchBubbleHost::Observer {
  public:
-  explicit TabSearchToolbarButtonController(BrowserView* browser_view);
+  TabSearchToolbarButtonController(BrowserView* browser_view,
+                                   TabSearchBubbleHost* tab_search_bubble_host);
   ~TabSearchToolbarButtonController() override;
 
   TabSearchToolbarButtonController(const TabSearchToolbarButtonController&) =
@@ -30,8 +36,17 @@
  private:
   void MaybeHideActionEphemerallyInToolbar();
 
-  raw_ptr<BrowserView> browser_view_;
-  bool bubble_showing_ = false;
+  // Gets the TabSearch ActionItem from the hosting browser.
+  actions::ActionItem* GetTabSearchActionItem();
+
+  // BrowserView hosting the Tab Search toolbar button, outlives this.
+  // TODO(crbug.com/417823694): Pass only the specific BrowserView dependencies
+  // into the controller.
+  const raw_ptr<BrowserView> browser_view_;
+
+  base::ScopedObservation<TabSearchBubbleHost, TabSearchBubbleHost::Observer>
+      tab_search_bubble_host_observation_{this};
+
   base::WeakPtrFactory<TabSearchToolbarButtonController> weak_ptr_factory_{
       this};
 };
diff --git a/chrome/browser/ui/user_education/recent_session_observer_impl.h b/chrome/browser/ui/user_education/recent_session_observer_impl.h
index 6bb23634..688c200 100644
--- a/chrome/browser/ui/user_education/recent_session_observer_impl.h
+++ b/chrome/browser/ui/user_education/recent_session_observer_impl.h
@@ -31,7 +31,7 @@
   void Init(RecentSessionTracker& tracker) override;
 
  private:
-  friend class RecentSessionObserverImplTest;
+  friend class RecentSessionObserverImplBrowserTest;
 
   void OnRecentSessionsUpdated(const RecentSessionData& recent_sessions);
 
diff --git a/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.cc b/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.cc
index f7c3276..bd6555f 100644
--- a/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.cc
+++ b/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.cc
@@ -8,7 +8,6 @@
 #include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/commerce/commerce_ui_tab_helper.h"
 #include "chrome/browser/ui/tabs/public/tab_features.h"
-#include "chrome/browser/ui/views/commerce/price_insights_icon_view.h"
 #include "chrome/browser/ui/views/page_action/page_action_controller.h"
 #include "components/strings/grit/components_strings.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -24,15 +23,15 @@
 PriceInsightsPageActionViewController::
     ~PriceInsightsPageActionViewController() = default;
 
-void PriceInsightsPageActionViewController::UpdatePageActionIcon() {
-  auto* tab_helper = tab_interface_->GetTabFeatures()->commerce_ui_tab_helper();
-  CHECK(tab_helper);
-
+void PriceInsightsPageActionViewController::UpdatePageActionIcon(
+    bool should_shown_icon,
+    bool should_expand_icon,
+    PriceInsightsIconLabelType label_type) {
   page_actions::PageActionController* page_action_controller =
       tab_interface_->GetTabFeatures()->page_action_controller();
   CHECK(page_action_controller);
 
-  if (!tab_helper->ShouldShowPriceInsightsIconView()) {
+  if (!should_shown_icon) {
     // Suggestion chip may be previously shown, ensure that the state is
     // cleared.
     page_action_controller->HideSuggestionChip(kActionCommercePriceInsights);
@@ -43,8 +42,7 @@
 
   page_action_controller->Show(kActionCommercePriceInsights);
 
-  if (!tab_helper->ShouldExpandPageActionIcon(
-          PageActionIconType::kPriceInsights)) {
+  if (!should_expand_icon) {
     return;
   }
 
@@ -55,9 +53,6 @@
   scoped_window_call_to_action_ptr_ =
       tab_interface_->GetBrowserWindowInterface()->ShowCallToAction();
 
-  PriceInsightsIconLabelType label_type =
-      tab_helper->GetPriceInsightsIconLabelTypeForPage();
-
   switch (label_type) {
     case PriceInsightsIconLabelType::kPriceIsLow:
       page_action_controller->OverrideText(
diff --git a/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h b/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h
index 0314bc1..fa440d1 100644
--- a/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h
+++ b/chrome/browser/ui/views/commerce/price_insights_page_action_view_controller.h
@@ -5,7 +5,10 @@
 #ifndef CHROME_BROWSER_UI_VIEWS_COMMERCE_PRICE_INSIGHTS_PAGE_ACTION_VIEW_CONTROLLER_H_
 #define CHROME_BROWSER_UI_VIEWS_COMMERCE_PRICE_INSIGHTS_PAGE_ACTION_VIEW_CONTROLLER_H_
 
+#include <memory>
+
 #include "base/memory/raw_ref.h"
+#include "chrome/browser/ui/views/commerce/price_insights_icon_view.h"
 
 class ScopedWindowCallToAction;
 
@@ -34,7 +37,9 @@
   // If the icon should be shown, it may also display an expanded label or a
   // suggestion chip depending on the context provided by the commerce UI tab
   // helper.
-  void UpdatePageActionIcon();
+  void UpdatePageActionIcon(bool should_shown_icon,
+                            bool should_expand_icon,
+                            PriceInsightsIconLabelType label_type);
 
  private:
   // Reference to the tab interface, which provides access to tab-specific
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 89c1620..16ec3a1 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -1202,13 +1202,6 @@
   // other cleanups that destroy views referenced in the layout manager.
   SetLayoutManager(nullptr);
 
-  auto* tab_search_toolbar_button_controller =
-      browser_->GetFeatures().tab_search_toolbar_button_controller();
-  if (tab_search_toolbar_button_controller) {
-    tab_search_bubble_host_->RemoveObserver(
-        tab_search_toolbar_button_controller);
-  }
-
   tab_search_bubble_host_.reset();
 
   // Destroy the top controls slide controller first as it depends on the
@@ -5292,8 +5285,6 @@
       tab_search_bubble_host_ = std::make_unique<TabSearchBubbleHost>(
           toolbar_->tab_search_button(), browser_.get(),
           tabstrip_->AsWeakPtr());
-      tab_search_bubble_host_->AddObserver(
-          browser_->GetFeatures().tab_search_toolbar_button_controller());
     } else {
       tab_search_bubble_host_ = std::make_unique<TabSearchBubbleHost>(
           tab_strip_region_view_->GetTabSearchButton(), browser_.get(),
diff --git a/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc b/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
index db261804a..a7542d44 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_flow_controller.cc
@@ -12,7 +12,6 @@
 #include "base/functional/callback_helpers.h"
 #include "base/functional/overloaded.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
 #include "chrome/browser/browser_process.h"
@@ -754,11 +753,11 @@
     // TODO(crbug.com/40942098): Find a way to get the web contents without
     // relying on the weak ptr.
     web_contents = weak_signed_in_flow_controller_->contents();
-    CHECK(web_contents, base::NotFatalUntil::M127);
+    CHECK(web_contents);
   } else {
     // TODO(crbug.com/40942098): Find another way to fetch the web contents.
     web_contents = GetSignedOutFlowWebContents();
-    CHECK(web_contents, base::NotFatalUntil::M127);
+    CHECK(web_contents);
   }
 
   auto search_engine_choice_step_completed = base::BindOnce(
diff --git a/chrome/browser/ui/views/profiles/profile_picker_view.cc b/chrome/browser/ui/views/profiles/profile_picker_view.cc
index f35dda9..c894f2d1 100644
--- a/chrome/browser/ui/views/profiles/profile_picker_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_picker_view.cc
@@ -463,7 +463,7 @@
   if (!profile) {
     NOTREACHED() << "Local fail in creating new profile";
   }
-  CHECK(!signin_util::IsForceSigninEnabled(), base::NotFatalUntil::M127);
+  CHECK(!signin_util::IsForceSigninEnabled());
 
   // Apply a new color to the profile or use the default theme.
   // TODO(b/328587059): Share the theme color logic with the same code in
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
index d4a7ae4..dd9fcb0 100644
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -32,7 +32,6 @@
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
 #include "base/metrics/user_metrics.h"
-#include "base/not_fatal_until.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/observer_list.h"
 #include "base/scoped_observation.h"
@@ -313,9 +312,9 @@
       }
     }
 
-    CHECK(!dragging_views.empty(), base::NotFatalUntil::M128)
+    CHECK(!dragging_views.empty())
         << "Dragging views cannot be empty during drag initialization.";
-    CHECK(base::Contains(dragging_views, source), base::NotFatalUntil::M128)
+    CHECK(base::Contains(dragging_views, source))
         << "Source must be part of dragging views.";
 
     // Delete the existing DragController before creating a new one. We do this
@@ -325,8 +324,7 @@
 
     CHECK((event.type() == ui::EventType::kMousePressed ||
            event.type() == ui::EventType::kGestureTapDown ||
-           event.type() == ui::EventType::kGestureScrollBegin),
-          base::NotFatalUntil::M128)
+           event.type() == ui::EventType::kGestureScrollBegin))
         << "Event type must be suitable for starting a drag.";
 
     drag_controller_ = std::make_unique<TabDragController>();
@@ -421,10 +419,10 @@
 
   void OwnDragController(
       std::unique_ptr<TabDragController> controller) override {
-    CHECK(controller, base::NotFatalUntil::M128)
+    CHECK(controller)
         << "The provided TabDragController is null, which is not expected.";
 
-    CHECK(!drag_controller_, base::NotFatalUntil::M128)
+    CHECK(!drag_controller_)
         << "Attempting to own a new drag controller while one already exists.";
 
     drag_controller_ = std::move(controller);
@@ -540,8 +538,7 @@
 
   std::vector<gfx::Rect> CalculateBoundsForDraggedViews(
       const std::vector<TabSlotView*>& views) override {
-    CHECK(!views.empty(), base::NotFatalUntil::M128)
-        << "The views vector must not be empty.";
+    CHECK(!views.empty()) << "The views vector must not be empty.";
 
     std::vector<gfx::Rect> bounds;
     const int overlap = TabStyle::Get()->GetTabOverlap();
@@ -557,10 +554,10 @@
 
   void SetBoundsForDrag(const std::vector<TabSlotView*>& views,
                         const std::vector<gfx::Rect>& bounds) override {
-    CHECK(!views.empty() || !bounds.empty(), base::NotFatalUntil::M128)
+    CHECK(!views.empty() || !bounds.empty())
         << "Views and bounds cannot both be empty.";
     tab_strip_->tab_container_->CancelAnimation();
-    CHECK_EQ(views.size(), bounds.size(), base::NotFatalUntil::M128)
+    CHECK_EQ(views.size(), bounds.size())
         << "The sizes of views and bounds must match.";
     for (size_t i = 0; i < views.size(); ++i) {
       views[i]->SetBoundsRect(bounds[i]);
@@ -594,12 +591,12 @@
 
     // No tabs should be dragging at this point.
     for (int i = 0; i < GetTabCount(); ++i) {
-      CHECK(!GetTabAt(i)->dragging(), base::NotFatalUntil::M128)
+      CHECK(!GetTabAt(i)->dragging())
           << "A tab is still marked as dragging when starting a new drag.";
     }
 
     for (TabSlotView* dragged_view : views) {
-      CHECK_NE(dragged_view->parent(), this, base::NotFatalUntil::M128);
+      CHECK_NE(dragged_view->parent(), this);
       AddChildViewRaw(dragged_view);
       dragged_view->set_dragging(true);
       if (TabGroupHeader* header =
@@ -667,7 +664,7 @@
                             const gfx::Point& location,
                             bool initial_drag) override {
     std::vector<gfx::Rect> bounds = CalculateBoundsForDraggedViews(views);
-    CHECK_EQ(views.size(), bounds.size(), base::NotFatalUntil::M128)
+    CHECK_EQ(views.size(), bounds.size())
         << "The sizes of views and bounds must match in LayoutDraggedViewsAt.";
 
     // The index of `source_view` in the TabStrip's viewmodel.
@@ -1166,7 +1163,7 @@
 void TabStrip::MoveTab(int from_model_index,
                        int to_model_index,
                        TabRendererData data) {
-  CHECK_GT(GetTabCount(), 0, base::NotFatalUntil::M128)
+  CHECK_GT(GetTabCount(), 0)
       << "The tab strip must contain at least one tab to perform a move "
          "operation.";
 
@@ -1188,8 +1185,7 @@
   // OnTabWillBeRemoved should have ended any ongoing drags containing
   // `contents` already - unless the call is coming from inside the house! (i.e.
   // the TabDragController is doing the removing as part of reverting a drag)
-  CHECK(drag_context_->CanRemoveTabIfDragging(contents),
-        base::NotFatalUntil::M128)
+  CHECK(drag_context_->CanRemoveTabIfDragging(contents))
       << "Attempted to remove a tab that could not be removed during drag.";
 
   tab_container_->RemoveTab(model_index, was_active);
@@ -1371,7 +1367,7 @@
 void TabStrip::SetSelection(const ui::ListSelectionModel& new_selection) {
   // This CHECK ensures there is always an active tab to maintain UI
   // consistency.
-  CHECK(new_selection.active().has_value(), base::NotFatalUntil::M128)
+  CHECK(new_selection.active().has_value())
       << "We should never transition to a state where no tab is active.";
 
   Tab* const new_active_tab = tab_at(new_selection.active().value());
@@ -1842,9 +1838,7 @@
   // Check that the source is either a valid tab or a tab group header, which
   // are the only valid drag targets.
   CHECK(GetModelIndexOf(source).has_value() ||
-            source->GetTabSlotViewType() ==
-                TabSlotView::ViewType::kTabGroupHeader,
-        base::NotFatalUntil::M128)
+        source->GetTabSlotViewType() == TabSlotView::ViewType::kTabGroupHeader)
       << "Drag source must be a valid tab or a tab group header.";
 
   drag_context_->MaybeStartDrag(source, event, original_selection);
@@ -2079,7 +2073,7 @@
 // TabStrip, views::View overrides:
 
 views::SizeBounds TabStrip::GetAvailableSize(const views::View* child) const {
-  CHECK(child == base::to_address(tab_container_), base::NotFatalUntil::M128)
+  CHECK(child == base::to_address(tab_container_))
       << "The child view does not match the expected tab_container_ address.";
   return parent()->GetAvailableSize(this);
 }
@@ -2326,7 +2320,7 @@
 }
 
 void TabStrip::ShiftTabRelative(Tab* tab, int offset) {
-  CHECK_EQ(1, std::abs(offset), base::NotFatalUntil::M128)
+  CHECK_EQ(1, std::abs(offset))
       << "Offset must be 1 or -1 to shift tab left or right.";
   const std::optional<int> maybe_start_index = GetModelIndexOf(tab);
   if (!maybe_start_index.has_value()) {
@@ -2397,7 +2391,7 @@
 
 void TabStrip::ShiftGroupRelative(const tab_groups::TabGroupId& group,
                                   int offset) {
-  CHECK_EQ(1, std::abs(offset), base::NotFatalUntil::M128)
+  CHECK_EQ(1, std::abs(offset))
       << "Offset must be 1 or -1 to shift the group left or right.";
   gfx::Range tabs_in_group = controller_->ListTabsInGroup(group);
 
@@ -2443,8 +2437,7 @@
     ui::mojom::MenuSourceType source_type) {
   // We are only intended to be installed as a context-menu handler for tabs, so
   // this cast should be safe.
-  CHECK(views::IsViewClass<Tab>(source), base::NotFatalUntil::M128)
-      << "The source must be a Tab class.";
+  CHECK(views::IsViewClass<Tab>(source)) << "The source must be a Tab class.";
   Tab* const tab = static_cast<Tab*>(source);
   if (tab->closing()) {
     return;
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button_browsertest.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button_browsertest.cc
new file mode 100644
index 0000000..4eab4443
--- /dev/null
+++ b/chrome/browser/ui/views/toolbar/webui_tab_counter_button_browsertest.cc
@@ -0,0 +1,24 @@
+// Copyright 2020 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/views/toolbar/webui_tab_counter_button.h"
+
+#include "chrome/browser/ui/browser_tabstrip.h"
+#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/views/frame/browser_view.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/browser_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/view.h"
+
+using WebUITabCounterButtonTest = InProcessBrowserTest;
+
+IN_PROC_BROWSER_TEST_F(WebUITabCounterButtonTest, CheckFocusBehavior) {
+  auto button = CreateWebUITabCounterButton(
+      views::Button::PressedCallback(),
+      BrowserView::GetBrowserViewForBrowser(browser()));
+  EXPECT_EQ(button->GetFocusBehavior(),
+            views::View::FocusBehavior::ACCESSIBLE_ONLY);
+}
diff --git a/chrome/browser/ui/views/toolbar/webui_tab_counter_button_unittest.cc b/chrome/browser/ui/views/toolbar/webui_tab_counter_button_unittest.cc
deleted file mode 100644
index 1096d4a4..0000000
--- a/chrome/browser/ui/views/toolbar/webui_tab_counter_button_unittest.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/ui/views/toolbar/webui_tab_counter_button.h"
-
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/views/controls/button/button.h"
-#include "ui/views/view.h"
-
-using WebUITabCounterButtonTest = TestWithBrowserView;
-
-TEST_F(WebUITabCounterButtonTest, CheckFocusBehavior) {
-  auto button = CreateWebUITabCounterButton(views::Button::PressedCallback(),
-                                            browser_view());
-  EXPECT_EQ(views::View::FocusBehavior::ACCESSIBLE_ONLY,
-            button->GetFocusBehavior());
-}
diff --git a/chrome/browser/ui/views/user_education/recent_session_observer_impl_unittest.cc b/chrome/browser/ui/views/user_education/recent_session_observer_impl_browsertest.cc
similarity index 82%
rename from chrome/browser/ui/views/user_education/recent_session_observer_impl_unittest.cc
rename to chrome/browser/ui/views/user_education/recent_session_observer_impl_browsertest.cc
index bf0c37a..4d57bc65 100644
--- a/chrome/browser/ui/views/user_education/recent_session_observer_impl_unittest.cc
+++ b/chrome/browser/ui/views/user_education/recent_session_observer_impl_browsertest.cc
@@ -10,10 +10,11 @@
 #include "base/callback_list.h"
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
+#include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/user_education/recent_session_policy.h"
-#include "chrome/browser/ui/views/frame/browser_view.h"
-#include "chrome/browser/ui/views/frame/test_with_browser_view.h"
 #include "chrome/browser/user_education/browser_user_education_storage_service.h"
+#include "chrome/test/base/in_process_browser_test.h"
+#include "content/public/test/browser_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "ui/base/interaction/expect_call_in_scope.h"
@@ -37,10 +38,10 @@
 
 }  // namespace
 
-class RecentSessionObserverImplTest : public TestWithBrowserView {
+class RecentSessionObserverImplBrowserTest : public InProcessBrowserTest {
  public:
-  RecentSessionObserverImplTest() = default;
-  ~RecentSessionObserverImplTest() override = default;
+  RecentSessionObserverImplBrowserTest() = default;
+  ~RecentSessionObserverImplBrowserTest() override = default;
 
   static void SendUpdate(RecentSessionObserverImpl& observer,
                          const RecentSessionData& data) {
@@ -48,12 +49,13 @@
   }
 };
 
-TEST_F(RecentSessionObserverImplTest, OnRecentSessionsUpdated) {
+IN_PROC_BROWSER_TEST_F(RecentSessionObserverImplBrowserTest,
+                       OnRecentSessionsUpdated) {
   auto policy_ptr =
       std::make_unique<testing::StrictMock<MockRecentSessionPolicy>>();
   auto& policy = *policy_ptr;
   const auto observer = std::make_unique<RecentSessionObserverImpl>(
-      *browser_view()->GetProfile(), std::move(policy_ptr));
+      *browser()->profile(), std::move(policy_ptr));
 
   RecentSessionData data;
 
@@ -63,13 +65,13 @@
   SendUpdate(*observer, data);
 }
 
-TEST_F(RecentSessionObserverImplTest, SessionCallback) {
+IN_PROC_BROWSER_TEST_F(RecentSessionObserverImplBrowserTest, SessionCallback) {
   UNCALLED_MOCK_CALLBACK(base::RepeatingClosure, callback);
   auto policy_ptr =
       std::make_unique<testing::StrictMock<MockRecentSessionPolicy>>();
   auto& policy = *policy_ptr;
   const auto observer = std::make_unique<RecentSessionObserverImpl>(
-      *browser_view()->GetProfile(), std::move(policy_ptr));
+      *browser()->profile(), std::move(policy_ptr));
   const auto subscription =
       observer->AddLowUsageSessionCallback(callback.Get());
 
@@ -88,13 +90,14 @@
   EXPECT_CALL_IN_SCOPE(callback, Run, SendUpdate(*observer, data));
 }
 
-TEST_F(RecentSessionObserverImplTest, SessionCallbackOnObserve) {
+IN_PROC_BROWSER_TEST_F(RecentSessionObserverImplBrowserTest,
+                       SessionCallbackOnObserve) {
   UNCALLED_MOCK_CALLBACK(base::RepeatingClosure, callback);
   auto policy_ptr =
       std::make_unique<testing::StrictMock<MockRecentSessionPolicy>>();
   auto& policy = *policy_ptr;
   const auto observer = std::make_unique<RecentSessionObserverImpl>(
-      *browser_view()->GetProfile(), std::move(policy_ptr));
+      *browser()->profile(), std::move(policy_ptr));
 
   RecentSessionData data;
 
diff --git a/chrome/browser/ui/views/webauthn/authenticator_qr_centered_view.cc b/chrome/browser/ui/views/webauthn/authenticator_qr_centered_view.cc
index 5a8bcba5..5378cb8 100644
--- a/chrome/browser/ui/views/webauthn/authenticator_qr_centered_view.cc
+++ b/chrome/browser/ui/views/webauthn/authenticator_qr_centered_view.cc
@@ -10,7 +10,6 @@
 #include "base/check.h"
 #include "base/containers/span.h"
 #include "base/memory/raw_ptr.h"
-#include "base/not_fatal_until.h"
 #include "chrome/browser/ui/color/chrome_color_id.h"
 #include "chrome/grit/generated_resources.h"
 #include "components/qr_code_generator/bitmap_generator.h"
@@ -63,7 +62,7 @@
 
   // Success is guaranteed, because `qr_string`'s size is bounded and smaller
   // than QR code limits.
-  CHECK(qr_code.has_value(), base::NotFatalUntil::M124);
+  CHECK(qr_code.has_value());
 
   qr_code_image_->SetImage(ui::ImageModel::FromImageSkia(qr_code.value()));
   qr_code_image_->SetVisible(true);
diff --git a/chrome/browser/web_applications/commands/set_user_display_mode_command.cc b/chrome/browser/web_applications/commands/set_user_display_mode_command.cc
index 93ddf2ef..ff157b4c 100644
--- a/chrome/browser/web_applications/commands/set_user_display_mode_command.cc
+++ b/chrome/browser/web_applications/commands/set_user_display_mode_command.cc
@@ -9,7 +9,6 @@
 
 #include "base/functional/callback.h"
 #include "base/metrics/user_metrics.h"
-#include "base/not_fatal_until.h"
 #include "base/values.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
 #include "chrome/browser/web_applications/locks/app_lock.h"
@@ -112,7 +111,7 @@
   {
     ScopedRegistryUpdate update = resources.sync_bridge().BeginUpdate();
     WebApp* web_app = update->UpdateApp(app_id);
-    CHECK(web_app, base::NotFatalUntil::M127);
+    CHECK(web_app);
     if (web_app) {
       web_app->SetUserDisplayMode(user_display_mode);
       if (needs_os_integration_sync) {
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index fe23383..55a4fe7 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -692,7 +692,7 @@
 void WebApp::SetSyncProto(sync_pb::WebAppSpecifics sync_proto) {
   // Populate sync_proto's start_url from this WebApp if missing.
   if (!start_url().is_empty()) {
-    CHECK(start_url().is_valid(), base::NotFatalUntil::M126);
+    CHECK(start_url().is_valid());
     // Note: sync data may have a start_url that does not match the `WebApp`
     // start_url, but it does not update the app (matching pre-M125 behaviour).
     if (!sync_proto.has_start_url()) {
@@ -701,11 +701,10 @@
   }
 
   // Sync data must never be set on an app with mismatching manifest_id.
-  CHECK(manifest_id().is_valid(), base::NotFatalUntil::M126);
+  CHECK(manifest_id().is_valid());
   std::string relative_manifest_id_path = RelativeManifestIdPath(manifest_id());
   if (sync_proto.has_relative_manifest_id()) {
-    CHECK_EQ(sync_proto.relative_manifest_id(), relative_manifest_id_path,
-             base::NotFatalUntil::M127);
+    CHECK_EQ(sync_proto.relative_manifest_id(), relative_manifest_id_path);
   } else {
     sync_proto.set_relative_manifest_id(relative_manifest_id_path);
   }
@@ -750,7 +749,7 @@
   CHECK(manifest_id.is_valid());
   CHECK(start_url_.is_empty() || url::IsSameOriginWith(start_url_, manifest_id))
       << start_url_.spec() << " vs " << manifest_id.spec();
-  CHECK(!manifest_id.has_ref(), base::NotFatalUntil::M127);
+  CHECK(!manifest_id.has_ref());
   manifest_id_ = manifest_id;
 
   // Ensure sync proto is initialized and remains consistent. Logic in
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index 2e76fa4..32757035 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -15,7 +15,6 @@
 
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
-#include "base/not_fatal_until.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
@@ -258,9 +257,9 @@
   // wins.
   const sync_pb::WebAppSpecifics& sync_proto() const {
     // Ensure the sync proto has been initialized.
-    CHECK(sync_proto_.has_start_url(), base::NotFatalUntil::M126);
-    CHECK(GURL(sync_proto_.start_url()).is_valid(), base::NotFatalUntil::M126);
-    CHECK(sync_proto_.has_relative_manifest_id(), base::NotFatalUntil::M126);
+    CHECK(sync_proto_.has_start_url());
+    CHECK(GURL(sync_proto_.start_url()).is_valid());
+    CHECK(sync_proto_.has_relative_manifest_id());
     return sync_proto_;
   }
 
diff --git a/chrome/browser/web_applications/web_app_install_finalizer.cc b/chrome/browser/web_applications/web_app_install_finalizer.cc
index 5252282..caaa134 100644
--- a/chrome/browser/web_applications/web_app_install_finalizer.cc
+++ b/chrome/browser/web_applications/web_app_install_finalizer.cc
@@ -19,7 +19,6 @@
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/sequenced_task_runner.h"
@@ -144,8 +143,7 @@
   }
 
   // Guaranteed by EnsureAppsHaveUserDisplayModeForCurrentPlatform().
-  CHECK(web_app.sync_proto().has_user_display_mode_cros(),
-        base::NotFatalUntil::M125);
+  CHECK(web_app.sync_proto().has_user_display_mode_cros());
 
   // Don't mitigate installations from sync, this is only for installs that will
   // be newly uploaded to sync.
diff --git a/chrome/browser/web_applications/web_app_install_info.cc b/chrome/browser/web_applications/web_app_install_info.cc
index 99f9b90..378694d1 100644
--- a/chrome/browser/web_applications/web_app_install_info.cc
+++ b/chrome/browser/web_applications/web_app_install_info.cc
@@ -12,7 +12,6 @@
 #include "base/check.h"
 #include "base/check_is_test.h"
 #include "base/containers/flat_tree.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/to_string.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/trace_event/trace_event.h"
@@ -379,12 +378,11 @@
 namespace {
 void CheckValidManifestIdAndStartUrl(const webapps::ManifestId& manifest_id,
                                      const GURL& start_url) {
-  CHECK(manifest_id.is_valid(), base::NotFatalUntil::M129);
-  CHECK(!manifest_id.has_ref(), base::NotFatalUntil::M129);
-  CHECK(start_url.is_valid(), base::NotFatalUntil::M129);
+  CHECK(manifest_id.is_valid());
+  CHECK(!manifest_id.has_ref());
+  CHECK(start_url.is_valid());
   CHECK(url::Origin::Create(start_url).IsSameOriginWith(
-            url::Origin::Create(manifest_id)),
-        base::NotFatalUntil::M129);
+      url::Origin::Create(manifest_id)));
 }
 }  // namespace
 
diff --git a/chrome/browser/web_applications/web_app_install_utils.cc b/chrome/browser/web_applications/web_app_install_utils.cc
index d2c66a70..1f7194f 100644
--- a/chrome/browser/web_applications/web_app_install_utils.cc
+++ b/chrome/browser/web_applications/web_app_install_utils.cc
@@ -31,7 +31,6 @@
 #include "base/metrics/histogram.h"
 #include "base/metrics/histogram_base.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/notreached.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
@@ -1136,8 +1135,8 @@
   sync_pb::WebAppSpecifics sync_proto = web_app.sync_proto();
   // Sync proto has already been initialized by setting the start_url and/or
   // manifest_id above.
-  CHECK(sync_proto.has_start_url(), base::NotFatalUntil::M126);
-  CHECK(sync_proto.has_relative_manifest_id(), base::NotFatalUntil::M126);
+  CHECK(sync_proto.has_start_url());
+  CHECK(sync_proto.has_relative_manifest_id());
   sync_proto.set_name(base::UTF16ToUTF8(web_app_info.title));
   sync_proto.clear_theme_color();
   if (web_app_info.theme_color.has_value()) {
diff --git a/chrome/browser/web_applications/web_app_proto_utils.cc b/chrome/browser/web_applications/web_app_proto_utils.cc
index f8e29cb7..0e9c4c9f 100644
--- a/chrome/browser/web_applications/web_app_proto_utils.cc
+++ b/chrome/browser/web_applications/web_app_proto_utils.cc
@@ -3,7 +3,6 @@
 // found in the LICENSE file.
 
 #include "chrome/browser/web_applications/web_app_proto_utils.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
 #include "chrome/browser/web_applications/proto/web_app_url_pattern.pb.h"
@@ -399,7 +398,7 @@
 }
 
 std::string RelativeManifestIdPath(webapps::ManifestId manifest_id) {
-  CHECK(manifest_id.is_valid(), base::NotFatalUntil::M127);
+  CHECK(manifest_id.is_valid());
   // The relative id does not include the initial '/' character.
   std::string relative_manifest_id_path = manifest_id.PathForRequest();
   if (relative_manifest_id_path.starts_with("/")) {
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc
index 4bd79be..86f22cd6 100644
--- a/chrome/browser/web_applications/web_app_sync_bridge.cc
+++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -25,7 +25,6 @@
 #include "base/functional/callback_helpers.h"
 #include "base/logging.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/to_string.h"
 #include "base/types/expected.h"
 #include "base/types/pass_key.h"
@@ -370,7 +369,7 @@
 
 void WebAppSyncBridge::SetUserPageOrdinal(const webapps::AppId& app_id,
                                           syncer::StringOrdinal page_ordinal) {
-  CHECK(page_ordinal.IsValid(), base::NotFatalUntil::M126);
+  CHECK(page_ordinal.IsValid());
   ScopedRegistryUpdate update = BeginUpdate();
   WebApp* web_app = update->UpdateApp(app_id);
   // Due to the extensions sync system setting ordinals on sync, this can get
@@ -390,7 +389,7 @@
 void WebAppSyncBridge::SetUserLaunchOrdinal(
     const webapps::AppId& app_id,
     syncer::StringOrdinal launch_ordinal) {
-  CHECK(launch_ordinal.IsValid(), base::NotFatalUntil::M126);
+  CHECK(launch_ordinal.IsValid());
   ScopedRegistryUpdate update = BeginUpdate();
   // Due to the extensions sync system setting ordinals on sync, this can get
   // called before the app is installed in the web apps system. Until apps are
@@ -523,7 +522,7 @@
   }
   for (const webapps::AppId& app_id : update_data->apps_to_delete) {
     auto it = registrar_->registry().find(app_id);
-    CHECK(it != registrar_->registry().end(), base::NotFatalUntil::M130);
+    CHECK(it != registrar_->registry().end());
     registrar_->registry().erase(it);
   }
 }
@@ -542,7 +541,7 @@
 
   for (const std::unique_ptr<WebApp>& new_app : update_data.apps_to_create) {
     if (new_app->IsSynced()) {
-      CHECK(new_app->manifest_id().is_valid(), base::NotFatalUntil::M125);
+      CHECK(new_app->manifest_id().is_valid());
       change_processor()->Put(new_app->app_id(), CreateSyncEntityData(*new_app),
                               metadata_change_list);
     }
@@ -558,7 +557,7 @@
     // the app if IsSynced flag stays true. Exclude the app from the sync "view"
     // if IsSynced flag becomes false.
     if (new_state->IsSynced()) {
-      CHECK(new_state->manifest_id().is_valid(), base::NotFatalUntil::M125);
+      CHECK(new_state->manifest_id().is_valid());
       // Only call 'Put' if it wasn't synced, or if the sync data has changed.
       // TODO(https://crbug.com/409867622): We can remove this optimization
       // after tests are updated to use a Fake version instead of the Mock
@@ -917,12 +916,12 @@
 
 std::string WebAppSyncBridge::GetClientTag(
     const syncer::EntityData& entity_data) const {
-  CHECK(entity_data.specifics.has_web_app(), base::NotFatalUntil::M125);
+  CHECK(entity_data.specifics.has_web_app());
   base::expected<webapps::ManifestId, StorageKeyParseResult> manifest_id =
       ParseManifestIdFromSyncEntity(entity_data.specifics.web_app());
   // This is guaranteed to be true, as the contract for this function is that
   // IsEntityDataValid must be true.
-  CHECK(manifest_id.has_value(), base::NotFatalUntil::M125);
+  CHECK(manifest_id.has_value());
   return GenerateAppIdFromManifestId(manifest_id.value());
 }
 
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index e27ee5e..bcb266f 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1748260543-a570212d6c379a3f0bef0b7704e763912f3d2600-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
+chrome-android32-main-1748281879-f6307920645d7c967935982bdcc31bd8d8219885-45948ebd114566ec45402d34c635daf1833726d9.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 433ae64..766cf05 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1748263541-59195261a4aeb4cce5b3c4648602558b3b74a52b-59dd52af4a9d415e1daf1c0fb3e6c29c57203361.profdata
+chrome-android64-main-1748285041-8d50d17d839af992aa35ba597047910cf9e0c3fd-def4aa84cb21b505f52ce398a3a29962094a23a7.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 81f68c1..34a6d03 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1748260543-125c386337e2dbc00eb2263d09a9eb017bef0a64-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
+chrome-linux-main-1748281879-7667e8e2fd64748ae4601eb3058cede98a5f150a-45948ebd114566ec45402d34c635daf1833726d9.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 13bacf87..75121aa 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1748267682-dae69aa8d12b9a0e606d9e80c6448940324f75ea-222fa6a40d583aab260429585088a0469723108d.profdata
+chrome-mac-arm-main-1748289504-5a78a4991f4bf92a93cc7a2ae35d8d605fad4c17-532a20f725c527d371febeefac67f20014f514b2.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b2a0ab5..612627e 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1748260543-8fcd83f27ccf8087ec2ee3b48213aced51434d62-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
+chrome-mac-main-1748281879-ccab29a8196a7d38897915fe44e0ad7ab0166168-45948ebd114566ec45402d34c635daf1833726d9.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 5f0a53d..400fca3 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1748260543-e2b99b128af326ae056c0fda7dd938c61152b77f-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
+chrome-win-arm64-main-1748281879-71ed81f464062b9e978f33a4c510be0f8ed3fb60-45948ebd114566ec45402d34c635daf1833726d9.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 25da11b3..88c342d 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1748249926-c5c67c4fb659007438429c3f05a9a626a09b1eee-50eafedd2577ddad80c88efdcc91b0f46b3325f7.profdata
+chrome-win32-main-1748260543-369d748d0e83b5094a87f8601251a6774bf4ba8b-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 3adf13c..54a9015 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1748238035-71c35c1b355083c736b11be97d6a2914c42ec1e8-418ce0257f6ebe8f9a141d27ee77e7f0e38cc2cb.profdata
+chrome-win64-main-1748260543-1b8a25b0391224b1b4bf93020837290e05fc6b4c-436cf5a446bcda10aa2bc655f57ce243f534330d.profdata
diff --git a/chrome/common/actor.mojom b/chrome/common/actor.mojom
index d97588a..ede0704 100644
--- a/chrome/common/actor.mojom
+++ b/chrome/common/actor.mojom
@@ -173,6 +173,9 @@
   // Arguments supplied to the tool are invalid.
   kArgumentsInvalid = 22,
 
+  // The task for the action was paused.
+  kTaskPaused = 23,
+
   ///////////////////////////////////////////////////////////////////////
   // Codes 100-199: Errors for navigation. (Not part of the ToolAction union
   // as it's a browser-side tool.)
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc
index 4c21e30..7a97160 100644
--- a/chrome/common/chrome_features.cc
+++ b/chrome/common/chrome_features.cc
@@ -328,7 +328,7 @@
 BASE_FEATURE(kGeoLanguage, "GeoLanguage", base::FEATURE_DISABLED_BY_DEFAULT);
 
 // Controls whether the actor component of Glic is enabled.
-BASE_FEATURE(kGlicActor, "GlicActor", base::FEATURE_ENABLED_BY_DEFAULT);
+BASE_FEATURE(kGlicActor, "GlicActor", base::FEATURE_DISABLED_BY_DEFAULT);
 const base::FeatureParam<base::TimeDelta> kGlicActorActorObservationDelay{
     &kGlicActor, "glic-actor-observation-delay", base::Seconds(3)};
 
@@ -423,6 +423,11 @@
                    "glic-user-status-oauth2-scope",
                    "https://www.googleapis.com/auth/gemini");
 
+BASE_FEATURE_PARAM(double,
+                   kGlicUserStatusRequestDelayJitter,
+                   &kGlicUserStatusCheck,
+                   "glic-user-status-request-delay-jitter",
+                   0.005);
 BASE_FEATURE(kGlicFreURLConfig,
              "GlicFreURLConfig",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h
index 2adec6ec..7437532 100644
--- a/chrome/common/chrome_features.h
+++ b/chrome/common/chrome_features.h
@@ -236,6 +236,10 @@
 extern const base::FeatureParam<base::TimeDelta> kGlicUserStatusRequestDelay;
 COMPONENT_EXPORT(CHROME_FEATURES)
 extern const base::FeatureParam<std::string> kGeminiOAuth2Scope;
+COMPONENT_EXPORT(CHROME_FEATURES)
+// This is the maximum deviation. The jitter to the delay is a uniformly random
+// sample from the chosen deviation. The value should be less than 1.
+extern const base::FeatureParam<double> kGlicUserStatusRequestDelayJitter;
 
 COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kGlicFreURLConfig);
 COMPONENT_EXPORT(CHROME_FEATURES)
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 09cc75b3..936b931 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4503,6 +4503,7 @@
         "../browser/supervised_user/desktop/supervised_user_extension_browsertest.cc",
         "../browser/supervised_user/extensions_interactive_uitest.cc",
         "../browser/ui/views/autofill/popup/custom_cursor_suppressor_browsertest.cc",
+        "../browser/ui/views/user_education/recent_session_observer_impl_browsertest.cc",
         "../browser/ui/views/web_apps/create_shortcut_confirmation_view_browsertest.cc",
         "../browser/ui/views/web_apps/simple_install_dialog_bubble_view_browsertest.cc",
         "../browser/ui/views/web_apps/web_app_identity_update_confirmation_view_browsertest.cc",
@@ -4589,10 +4590,6 @@
         ]
       }
 
-      if (enterprise_client_certificates) {
-        sources += [ "../browser/enterprise/client_certificates/client_certificates_browsertest.cc" ]
-      }
-
       if (is_win || is_linux || is_mac) {
         deps += [
           "//chrome/browser/enterprise/connectors/device_trust/key_management/browser/commands:test_support",
@@ -5629,6 +5626,7 @@
     if (enable_webui_tab_strip) {
       sources += [
         "../browser/ui/views/frame/webui_tab_strip_field_trial_browsertest.cc",
+        "../browser/ui/views/toolbar/webui_tab_counter_button_browsertest.cc",
         "../browser/ui/webui/tab_strip/tab_strip_ui_browsertest.cc",
       ]
     }
@@ -6492,7 +6490,6 @@
   if (enable_webui_tab_strip) {
     sources += [
       "../browser/ui/views/frame/webui_tab_strip_container_view_unittest.cc",
-      "../browser/ui/views/toolbar/webui_tab_counter_button_unittest.cc",
       "../browser/ui/webui/tab_strip/tab_strip_page_handler_unittest.cc",
       "../browser/ui/webui/tab_strip/tab_strip_ui_layout_unittest.cc",
       "../browser/ui/webui/tab_strip/thumbnail_tracker_unittest.cc",
@@ -10279,7 +10276,6 @@
       "../browser/ui/views/translate/translate_bubble_view_unittest.cc",
       "../browser/ui/views/user_education/browser_user_education_service_unittest.cc",
       "../browser/ui/views/user_education/help_bubble_view_timeout_unittest.cc",
-      "../browser/ui/views/user_education/recent_session_observer_impl_unittest.cc",
       "../browser/ui/views/user_education/views_tutorial_unittest.cc",
       "../browser/ui/views/web_apps/isolated_web_apps/callback_delayer_unittest.cc",
       "../browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.cc",
diff --git a/chromeos/ash/services/network_config/cros_network_config.cc b/chromeos/ash/services/network_config/cros_network_config.cc
index df098c2..63fe78c 100644
--- a/chromeos/ash/services/network_config/cros_network_config.cc
+++ b/chromeos/ash/services/network_config/cros_network_config.cc
@@ -15,7 +15,6 @@
 #include "base/containers/flat_map.h"
 #include "base/i18n/time_formatting.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
@@ -673,8 +672,7 @@
 std::string GetRequiredString(const base::Value::Dict* dict, const char* key) {
   const base::Value* v = dict->Find(key);
   if (!v) {
-    NOTREACHED(base::NotFatalUntil::M127) << "Required key missing: " << key;
-    return std::string();
+    NOTREACHED() << "Required key missing: " << key;
   }
   if (!v->is_string()) {
     NET_LOG(ERROR) << "Expected string, found: " << *v;
diff --git a/clank b/clank
index c6f37b2..7b3b668 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit c6f37b2a1ac4f90393eff3c734ca926a8e602153
+Subproject commit 7b3b66843fe0c37489709a09bf6e4c57c6087f53
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 51f59a7c..6eb0b602 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -8,6 +8,7 @@
 import("//build/config/ui.gni")
 import("//components/compose/features.gni")
 import("//components/enterprise/buildflags/buildflags.gni")
+import("//components/guest_contents/common/buildflags.gni")
 import("//components/guest_view/buildflags/buildflags.gni")
 import("//components/nacl/features.gni")
 import("//components/optimization_guide/features.gni")
@@ -726,6 +727,10 @@
     ]
   }
 
+  if (enable_guest_contents) {
+    deps += [ "//components/guest_contents/browser:unit_tests" ]
+  }
+
   if (enable_guest_view) {
     deps += [ "//components/guest_view/browser:unit_tests" ]
   }
@@ -1233,6 +1238,7 @@
       "autofill/core/browser/ml_model/field_classification_model_executor_perftest.cc",
       "discardable_memory/common/discardable_shared_memory_heap_perftest.cc",
       "omnibox/browser/history_quick_provider_performance_unittest.cc",
+      "persistent_cache/persistent_cache_perftest.cc",
       "subresource_filter/core/common/perftests/indexed_ruleset_perftest.cc",
       "test/run_all_perftests.cc",
       "visitedlink/test/visitedlink_perftest.cc",
@@ -1248,6 +1254,8 @@
       "//components/history/core/test",
       "//components/omnibox/browser",
       "//components/omnibox/browser:test_support",
+      "//components/persistent_cache",
+      "//components/persistent_cache:test_support",
       "//components/subresource_filter/core/common",
       "//components/subresource_filter/tools:tools_lib",
       "//components/test:test_support",
diff --git a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
index 080b7c3f..e0f316f 100644
--- a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
+++ b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.cc
@@ -18,6 +18,8 @@
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/crowdsourcing/disambiguate_possible_field_types.h"
 #include "components/autofill/core/browser/data_model/addresses/address.h"
+#include "components/autofill/core/browser/data_model/addresses/autofill_profile_comparator.h"
+#include "components/autofill/core/browser/data_model/autofill_ai/entity_instance.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
 #include "components/autofill/core/browser/data_model/payments/credit_card.h"
 #include "components/autofill/core/browser/data_model/valuables/loyalty_card.h"
@@ -34,6 +36,31 @@
 
 namespace {
 
+// Matches a date consisting of year, month, and day in a the given string.
+std::vector<std::u16string> GetMatchingCompleteDateFormats(
+    std::u16string_view date) {
+  std::vector<std::u16string> format_strings;
+  for (std::u16string_view format :
+       {// Ordering: year month day.
+        u"YYYY*MM*DD", u"YY*MM*DD", u"YYYY+M+D", u"YY+M+D",
+        // Ordering: month day year.
+        u"MM*DD*YYYY", u"MM*DD*YY", u"M+D+YYYY", u"M+D+YY",
+        // Ordering: day month year.
+        u"DD*MM*YYYY", u"DD*MM*YY", u"D+M+YYYY", u"D+M+YY"}) {
+    data_util::Date result;
+    const char16_t* separator = nullptr;
+    if (data_util::ParseDate(date, format, result, separator) &&
+        data_util::IsValidDateForFormat(result, format)) {
+      std::u16string instantiated_format;
+      base::ReplaceChars(format, u"*+", separator, &instantiated_format);
+      if (data_util::ParseDate(date, instantiated_format, result)) {
+        format_strings.push_back(instantiated_format);
+      }
+    }
+  }
+  return format_strings;
+}
+
 // Finds the first field in |form_structure| with |field.value|=|value|.
 AutofillField* FindFirstFieldWithValue(const FormStructure& form_structure,
                                        std::u16string_view value) {
@@ -132,6 +159,88 @@
   return HeuristicallyFindCVCFieldForUpload(form_structure);
 }
 
+// Returns the FieldTypes for some given EntityInstance defines a non-empty
+// value.
+//
+// This may not just include Autofill AI types like PASSPORT_NUMBER but
+// also tag types like PASSPORT_NAME_TAG together with the refined type like
+// NAME_FIRST.
+FieldTypeSet GetAvailableAutofillAiFieldTypes(
+    base::span<const EntityInstance> entities,
+    const std::string& app_locale) {
+  CHECK(base::FeatureList::IsEnabled(features::kAutofillAiWithDataSchema));
+  AutofillProfileComparator comparator(app_locale);
+  FieldTypeSet types;
+  for (const EntityInstance& entity : entities) {
+    for (const AttributeInstance& attribute : entity.attributes()) {
+      for (FieldType field_type : attribute.GetSupportedTypes()) {
+        bool is_empty = comparator.HasOnlySkippableCharacters(attribute.GetInfo(
+            field_type, comparator.app_locale(), std::nullopt));
+        if (!is_empty) {
+          types.insert(attribute.type().field_type());
+          types.insert(field_type);
+        }
+      }
+    }
+  }
+  return types;
+}
+
+// Returns the FieldTypes for some given EntityInstance has an attribute whose
+// value matches `value_u16`.
+//
+// This may not just include Autofill AI types like PASSPORT_NUMBER but
+// also tag types like PASSPORT_NAME_TAG together with the refined type like
+// NAME_FIRST.
+FieldTypeSet GetPossibleAutofillAiFieldTypes(
+    base::span<const EntityInstance> entities,
+    std::u16string_view value_u16,
+    const std::string& app_locale) {
+  CHECK(base::FeatureList::IsEnabled(features::kAutofillAiWithDataSchema));
+
+  AutofillProfileComparator comparator(app_locale);
+  if (comparator.HasOnlySkippableCharacters(value_u16)) {
+    return {};
+  }
+
+  std::u16string value =
+      AutofillProfileComparator::NormalizeForComparison(value_u16);
+
+  auto date_matches = [&comparator, &value](const AttributeInstance& attribute,
+                                            FieldType field_type) {
+    return std::ranges::any_of(GetMatchingCompleteDateFormats(value),
+                               [&](const std::u16string& format) {
+                                 return attribute.GetInfo(
+                                            field_type, comparator.app_locale(),
+                                            format) == value;
+                               });
+  };
+
+  auto nondate_matches = [&comparator, &value](
+                             const AttributeInstance& attribute,
+                             FieldType field_type) {
+    return comparator.Compare(
+        value,
+        attribute.GetInfo(field_type, comparator.app_locale(), std::nullopt),
+        AutofillProfileComparator::DISCARD_WHITESPACE);
+  };
+
+  FieldTypeSet types;
+  for (const EntityInstance& entity : entities) {
+    for (const AttributeInstance& attribute : entity.attributes()) {
+      for (FieldType field_type : attribute.GetSupportedTypes()) {
+        if (IsDateFieldType(field_type)
+                ? date_matches(attribute, field_type)
+                : nondate_matches(attribute, field_type)) {
+          types.insert(attribute.type().field_type());
+          types.insert(field_type);
+        }
+      }
+    }
+  }
+  return types;
+}
+
 // Extracts the value from `field`. Then for each profile or credit card,
 // identify any stored types that match the value. Runs additional heuristics
 // for increased accuracy. Defaults to `{UNKNOWN_TYPE}` if no types could be
@@ -140,6 +249,7 @@
     AutofillField& field,
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     const std::set<FieldGlobalId> fields_that_match_state,
     const std::string& app_locale) {
@@ -158,9 +268,14 @@
   for (const AutofillProfile& profile : profiles) {
     profile.GetMatchingTypes(value_u16, app_locale, &matching_types);
   }
+  if (fields_that_match_state.contains(field.global_id())) {
+    matching_types.insert(ADDRESS_HOME_STATE);
+  }
+
   for (const CreditCard& card : credit_cards) {
     card.GetMatchingTypes(value_u16, app_locale, &matching_types);
   }
+
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableLoyaltyCardsFilling)) {
     const std::string value_u8 = base::UTF16ToUTF8(value_u16);
@@ -171,9 +286,11 @@
     }
   }
 
-  if (fields_that_match_state.contains(field.global_id())) {
-    matching_types.insert(ADDRESS_HOME_STATE);
+  if (base::FeatureList::IsEnabled(features::kAutofillAiWithDataSchema)) {
+    matching_types.insert_all(
+        GetPossibleAutofillAiFieldTypes(entities, value_u16, app_locale));
   }
+
   if (matching_types.empty()) {
     matching_types.insert(UNKNOWN_TYPE);
   }
@@ -186,15 +303,16 @@
 void FindAndSetPossibleFieldTypes(
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     const std::set<FieldGlobalId> fields_that_match_state,
     std::u16string_view last_unlocked_credit_card_cvc,
     const std::string& app_locale,
     FormStructure& form) {
-  for (size_t i = 0; i < form.field_count(); ++i) {
-    FindAndSetPossibleFieldTypesForField(*form.field(i), profiles, credit_cards,
-                                         loyalty_cards, fields_that_match_state,
-                                         app_locale);
+  for (const std::unique_ptr<AutofillField>& field : form.fields()) {
+    FindAndSetPossibleFieldTypesForField(*field, profiles, credit_cards,
+                                         entities, loyalty_cards,
+                                         fields_that_match_state, app_locale);
   }
 
   // As CVCs are not stored, run special heuristics to detect CVC-like values.
@@ -208,31 +326,6 @@
   }
 }
 
-// Matches a date consisting of year, month, and day in a the given string.
-std::vector<std::u16string> GetMatchingCompleteDateFormats(
-    std::u16string_view date) {
-  std::vector<std::u16string> format_strings;
-  for (std::u16string_view format :
-       {// Ordering: year month day.
-        u"YYYY*MM*DD", u"YY*MM*DD", u"YYYY+M+D", u"YY+M+D",
-        // Ordering: month day year.
-        u"MM*DD*YYYY", u"MM*DD*YY", u"M+D+YYYY", u"M+D+YY",
-        // Ordering: day month year.
-        u"DD*MM*YYYY", u"DD*MM*YY", u"D+M+YYYY", u"D+M+YY"}) {
-    data_util::Date result;
-    const char16_t* separator = nullptr;
-    if (data_util::ParseDate(date, format, result, separator) &&
-        data_util::IsValidDateForFormat(result, format)) {
-      std::u16string instantiated_format;
-      base::ReplaceChars(format, u"*+", separator, &instantiated_format);
-      if (data_util::ParseDate(date, instantiated_format, result)) {
-        format_strings.push_back(instantiated_format);
-      }
-    }
-  }
-  return format_strings;
-}
-
 }  // namespace
 
 std::set<FieldGlobalId> PreProcessStateMatchingTypes(
@@ -275,6 +368,7 @@
 void DeterminePossibleFieldTypesForUpload(
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     const std::set<FieldGlobalId>& fields_that_match_state,
     std::u16string_view last_unlocked_credit_card_cvc,
@@ -285,7 +379,7 @@
     // the values so that the first call does not affect later calls.
     field->set_possible_types({});
   }
-  FindAndSetPossibleFieldTypes(profiles, credit_cards, loyalty_cards,
+  FindAndSetPossibleFieldTypes(profiles, credit_cards, entities, loyalty_cards,
                                fields_that_match_state,
                                last_unlocked_credit_card_cvc, app_locale, form);
   DisambiguatePossibleFieldTypes(form);
@@ -294,6 +388,7 @@
 FieldTypeSet DetermineAvailableFieldTypes(
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     std::u16string_view last_unlocked_credit_card_cvc,
     const std::string& app_locale) {
@@ -301,6 +396,7 @@
   for (const AutofillProfile& profile : profiles) {
     profile.GetNonEmptyTypes(app_locale, &types);
   }
+
   for (const CreditCard& card : credit_cards) {
     card.GetNonEmptyTypes(app_locale, &types);
   }
@@ -309,12 +405,16 @@
       types.contains(CREDIT_CARD_NUMBER)) {
     types.insert(CREDIT_CARD_VERIFICATION_CODE);
   }
+
+  if (base::FeatureList::IsEnabled(features::kAutofillAiWithDataSchema)) {
+    types.insert_all(GetAvailableAutofillAiFieldTypes(entities, app_locale));
+  }
+
   if (base::FeatureList::IsEnabled(
           features::kAutofillEnableLoyaltyCardsFilling) &&
       !loyalty_cards.empty()) {
     types.insert(LOYALTY_MEMBERSHIP_ID);
   }
-
   return types;
 }
 
diff --git a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.h b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.h
index ec92c64..3d8b2a2 100644
--- a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.h
+++ b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types.h
@@ -20,6 +20,7 @@
 
 class AutofillProfile;
 class CreditCard;
+class EntityInstance;
 class FormStructure;
 class LoyaltyCard;
 
@@ -32,14 +33,16 @@
     const FormStructure& form_structure,
     const std::string& app_locale);
 
-// Uses the existing personal data in `profiles`, `credit_cards` and
-// `loyalty_cards` to determine possible field types for the `form`.  This is
-// potentially expensive -- on the order of 50ms even for a small set of
+// Determines the `FieldType`s for which profiles etc. define non-empty
+// values. The result is stored in FormStructure::possible_types().
+//
+// This is potentially expensive -- on the order of 50ms even for a small set of
 // `stored_data`. Hence, it should not run on the UI thread -- to avoid
 // locking up the UI -- nor on the IO thread -- to avoid blocking IPC calls.
 void DeterminePossibleFieldTypesForUpload(
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     const std::set<FieldGlobalId>& fields_that_match_state,
     std::u16string_view last_unlocked_credit_card_cvc,
@@ -51,6 +54,7 @@
 FieldTypeSet DetermineAvailableFieldTypes(
     base::span<const AutofillProfile> profiles,
     base::span<const CreditCard> credit_cards,
+    base::span<const EntityInstance> entities,
     base::span<const LoyaltyCard> loyalty_cards,
     std::u16string_view last_unlocked_credit_card_cvc,
     const std::string& app_locale);
diff --git a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types_unittest.cc b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types_unittest.cc
index 9194386a..0f7145e8 100644
--- a/components/autofill/core/browser/crowdsourcing/determine_possible_field_types_unittest.cc
+++ b/components/autofill/core/browser/crowdsourcing/determine_possible_field_types_unittest.cc
@@ -35,6 +35,7 @@
 using ::testing::Matcher;
 using ::testing::Not;
 using ::testing::Pair;
+using ::testing::UnorderedElementsAre;
 using ::testing::UnorderedElementsAreArray;
 
 // Fakes that a `form` has been seen (without its field value) and parsed and
@@ -328,7 +329,8 @@
       ConstructFormStructureFromFormData(form);
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/u"", "en-us", *form_structure);
 
@@ -343,8 +345,17 @@
                          testing::ValuesIn(kProfileMatchingTypesTestCases));
 
 class DeterminePossibleFieldTypesForUploadTest : public ::testing::Test {
- protected:
+ public:
+  DeterminePossibleFieldTypesForUploadTest() {
+    scoped_feature_list_.InitWithFeatures(
+        {features::kAutofillAiWithDataSchema,
+         features::kAutofillEnableLoyaltyCardsFilling},
+        {});
+  }
+
+ private:
   test::AutofillUnitTestEnvironment autofill_test_environment_;
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
 // If a server-side credit card is unmasked by entering the CVC, the
@@ -377,7 +388,8 @@
   form_structure->field(0)->set_possible_types({CREDIT_CARD_NUMBER});
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/kCvc16, "en-us", *form_structure);
 
@@ -427,7 +439,8 @@
   std::vector<AutofillProfile> profiles;
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/std::u16string(), "en-us",
       *form_structure);
@@ -478,7 +491,8 @@
   std::vector<AutofillProfile> profiles;
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/std::u16string(), "en-us",
       *form_structure);
@@ -528,7 +542,8 @@
   std::vector<AutofillProfile> profiles;
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/std::u16string(), "en-us",
       *form_structure);
@@ -578,7 +593,8 @@
   std::vector<AutofillProfile> profiles;
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/std::u16string(), "en-us",
       *form_structure);
@@ -625,7 +641,8 @@
   std::vector<AutofillProfile> profiles;
 
   DeterminePossibleFieldTypesForUpload(
-      profiles, credit_cards, std::vector<LoyaltyCard>(),
+      profiles, credit_cards, std::vector<EntityInstance>(),
+      std::vector<LoyaltyCard>(),
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/u"", "en-us", *form_structure);
 
@@ -635,8 +652,6 @@
 
 // Tests if the loyalty card field detected.
 TEST_F(DeterminePossibleFieldTypesForUploadTest, CrowdsourceLoyaltyCardField) {
-  base::test::ScopedFeatureList scoped_feature_list_{
-      features::kAutofillEnableLoyaltyCardsFilling};
   constexpr char loyalty_card_program[] = "test_program";
   constexpr char loyalty_card_number[] = "4234567890123456";
 
@@ -661,7 +676,8 @@
   loyalty_card.set_loyalty_card_number(loyalty_card_number);
   loyalty_cards.push_back(loyalty_card);
   DeterminePossibleFieldTypesForUpload(
-      std::vector<AutofillProfile>(), std::vector<CreditCard>(), loyalty_cards,
+      std::vector<AutofillProfile>(), std::vector<CreditCard>(),
+      std::vector<EntityInstance>(), loyalty_cards,
       /*fields_that_match_state=*/{},
       /*last_unlocked_credit_card_cvc=*/u"", "en-us", *form_structure);
 
@@ -670,6 +686,51 @@
                                                FieldPropertiesFlags::kNoFlags);
 }
 
+// Tests if the Autofill AI field types are crowdsourced.
+TEST_F(DeterminePossibleFieldTypesForUploadTest, CrowdsourceAutofillAiTypes) {
+  FormData form;
+  form.set_fields({
+      CreateTestFormField("first-name", "first-name", "Pippi",
+                          FormControlType::kInputText),
+      CreateTestFormField("last-name", "last-name", "Longstocking",
+                          FormControlType::kInputText),
+      CreateTestFormField("number", "number", "1234567",
+                          FormControlType::kInputText),
+      CreateTestFormField("expiry-date", "expiry-date", "30/08/2019",
+                          FormControlType::kInputText),
+      CreateTestFormField("wrong-country", "wrong-country", "Finland",
+                          FormControlType::kInputText),
+  });
+  std::unique_ptr<FormStructure> form_structure =
+      ConstructFormStructureFromFormData(form);
+
+  EntityInstance entity = test::GetPassportEntityInstance({
+      .name = u"Pippi Longstocking",
+      .number = u"1234567",
+      .country = u"Sweden",
+      .expiry_date = u"2019-08-30",
+      .issue_date = u"2010-09-01",
+  });
+
+  DeterminePossibleFieldTypesForUpload(
+      std::vector<AutofillProfile>(), std::vector<CreditCard>(),
+      base::span_from_ref(entity), std::vector<LoyaltyCard>(),
+      /*fields_that_match_state=*/{},
+      /*last_unlocked_credit_card_cvc=*/u"", "en-US", *form_structure);
+
+  EXPECT_THAT(form_structure->fields()[0]->possible_types(),
+              UnorderedElementsAre(PASSPORT_NAME_TAG, NAME_FIRST));
+  EXPECT_THAT(
+      form_structure->fields()[1]->possible_types(),
+      UnorderedElementsAre(PASSPORT_NAME_TAG, NAME_LAST, NAME_LAST_SECOND));
+  EXPECT_THAT(form_structure->fields()[2]->possible_types(),
+              UnorderedElementsAre(PASSPORT_NUMBER));
+  EXPECT_THAT(form_structure->fields()[3]->possible_types(),
+              UnorderedElementsAre(PASSPORT_EXPIRATION_DATE));
+  EXPECT_THAT(form_structure->fields()[4]->possible_types(),
+              UnorderedElementsAre(UNKNOWN_TYPE));
+}
+
 // Test fixture for PreProcessStateMatchingTypes().
 class PreProcessStateMatchingTypesTest : public testing::Test {
  public:
@@ -990,11 +1051,13 @@
               UnorderedElementsAreArray(expectations));
 }
 
+// Test fixture for DetermineAvailableFieldTypes().
 class DetermineAvailableFieldTypesTest : public ::testing::Test {
  public:
   DetermineAvailableFieldTypesTest() {
     features_.InitWithFeatures(
-        {features::kAutofillEnableLoyaltyCardsFilling,
+        {features::kAutofillAiWithDataSchema,
+         features::kAutofillEnableLoyaltyCardsFilling,
          features::kAutofillEnableEmailOrLoyaltyCardsFilling},
         {});
   }
@@ -1004,13 +1067,28 @@
   base::test::ScopedFeatureList features_;
 };
 
+// Tests that entities are included in the set of available field types.
+TEST_F(DetermineAvailableFieldTypesTest, Entities) {
+  EntityInstance entity = test::GetPassportEntityInstance();
+  FieldTypeSet available_types = DetermineAvailableFieldTypes(
+      /*profiles=*/{}, /*credit_cards=*/{}, /*entities=*/{entity},
+      /*loyalty_cards=*/{},
+      /*last_unlocked_credit_card_cvc=*/u"",
+      /*app_locale=*/"en-US");
+  EXPECT_THAT(available_types,
+              UnorderedElementsAre(
+                  NAME_FULL, NAME_FIRST, NAME_LAST, NAME_LAST_SECOND,
+                  PASSPORT_NAME_TAG, PASSPORT_NUMBER, PASSPORT_EXPIRATION_DATE,
+                  PASSPORT_ISSUE_DATE, PASSPORT_ISSUING_COUNTRY));
+}
+
 // Tests that loyalty cards are included in the set of available field types.
 TEST_F(DetermineAvailableFieldTypesTest, LoyaltyCards) {
   LoyaltyCard card = test::CreateLoyaltyCard();
-  FieldTypeSet available_types =
-      DetermineAvailableFieldTypes(/*profiles=*/{}, /*credit_cards=*/{}, {card},
-                                   /*last_unlocked_credit_card_cvc=*/u"",
-                                   /*app_locale=*/"");
+  FieldTypeSet available_types = DetermineAvailableFieldTypes(
+      /*profiles=*/{}, /*credit_cards=*/{}, /*entities=*/{}, {card},
+      /*last_unlocked_credit_card_cvc=*/u"",
+      /*app_locale=*/"");
   EXPECT_TRUE(available_types.contains(LOYALTY_MEMBERSHIP_ID));
 }
 
diff --git a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
index 612a1362..cced470 100644
--- a/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
+++ b/components/autofill/core/browser/crowdsourcing/votes_uploader.cc
@@ -206,6 +206,11 @@
           .payments_data_manager()
           .GetCreditCards();
 
+  base::span<const EntityInstance> entities;
+  if (EntityDataManager* edm = client_->GetEntityDataManager()) {
+    entities = edm->GetEntityInstances();
+  }
+
   std::vector<LoyaltyCard> loyalty_cards;
   if (ValuablesDataManager* valuables_data_manager =
           client_->GetValuablesDataManager()) {
@@ -213,12 +218,13 @@
                                    [](LoyaltyCard card) { return card; });
   }
 
-  if (profiles.empty() && credit_cards.empty() && loyalty_cards.empty()) {
+  if (profiles.empty() && credit_cards.empty() && entities.empty() &&
+      loyalty_cards.empty()) {
     return false;
   }
 
-  if (form->field_count() *
-          (profiles.size() + credit_cards.size() + loyalty_cards.size()) >=
+  if (form->field_count() * (profiles.size() + credit_cards.size() +
+                             entities.size() + loyalty_cards.size()) >=
       kMaxTypeMatchingCalls) {
     return false;
   }
@@ -243,6 +249,7 @@
       base::BindOnce(
           [](const std::vector<AutofillProfile>& profiles,
              const std::vector<CreditCard>& credit_cards,
+             const std::vector<EntityInstance>& entities,
              const std::vector<LoyaltyCard>& loyalty_cards,
              const std::u16string& last_unlocked_credit_card_cvc,
              const std::string& app_locale, bool observed_submission,
@@ -251,15 +258,16 @@
              FormStructure::FormAssociations form_associations,
              std::set<FieldGlobalId> fields_that_match_state) {
             DeterminePossibleFieldTypesForUpload(
-                profiles, credit_cards, loyalty_cards, fields_that_match_state,
-                last_unlocked_credit_card_cvc, app_locale, *form);
+                profiles, credit_cards, entities, loyalty_cards,
+                fields_that_match_state, last_unlocked_credit_card_cvc,
+                app_locale, *form);
 
             EncodeUploadRequestOptions options;
             options.encoder = std::move(randomized_encoder);
             options.form_associations = std::move(form_associations);
             options.observed_submission = observed_submission;
             options.available_field_types = DetermineAvailableFieldTypes(
-                profiles, credit_cards, loyalty_cards,
+                profiles, credit_cards, entities, loyalty_cards,
                 last_unlocked_credit_card_cvc, app_locale);
             for (auto& [field_id, format_strings] :
                  DeterminePossibleFormatStringsForUpload(form->fields())) {
@@ -275,8 +283,9 @@
           // function is called asynchronously.
           base::ToVector(profiles, [](const auto* ptr) { return *ptr; }),
           base::ToVector(credit_cards, [](const auto* ptr) { return *ptr; }),
-          std::move(loyalty_cards), last_unlocked_credit_card_cvc,
-          client_->GetAppLocale(), observed_submission, std::move(form),
+          base::ToVector(entities), std::move(loyalty_cards),
+          last_unlocked_credit_card_cvc, client_->GetAppLocale(),
+          observed_submission, std::move(form),
           RandomizedEncoder::Create(client_->GetPrefs()),
           std::move(form_associations), std::move(fields_that_match_state)),
       base::BindOnce(&VotesUploader::OnFieldTypesDetermined,
diff --git a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
index 64a4035..a4c58b5b 100644
--- a/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuable_sync_bridge_unittest.cc
@@ -187,6 +187,23 @@
   EXPECT_THAT(GetAllDataFromTable(), UnorderedElementsAre(remote1, remote2));
 }
 
+// Tests that loyalty cards with empty logo url are synced and stored.
+TEST_F(ValuableSyncBridgeTest, LoyaltyCardsWithNoProgramLogo) {
+  const LoyaltyCard remote1 = LoyaltyCard(
+      ValuableId(std::string("no_logo")), "merchant_name", "program_name",
+      GURL(), "card_number", {GURL("https://domain.example")});
+
+  EXPECT_CALL(mock_processor(), Put).Times(0);
+  EXPECT_CALL(mock_processor(), Delete).Times(0);
+  EXPECT_CALL(backend(), CommitChanges);
+  EXPECT_CALL(backend(),
+              NotifyOnAutofillChangedBySync(syncer::AUTOFILL_VALUABLE));
+
+  EXPECT_TRUE(StartSyncing({remote1}));
+
+  EXPECT_THAT(GetAllDataFromTable(), UnorderedElementsAre(remote1));
+}
+
 // Tests that `MergeFullSyncData()` replaces currently stored loyalty cards.
 TEST_F(ValuableSyncBridgeTest, MergeFullSyncData_ReplacePreviousData) {
   const LoyaltyCard remote1 = TestLoyaltyCard(kId1);
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc b/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
index 30cd6d4..5b1a60cf 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuables_sync_util.cc
@@ -59,9 +59,16 @@
 
 bool AreAutofillLoyaltyCardSpecificsValid(
     const AutofillValuableSpecifics& specifics) {
+  const auto HasEmptyOrValidProgramLogo =
+      [](const AutofillValuableSpecifics& specifics) {
+        return !specifics.loyalty_card().has_program_logo() ||
+               specifics.loyalty_card().program_logo().empty() ||
+               GURL(specifics.loyalty_card().program_logo()).is_valid();
+      };
+
   return !specifics.id().empty() && specifics.has_loyalty_card() &&
          !specifics.loyalty_card().loyalty_card_number().empty() &&
-         GURL(specifics.loyalty_card().program_logo()).is_valid();
+         HasEmptyOrValidProgramLogo(specifics);
 }
 
 AutofillValuableSpecifics TrimAutofillValuableSpecificsDataForCaching(
diff --git a/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc b/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
index c5d2c26e..dec0c4e0 100644
--- a/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
+++ b/components/autofill/core/browser/webdata/valuables/valuables_sync_util_unittest.cc
@@ -107,6 +107,12 @@
       TestLoyaltyCardSpecifics(kId1, kValidProgramLogo, /*number=*/"")));
   EXPECT_TRUE(
       AreAutofillLoyaltyCardSpecificsValid(TestLoyaltyCardSpecifics(kId1)));
+
+  sync_pb::AutofillValuableSpecifics specifics = TestLoyaltyCardSpecifics(kId1);
+  specifics.mutable_loyalty_card()->clear_program_logo();
+  EXPECT_TRUE(AreAutofillLoyaltyCardSpecificsValid(specifics));
+  EXPECT_TRUE(AreAutofillLoyaltyCardSpecificsValid(
+      TestLoyaltyCardSpecifics(kId1, /*program_logo=*/"")));
 }
 
 TEST_F(LoyaltyCardSyncUtilTest, TrimAutofillValuableSpecificsDataForCaching) {
diff --git a/components/content_settings/core/common/cookie_settings_base.cc b/components/content_settings/core/common/cookie_settings_base.cc
index 2b32299..39766d36c 100644
--- a/components/content_settings/core/common/cookie_settings_base.cc
+++ b/components/content_settings/core/common/cookie_settings_base.cc
@@ -762,13 +762,11 @@
           std::get_if<AllowAllCookies>(&choice)) {
     CHECK(IsAllowed(cookie_setting));
     CHECK(!is_third_party_request || !block_third_party_cookies ||
-              allow_cookies->mechanism != ThirdPartyCookieAllowMechanism::kNone,
-          base::NotFatalUntil::M128);
+          allow_cookies->mechanism != ThirdPartyCookieAllowMechanism::kNone);
     // `!is_third_party_request` implies that the exemption reason must be
     // kNone. (It doesn't make sense to exempt a first-party cookie from 3PCD.)
     CHECK(is_third_party_request ||
-              allow_cookies->mechanism == ThirdPartyCookieAllowMechanism::kNone,
-          base::NotFatalUntil::M128);
+          allow_cookies->mechanism == ThirdPartyCookieAllowMechanism::kNone);
 
     FireStorageAccessHistogram(
         GetStorageAccessResult(allow_cookies->mechanism));
@@ -800,9 +798,9 @@
   }
 
   if (std::holds_alternative<AllowPartitionedCookies>(choice)) {
-    CHECK(is_third_party_request, base::NotFatalUntil::M128);
-    CHECK(block_third_party_cookies, base::NotFatalUntil::M128);
-    CHECK(!is_explicit_setting, base::NotFatalUntil::M128);
+    CHECK(is_third_party_request);
+    CHECK(block_third_party_cookies);
+    CHECK(!is_explicit_setting);
 
     FireStorageAccessHistogram(StorageAccessResult::ACCESS_BLOCKED);
 
@@ -822,7 +820,7 @@
   }
 
   CHECK(std::holds_alternative<BlockAllCookies>(choice));
-  CHECK_EQ(cookie_setting, CONTENT_SETTING_BLOCK, base::NotFatalUntil::M128);
+  CHECK_EQ(cookie_setting, CONTENT_SETTING_BLOCK);
   FireStorageAccessHistogram(StorageAccessResult::ACCESS_BLOCKED);
 
   if (info) {
diff --git a/components/dom_distiller/core/distiller_page.cc b/components/dom_distiller/core/distiller_page.cc
index 0df1b5e..2ee387b8 100644
--- a/components/dom_distiller/core/distiller_page.cc
+++ b/components/dom_distiller/core/distiller_page.cc
@@ -37,9 +37,9 @@
     const GURL& gurl,
     const dom_distiller::proto::DomDistillerOptions options,
     DistillerPageCallback callback) {
-  CHECK(ready_, base::NotFatalUntil::M126);
-  CHECK(callback, base::NotFatalUntil::M127);
-  CHECK(!distiller_page_callback_, base::NotFatalUntil::M127);
+  CHECK(ready_);
+  CHECK(callback);
+  CHECK(!distiller_page_callback_);
   // It is only possible to distill one page at a time. |ready_| is reset when
   // the callback to OnDistillationDone happens.
   ready_ = false;
diff --git a/components/enterprise/watermarking/features.cc b/components/enterprise/watermarking/features.cc
index d486d51597..a89e6e5 100644
--- a/components/enterprise/watermarking/features.cc
+++ b/components/enterprise/watermarking/features.cc
@@ -10,6 +10,6 @@
 
 BASE_FEATURE(kEnablePrintWatermark,
              "EnablePrintWatermark",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 }  // namespace enterprise_watermark::features
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_ruleset_publisher.cc b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_ruleset_publisher.cc
index 96d7ad6..104d513 100644
--- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_ruleset_publisher.cc
+++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_ruleset_publisher.cc
@@ -30,9 +30,9 @@
 void FingerprintingProtectionRulesetPublisher::SendRulesetToRenderProcess(
     base::File* file,
     content::RenderProcessHost* rph) {
-  CHECK(rph, base::NotFatalUntil::M129);
-  CHECK(file, base::NotFatalUntil::M129);
-  CHECK(file->IsValid(), base::NotFatalUntil::M129);
+  CHECK(rph);
+  CHECK(file);
+  CHECK(file->IsValid());
   if (!rph->GetChannel()) {
     return;
   }
diff --git a/components/guest_contents/DIR_METADATA b/components/guest_contents/DIR_METADATA
new file mode 100644
index 0000000..4caf504
--- /dev/null
+++ b/components/guest_contents/DIR_METADATA
@@ -0,0 +1,3 @@
+buganizer_public: {
+  component_id: 1681552
+}
diff --git a/components/guest_contents/OWNERS b/components/guest_contents/OWNERS
new file mode 100644
index 0000000..32c5d76
--- /dev/null
+++ b/components/guest_contents/OWNERS
@@ -0,0 +1,7 @@
+kerenzhu@chromium.org
+tluk@chromium.org
+dayeung@chromium.org
+robliao@chromium.org
+
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/components/guest_contents/browser/BUILD.gn b/components/guest_contents/browser/BUILD.gn
new file mode 100644
index 0000000..fb91e33
--- /dev/null
+++ b/components/guest_contents/browser/BUILD.gn
@@ -0,0 +1,38 @@
+# 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("//components/guest_contents/common/buildflags.gni")
+import("//mojo/public/tools/bindings/mojom.gni")
+
+assert(enable_guest_contents)
+
+static_library("browser") {
+  sources = [
+    "guest_contents_handle.cc",
+    "guest_contents_handle.h",
+  ]
+
+  deps = [
+    "//base",
+    "//content/public/browser",
+    "//content/public/common",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+
+  sources = [
+    "guest_contents_handle_unittest.cc",
+  ]
+
+  public_deps = [
+    "//content/test:test_support",
+  ]
+
+  deps = [
+    ":browser",
+    "//base",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/guest_contents/browser/DEPS b/components/guest_contents/browser/DEPS
new file mode 100644
index 0000000..1254dcc
--- /dev/null
+++ b/components/guest_contents/browser/DEPS
@@ -0,0 +1,10 @@
+include_rules = [
+  "+content/public/browser",
+  "+content/public/common",
+]
+
+specific_include_rules = {
+  "^(test_|.*_(unit|pixel|perf)?test).*\.(cc|h)": [
+    "+content/public/test",
+  ],
+}
diff --git a/components/guest_contents/browser/guest_contents_handle.cc b/components/guest_contents/browser/guest_contents_handle.cc
new file mode 100644
index 0000000..2696d82
--- /dev/null
+++ b/components/guest_contents/browser/guest_contents_handle.cc
@@ -0,0 +1,86 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/guest_contents/browser/guest_contents_handle.h"
+
+#include <map>
+
+#include "base/no_destructor.h"
+#include "content/public/browser/unowned_inner_web_contents_client.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace guest_contents {
+
+namespace {
+
+std::map<GuestId, GuestContentsHandle*>& GetGuestContentsMap() {
+  static base::NoDestructor<std::map<GuestId, GuestContentsHandle*>>
+      guest_contents_map;
+  return *guest_contents_map;
+}
+
+}  // namespace
+
+// static
+GuestContentsHandle* GuestContentsHandle::CreateForWebContents(
+    content::WebContents* web_contents) {
+  content::WebContentsUserData<GuestContentsHandle>::CreateForWebContents(
+      web_contents);
+  return FromWebContents(web_contents);
+}
+
+// static
+GuestContentsHandle* GuestContentsHandle::FromID(GuestId id) {
+  return GetGuestContentsMap().contains(id) ? GetGuestContentsMap()[id]
+                                            : nullptr;
+}
+
+GuestContentsHandle::GuestContentsHandle(content::WebContents* web_contents)
+    : content::WebContentsUserData<GuestContentsHandle>(*web_contents),
+      content::WebContentsObserver(web_contents),
+      id_(GetNextId()) {
+  CHECK(!GetGuestContentsMap().contains(id_));
+  GetGuestContentsMap()[id_] = this;
+}
+
+GuestContentsHandle::~GuestContentsHandle() {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  GetGuestContentsMap().erase(id_);
+}
+
+void GuestContentsHandle::AttachToOuterWebContents(
+    content::RenderFrameHost* outer_delegate_frame) {
+  content::WebContents* outer_web_contents =
+      content::WebContents::FromRenderFrameHost(outer_delegate_frame);
+  CHECK(outer_web_contents);
+  outer_web_contents->AttachUnownedInnerWebContents(
+      content::UnownedInnerWebContentsClient::GetPassKey(), web_contents(),
+      outer_delegate_frame);
+}
+
+void GuestContentsHandle::DetachFromOuterWebContents() {
+  content::WebContents* outer_web_contents =
+      web_contents()->GetOuterWebContents();
+  if (!outer_web_contents) {
+    return;
+  }
+
+  outer_web_contents->DetachUnownedInnerWebContents(
+      content::UnownedInnerWebContentsClient::GetPassKey(), web_contents());
+}
+
+void GuestContentsHandle::WebContentsDestroyed() {
+  DetachFromOuterWebContents();
+}
+
+GuestId GuestContentsHandle::GetNextId() {
+  static GuestId next_id = 0;
+  return next_id++;
+}
+
+WEB_CONTENTS_USER_DATA_KEY_IMPL(GuestContentsHandle);
+
+}  // namespace guest_contents
diff --git a/components/guest_contents/browser/guest_contents_handle.h b/components/guest_contents/browser/guest_contents_handle.h
new file mode 100644
index 0000000..0a871156
--- /dev/null
+++ b/components/guest_contents/browser/guest_contents_handle.h
@@ -0,0 +1,59 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_GUEST_CONTENTS_BROWSER_GUEST_CONTENTS_HANDLE_H_
+#define COMPONENTS_GUEST_CONTENTS_BROWSER_GUEST_CONTENTS_HANDLE_H_
+
+#include "base/sequence_checker.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_observer.h"
+#include "content/public/browser/web_contents_user_data.h"
+
+namespace guest_contents {
+
+using GuestId = int;
+
+// A handle for a guest WebContents, uniquely identified by a GuestId. It
+// provides APIs for attaching and detaching the guest WebContents from the
+// outer WebContents. It has the same lifetime as the guest WebContents.
+class GuestContentsHandle
+    : public content::WebContentsUserData<GuestContentsHandle>,
+      public content::WebContentsObserver {
+ public:
+  ~GuestContentsHandle() override;
+
+  // Creates a handle for the given `web_contents`.
+  static GuestContentsHandle* CreateForWebContents(
+      content::WebContents* web_contents);
+
+  static GuestContentsHandle* FromID(GuestId id);
+
+  // Returns the unique ID of this guest. This ID is automatically assigned
+  // when the GuestContentsHandle is created.
+  GuestId id() { return id_; }
+
+  void AttachToOuterWebContents(
+      content::RenderFrameHost* outer_delegate_frame);
+
+  void DetachFromOuterWebContents();
+
+ private:
+  friend content::WebContentsUserData<GuestContentsHandle>;
+  WEB_CONTENTS_USER_DATA_KEY_DECL();
+
+  explicit GuestContentsHandle(content::WebContents* web_contents);
+
+  // content::WebContentsObserver:
+  void WebContentsDestroyed() override;
+
+  GuestId GetNextId();
+
+  GuestId id_;
+
+  SEQUENCE_CHECKER(sequence_checker_);
+};
+
+}  // namespace guest_contents
+
+#endif  // COMPONENTS_GUEST_CONTENTS_BROWSER_GUEST_CONTENTS_HANDLE_H_
diff --git a/components/guest_contents/browser/guest_contents_handle_unittest.cc b/components/guest_contents/browser/guest_contents_handle_unittest.cc
new file mode 100644
index 0000000..af13a2d
--- /dev/null
+++ b/components/guest_contents/browser/guest_contents_handle_unittest.cc
@@ -0,0 +1,147 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/guest_contents/browser/guest_contents_handle.h"
+
+#include "base/location.h"
+#include "base/test/scoped_feature_list.h"
+#include "content/public/common/content_features.h"
+#include "content/public/test/test_renderer_host.h"
+
+namespace guest_contents {
+
+class GuestContentsHandleTest : public content::RenderViewHostTestHarness {
+ public:
+  void SetUp() override {
+    content::RenderViewHostTestHarness::SetUp();
+    guest_web_contents_ = CreateTestWebContents();
+    content::RenderFrameHostTester::For(
+        guest_web_contents_->GetPrimaryMainFrame())
+        ->InitializeRenderFrameIfNeeded();
+    outer_web_contents_ = CreateTestWebContents();
+    content::RenderFrameHostTester* outer_rfh_tester =
+        content::RenderFrameHostTester::For(
+            outer_web_contents_->GetPrimaryMainFrame());
+    outer_rfh_tester->InitializeRenderFrameIfNeeded();
+    outer_delegate_rfh_ = outer_rfh_tester->AppendChild("outer_delegate");
+    ASSERT_TRUE(outer_delegate_rfh_);
+  }
+
+  void TearDown() override {
+    outer_delegate_rfh_ = nullptr;
+    guest_web_contents_.reset();
+    outer_web_contents_.reset();
+    content::RenderViewHostTestHarness::TearDown();
+  }
+
+  std::unique_ptr<content::WebContents>& guest_web_contents() {
+    return guest_web_contents_;
+  }
+  std::unique_ptr<content::WebContents>& outer_web_contents() {
+    return outer_web_contents_;
+  }
+  content::RenderFrameHost& outer_delegate_rfh() {
+    return *outer_delegate_rfh_;
+  }
+
+ protected:
+  std::unique_ptr<content::WebContents> guest_web_contents_;
+  std::unique_ptr<content::WebContents> outer_web_contents_;
+  raw_ptr<content::RenderFrameHost> outer_delegate_rfh_;
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+    features::kAttachUnownedInnerWebContents};
+};
+
+TEST_F(GuestContentsHandleTest, CreateAndGetById) {
+  GuestContentsHandle* handle =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents().get());
+  ASSERT_TRUE(handle);
+  EXPECT_EQ(handle,
+            GuestContentsHandle::FromWebContents(guest_web_contents().get()));
+
+  GuestId id = handle->id();
+  EXPECT_EQ(handle, GuestContentsHandle::FromID(id));
+
+  // Test invalid ID
+  EXPECT_EQ(nullptr, GuestContentsHandle::FromID(id + 1));
+  EXPECT_EQ(nullptr, GuestContentsHandle::FromID(-1));
+
+  // Destroy the WebContents, which should destroy the handle
+  guest_web_contents().reset();
+
+  // Handle should no longer be findable by ID
+  EXPECT_EQ(nullptr, GuestContentsHandle::FromID(id));
+}
+
+TEST_F(GuestContentsHandleTest, UniqueIds) {
+  GuestContentsHandle* handle1 =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents().get());
+  ASSERT_TRUE(handle1);
+
+  // Create a second guest WebContents and handle
+  std::unique_ptr<content::WebContents> guest_web_contents2 =
+      CreateTestWebContents();
+  GuestContentsHandle* handle2 =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents2.get());
+  ASSERT_TRUE(handle2);
+
+  EXPECT_NE(handle1->id(), handle2->id());
+
+  // Clean up second guest
+  guest_web_contents2.reset();
+  // First handle should still exist
+  EXPECT_EQ(handle1, GuestContentsHandle::FromID(handle1->id()));
+}
+
+TEST_F(GuestContentsHandleTest, AttachAndDetach) {
+  GuestContentsHandle* handle =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents().get());
+  ASSERT_TRUE(handle);
+
+  handle->AttachToOuterWebContents(&outer_delegate_rfh());
+  EXPECT_EQ(guest_web_contents()->GetOuterWebContents(),
+            outer_web_contents().get());
+  EXPECT_TRUE(base::Contains(outer_web_contents()->GetInnerWebContents(),
+                             guest_web_contents().get()));
+
+  handle->DetachFromOuterWebContents();
+  EXPECT_EQ(nullptr, guest_web_contents()->GetOuterWebContents());
+  EXPECT_TRUE(outer_web_contents()->GetInnerWebContents().empty());
+}
+
+TEST_F(GuestContentsHandleTest, DestroyGuestContents) {
+  GuestContentsHandle* handle =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents().get());
+  ASSERT_TRUE(handle);
+
+  handle->AttachToOuterWebContents(&outer_delegate_rfh());
+  EXPECT_EQ(guest_web_contents()->GetOuterWebContents(),
+            outer_web_contents().get());
+  EXPECT_TRUE(base::Contains(outer_web_contents()->GetInnerWebContents(),
+            guest_web_contents().get()));
+
+  // Destroy the guest WebContents while it is still attached to the outer
+  // WebContents.
+  guest_web_contents().reset();
+  EXPECT_TRUE(outer_web_contents()->GetInnerWebContents().empty());
+}
+
+TEST_F(GuestContentsHandleTest, DestroyOuterWebContents) {
+  GuestContentsHandle* handle =
+      GuestContentsHandle::CreateForWebContents(guest_web_contents().get());
+  ASSERT_TRUE(handle);
+
+  handle->AttachToOuterWebContents(&outer_delegate_rfh());
+  EXPECT_EQ(guest_web_contents()->GetOuterWebContents(),
+            outer_web_contents().get());
+
+  // Destroy the outer WebContents while it still has a guest WebContents.
+  outer_delegate_rfh_ = nullptr;
+  outer_web_contents().reset();
+  EXPECT_EQ(nullptr, guest_web_contents()->GetOuterWebContents());
+}
+
+}  // namespace guest_contents
diff --git a/components/guest_contents/common/BUILD.gn b/components/guest_contents/common/BUILD.gn
new file mode 100644
index 0000000..aa1a8a3
--- /dev/null
+++ b/components/guest_contents/common/BUILD.gn
@@ -0,0 +1,10 @@
+# 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/buildflag_header.gni")
+
+buildflag_header("buildflags") {
+  header = "buildflags.h"
+  flags = [ "ENABLE_GUEST_CONTENTS=$enable_guest_contents" ]
+}
diff --git a/components/guest_contents/common/buildflags.gni b/components/guest_contents/common/buildflags.gni
new file mode 100644
index 0000000..3b3a29e
--- /dev/null
+++ b/components/guest_contents/common/buildflags.gni
@@ -0,0 +1,11 @@
+# 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/config/cast.gni")
+import("//build/config/chrome_build.gni")
+
+declare_args() {
+  # `enable_guest_contents` controls whether the guest_contents is compiled.
+  enable_guest_contents = !is_android && !is_ios && !is_castos
+}
diff --git a/components/history/core/browser/history_backend_unittest.cc b/components/history/core/browser/history_backend_unittest.cc
index 26442f9..928442d 100644
--- a/components/history/core/browser/history_backend_unittest.cc
+++ b/components/history/core/browser/history_backend_unittest.cc
@@ -61,6 +61,7 @@
 #include "components/sync/base/features.h"
 #include "sql/sqlite_result_code_values.h"
 #include "sql/test/test_helpers.h"
+#include "sql/transaction.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/skia/include/core/SkBitmap.h"
@@ -233,6 +234,7 @@
   using HistoryBackend::expirer_;
   using HistoryBackend::favicon_backend_;
   using HistoryBackend::recent_redirects_;
+  using HistoryBackend::singleton_transaction_;
 
   VisitTracker& visit_tracker() { return tracker_; }
 
@@ -3277,6 +3279,22 @@
                                  /*user_initiated*/ true);
 }
 
+// Tests for https://crbug.com/420369590.
+TEST_F(HistoryBackendTest, DatabaseErrorOnClosedDatabase) {
+  // Clear the pending transaction to avoid DCHECKs to trigger. This is required
+  // since we are closing the raw sqlite database.
+  backend_->singleton_transaction_.reset();
+
+  // Close the database. This is simulating a case where the open failed but
+  // the database is not poisoned.
+  backend_->db()->GetDBForTesting().Close();
+
+  // Retrieve the error diagnostic information.
+  std::string result = backend_->db()->GetDiagnosticInfo(
+      static_cast<int>(sql::SqliteResultCode::kCorrupt), nullptr, nullptr);
+  EXPECT_EQ(result, "Database is not opened.");
+}
+
 // Tests that a typed navigation which results in a redirect from HTTP to HTTPS
 // will cause the HTTPS URL to accrue the typed count, and the HTTP URL to not.
 TEST_F(HistoryBackendTest, RedirectScoring) {
diff --git a/components/history/core/browser/history_database.cc b/components/history/core/browser/history_database.cc
index 89a1da12..0d0ef1a 100644
--- a/components/history/core/browser/history_database.cc
+++ b/components/history/core/browser/history_database.cc
@@ -427,6 +427,9 @@
     int extended_error,
     sql::Statement* statement,
     sql::DatabaseDiagnostics* diagnostics) {
+  if (!db_.is_open()) {
+    return "Database is not opened.";
+  }
   return db_.GetDiagnosticInfo(extended_error, statement, diagnostics);
 }
 
diff --git a/components/optimization_guide/core/model_execution/model_execution_features_controller.cc b/components/optimization_guide/core/model_execution/model_execution_features_controller.cc
index 0af64f0..ab2197b2 100644
--- a/components/optimization_guide/core/model_execution/model_execution_features_controller.cc
+++ b/components/optimization_guide/core/model_execution/model_execution_features_controller.cc
@@ -415,10 +415,9 @@
   // When the feature is enabled, check the user is valid to enable the
   // feature.
   CHECK(!is_enabled ||
-            GetCurrentUserValidityResult(feature,
-                                         /*skip_enterprise_check=*/false) ==
-                ModelExecutionFeaturesController::UserValidityResult::kValid,
-        base::NotFatalUntil::M125);
+        GetCurrentUserValidityResult(feature,
+                                     /*skip_enterprise_check=*/false) ==
+            ModelExecutionFeaturesController::UserValidityResult::kValid);
 
   if (pref_value != prefs::FeatureOptInState::kNotInitialized) {
     base::UmaHistogramBoolean(
diff --git a/components/payments/core/payment_manifest_downloader.cc b/components/payments/core/payment_manifest_downloader.cc
index 340d4f7f..af2de5f 100644
--- a/components/payments/core/payment_manifest_downloader.cc
+++ b/components/payments/core/payment_manifest_downloader.cc
@@ -227,20 +227,18 @@
 
 void PaymentManifestDownloader::OnURLLoaderComplete(
     network::SimpleURLLoader* url_loader,
-    std::unique_ptr<std::string> response_body) {
+    std::optional<std::string> response_body) {
   scoped_refptr<net::HttpResponseHeaders> headers;
   if (url_loader->ResponseInfo()) {
     headers = url_loader->ResponseInfo()->headers;
   }
 
-  std::string response_body_str;
-  if (response_body.get()) {
-    response_body_str = std::move(*response_body);
+  if (!response_body.has_value()) {
+    response_body.emplace();
   }
 
   OnURLLoaderCompleteInternal(url_loader, url_loader->GetFinalURL(),
-                              response_body_str, headers,
-                              url_loader->NetError());
+                              *response_body, headers, url_loader->NetError());
 }
 
 void PaymentManifestDownloader::OnURLLoaderCompleteInternal(
diff --git a/components/payments/core/payment_manifest_downloader.h b/components/payments/core/payment_manifest_downloader.h
index 9e12937..f0b6dac9 100644
--- a/components/payments/core/payment_manifest_downloader.h
+++ b/components/payments/core/payment_manifest_downloader.h
@@ -174,7 +174,7 @@
 
   // Called by SimpleURLLoader on completion.
   void OnURLLoaderComplete(network::SimpleURLLoader* url_loader,
-                           std::unique_ptr<std::string> response_body);
+                           std::optional<std::string> response_body);
 
   // Internally called by OnURLLoaderComplete, exposed to ease unit tests.
   void OnURLLoaderCompleteInternal(
diff --git a/components/persistent_cache/BUILD.gn b/components/persistent_cache/BUILD.gn
index 2e0a2e8b..d9205d22 100644
--- a/components/persistent_cache/BUILD.gn
+++ b/components/persistent_cache/BUILD.gn
@@ -47,16 +47,35 @@
   ]
 }
 
+static_library("test_support") {
+  testonly = true
+
+  sources = [
+    "mock/mock_backend_impl.cc",
+    "mock/mock_backend_impl.h",
+    "mock/mock_entry_impl.cc",
+    "mock/mock_entry_impl.h",
+    "sqlite/test_utils.cc",
+    "sqlite/test_utils.h",
+  ]
+
+  deps = [
+    ":persistent_cache",
+    "//base",
+    "//base/test:test_support",
+    "//sql",
+    "//testing/gmock",
+    "//testing/gtest",
+    "//third_party/sqlite",
+  ]
+}
+
 source_set("unit_tests") {
   testonly = true
 
   sources = [
     "backend_params_manager_unittest.cc",
     "entry_unittest.cc",
-    "mock/mock_backend_impl.cc",
-    "mock/mock_backend_impl.h",
-    "mock/mock_entry_impl.cc",
-    "mock/mock_entry_impl.h",
     "sqlite/sqlite_entry_unittest.cc",
   ]
 
@@ -64,14 +83,13 @@
   if (!is_fuchsia) {
     sources += [
       "persistent_cache_unittest.cc",
-      "sqlite/test_utils.cc",
-      "sqlite/test_utils.h",
       "sqlite/vfs/sqlite_sandboxed_vfs_unittest.cc",
     ]
   }
 
   deps = [
     ":persistent_cache",
+    ":test_support",
     "//base",
     "//base/test:test_support",
     "//sql",
diff --git a/components/persistent_cache/persistent_cache_perftest.cc b/components/persistent_cache/persistent_cache_perftest.cc
new file mode 100644
index 0000000..e131b3c
--- /dev/null
+++ b/components/persistent_cache/persistent_cache_perftest.cc
@@ -0,0 +1,50 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/persistent_cache/persistent_cache.h"
+
+#include "base/time/time.h"
+#include "base/timer/elapsed_timer.h"
+#include "build/buildflag.h"
+#include "components/persistent_cache/entry.h"
+#include "components/persistent_cache/sqlite/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/perf/perf_result_reporter.h"
+
+namespace persistent_cache {
+
+using PersistentCachePerftest = testing::Test;
+
+#if !BUILDFLAG(IS_FUCHSIA)
+
+TEST_F(PersistentCachePerftest, OpenClose) {
+  test_utils::TestHelper provider;
+  BackendParams backend_params =
+      provider.CreateBackendFilesAndBuildParams(BackendType::kSqlite);
+  auto persistent_cache = PersistentCache::Open(backend_params.Copy());
+  ASSERT_TRUE(persistent_cache);
+
+  // Ensures there are entries in the cache.
+  const char* kKey = "foo";
+  persistent_cache->Insert(kKey, base::byte_span_from_cstring("1"));
+  auto entry = persistent_cache->Find(kKey);
+  ASSERT_TRUE(entry);
+
+  base::ElapsedTimer timer;
+  const int kAmountOfIteration = 16 * 1024;
+  for (size_t i = 0; i < kAmountOfIteration; ++i) {
+    auto persistent_cache_under_test =
+        PersistentCache::Open(backend_params.Copy());
+  }
+
+  perf_test::PerfResultReporter reporter("PersistentCache", "OpenClose");
+  reporter.RegisterImportantMetric(".wall_time", "us");
+  reporter.AddResult(".wall_time",
+                     static_cast<size_t>(timer.Elapsed().InMicroseconds() /
+                                         kAmountOfIteration));
+}
+
+#endif  // !BUILDFLAG(IS_FUCHSIA)
+
+}  // namespace persistent_cache
diff --git a/components/policy/test_support/BUILD.gn b/components/policy/test_support/BUILD.gn
index 50009316..e9a5cf4 100644
--- a/components/policy/test_support/BUILD.gn
+++ b/components/policy/test_support/BUILD.gn
@@ -22,8 +22,6 @@
     "request_handler_for_api_authorization.h",
     "request_handler_for_auto_enrollment.cc",
     "request_handler_for_auto_enrollment.h",
-    "request_handler_for_browser_public_key_upload.cc",
-    "request_handler_for_browser_public_key_upload.h",
     "request_handler_for_cert_upload.cc",
     "request_handler_for_cert_upload.h",
     "request_handler_for_check_android_management.cc",
@@ -143,7 +141,6 @@
     "remote_commands_state_unittest.cc",
     "request_handler_for_api_authorization_unittest.cc",
     "request_handler_for_auto_enrollment_unittest.cc",
-    "request_handler_for_browser_public_key_upload_unittest.cc",
     "request_handler_for_cert_upload_unittest.cc",
     "request_handler_for_check_android_management_unittest.cc",
     "request_handler_for_check_user_account_unittest.cc",
diff --git a/components/policy/test_support/embedded_policy_test_server.cc b/components/policy/test_support/embedded_policy_test_server.cc
index 9ee7b46..b15cd41 100644
--- a/components/policy/test_support/embedded_policy_test_server.cc
+++ b/components/policy/test_support/embedded_policy_test_server.cc
@@ -19,7 +19,6 @@
 #include "components/policy/test_support/policy_storage.h"
 #include "components/policy/test_support/request_handler_for_api_authorization.h"
 #include "components/policy/test_support/request_handler_for_auto_enrollment.h"
-#include "components/policy/test_support/request_handler_for_browser_public_key_upload.h"
 #include "components/policy/test_support/request_handler_for_cert_upload.h"
 #include "components/policy/test_support/request_handler_for_check_android_management.h"
 #include "components/policy/test_support/request_handler_for_chrome_desktop_report.h"
@@ -112,8 +111,6 @@
   ResetServerState();
   RegisterHandler(std::make_unique<RequestHandlerForApiAuthorization>(this));
   RegisterHandler(std::make_unique<RequestHandlerForAutoEnrollment>(this));
-  RegisterHandler(
-      std::make_unique<RequestHandlerForBrowserPublicKeyUpload>(this));
   RegisterHandler(std::make_unique<RequestHandlerForCertUpload>(this));
   RegisterHandler(
       std::make_unique<RequestHandlerForCheckAndroidManagement>(this));
diff --git a/components/policy/test_support/embedded_policy_test_server_test_base.cc b/components/policy/test_support/embedded_policy_test_server_test_base.cc
index 4b0085a..88d76e15 100644
--- a/components/policy/test_support/embedded_policy_test_server_test_base.cc
+++ b/components/policy/test_support/embedded_policy_test_server_test_base.cc
@@ -66,11 +66,6 @@
   AddQueryParam(dm_protocol::kParamDeviceID, device_id);
 }
 
-void EmbeddedPolicyTestServerTestBase::SetProfileIdParam(
-    const std::string& profile_id) {
-  AddQueryParam(dm_protocol::kParamProfileID, profile_id);
-}
-
 void EmbeddedPolicyTestServerTestBase::SetDeviceType(
     const std::string& device_type) {
   AddQueryParam(dm_protocol::kParamDeviceType, device_type);
diff --git a/components/policy/test_support/embedded_policy_test_server_test_base.h b/components/policy/test_support/embedded_policy_test_server_test_base.h
index c659e0a..604bb67 100644
--- a/components/policy/test_support/embedded_policy_test_server_test_base.h
+++ b/components/policy/test_support/embedded_policy_test_server_test_base.h
@@ -44,7 +44,6 @@
   void SetMethod(const std::string& method);
   void SetAppType(const std::string& app_type);
   void SetDeviceIdParam(const std::string& device_id);
-  void SetProfileIdParam(const std::string& profile_id);
   void SetDeviceType(const std::string& device_type);
   void SetOAuthToken(const std::string& oauth_token);
   void SetRequestTypeParam(const std::string& request_type);
diff --git a/components/policy/test_support/request_handler_for_browser_public_key_upload.cc b/components/policy/test_support/request_handler_for_browser_public_key_upload.cc
deleted file mode 100644
index c2a0609..0000000
--- a/components/policy/test_support/request_handler_for_browser_public_key_upload.cc
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/policy/test_support/request_handler_for_browser_public_key_upload.h"
-
-#include "components/policy/core/common/cloud/cloud_policy_constants.h"
-#include "components/policy/proto/device_management_backend.pb.h"
-#include "components/policy/test_support/test_server_helpers.h"
-#include "net/http/http_status_code.h"
-#include "net/test/embedded_test_server/http_request.h"
-#include "net/test/embedded_test_server/http_response.h"
-
-using net::test_server::HttpRequest;
-using net::test_server::HttpResponse;
-
-namespace em = enterprise_management;
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-
-namespace policy {
-
-namespace {
-
-// Generates a self-signed issuer_cert_builder certificate with
-// `issuer_common_name`. Then issues a certificate for the public key `spki_der`
-// (DER-encoded X.509 SubjectPublicKeyInfo) with SubjectCommonName
-// `subject_common_name`. Returns a PEM-encoded representation of that
-// certificate.
-std::string GeneratePEMEncodedCertificate(
-    const std::string& public_key,
-    const std::string& issuer_common_name,
-    const std::string& subject_common_name) {
-  std::vector<uint8_t> pk(public_key.begin(), public_key.end());
-  base::span<const uint8_t> spki_der(pk);
-  net::CertBuilder issuer_cert_builder(/*orig_cert=*/nullptr,
-                                       /*issuer=*/nullptr);
-  issuer_cert_builder.SetSubjectCommonName(issuer_common_name);
-  issuer_cert_builder.GenerateRSAKey();
-  std::unique_ptr<net::CertBuilder> cert_builder =
-      net::CertBuilder::FromSubjectPublicKeyInfo(spki_der,
-                                                 &issuer_cert_builder);
-  cert_builder->SetSignatureAlgorithm(
-      bssl::SignatureAlgorithm::kRsaPkcs1Sha256);
-  cert_builder->SetValidity(base::Time::Now(),
-                            base::Time::Now() + base::Days(30));
-  cert_builder->SetSubjectCommonName(subject_common_name);
-
-  return cert_builder->GetPEM();
-}
-
-}  // namespace
-
-RequestHandlerForBrowserPublicKeyUpload::
-    RequestHandlerForBrowserPublicKeyUpload(EmbeddedPolicyTestServer* parent)
-    : EmbeddedPolicyTestServer::RequestHandler(parent) {}
-
-RequestHandlerForBrowserPublicKeyUpload::
-    ~RequestHandlerForBrowserPublicKeyUpload() = default;
-
-std::string RequestHandlerForBrowserPublicKeyUpload::RequestType() {
-  return dm_protocol::kValueBrowserUploadPublicKey;
-}
-
-std::unique_ptr<HttpResponse>
-RequestHandlerForBrowserPublicKeyUpload::HandleRequest(
-    const HttpRequest& request) {
-  // Make sure dm token is present.
-  std::string dm_token;
-  if (!GetDeviceTokenFromRequest(request, &dm_token)) {
-    return CreateHttpResponse(net::HTTP_UNAUTHORIZED, "Missing dm token");
-  }
-
-  // Verify if Profile or Browser.
-  std::string profile_id;
-  bool is_profile = GetProfileIdFromRequest(request, &profile_id);
-
-  em::DeviceManagementRequest device_management_request;
-  device_management_request.ParseFromString(request.content);
-  const em::BrowserPublicKeyUploadRequest& key_upload_request =
-      device_management_request.browser_public_key_upload_request();
-
-  if (key_upload_request.public_key().empty()) {
-    return CreateHttpResponse(net::HTTP_BAD_REQUEST, "Missing public key");
-  }
-
-  if (key_upload_request.key_trust_level() ==
-      BPKUR::KEY_TRUST_LEVEL_UNSPECIFIED) {
-    return CreateHttpResponse(net::HTTP_BAD_REQUEST,
-                              "Missing public key trust level");
-  }
-
-  if (key_upload_request.key_type() == BPKUR::KEY_TYPE_UNSPECIFIED) {
-    return CreateHttpResponse(net::HTTP_BAD_REQUEST, "Missing public key type");
-  }
-
-  em::DeviceManagementResponse device_management_response;
-  if (key_upload_request.provision_certificate()) {
-    device_management_response.mutable_browser_public_key_upload_response()
-        ->set_pem_encoded_certificate(GeneratePEMEncodedCertificate(
-            key_upload_request.public_key(),
-            /*issuer_common_name=*/
-            is_profile ? "Profile Root CA" : "Browser Root CA",
-            /*subject_common_name=*/"Test Client Cert"));
-  }
-
-  device_management_response.mutable_browser_public_key_upload_response()
-      ->set_response_code(em::BrowserPublicKeyUploadResponse::SUCCESS);
-
-  return CreateHttpResponse(net::HTTP_OK, device_management_response);
-}
-
-}  // namespace policy
diff --git a/components/policy/test_support/request_handler_for_browser_public_key_upload.h b/components/policy/test_support/request_handler_for_browser_public_key_upload.h
deleted file mode 100644
index c97d9b0..0000000
--- a/components/policy/test_support/request_handler_for_browser_public_key_upload.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef COMPONENTS_POLICY_TEST_SUPPORT_REQUEST_HANDLER_FOR_BROWSER_PUBLIC_KEY_UPLOAD_H_
-#define COMPONENTS_POLICY_TEST_SUPPORT_REQUEST_HANDLER_FOR_BROWSER_PUBLIC_KEY_UPLOAD_H_
-
-#include "components/policy/test_support/embedded_policy_test_server.h"
-
-namespace policy {
-
-class RequestHandlerForBrowserPublicKeyUpload
-    : public EmbeddedPolicyTestServer::RequestHandler {
- public:
-  explicit RequestHandlerForBrowserPublicKeyUpload(
-      EmbeddedPolicyTestServer* parent);
-
-  RequestHandlerForBrowserPublicKeyUpload(
-      RequestHandlerForBrowserPublicKeyUpload&& handler) = delete;
-  RequestHandlerForBrowserPublicKeyUpload& operator=(
-      RequestHandlerForBrowserPublicKeyUpload&& handler) = delete;
-
-  ~RequestHandlerForBrowserPublicKeyUpload() override;
-
-  // EmbeddedPolicyTestServer::RequestHandler:
-  std::string RequestType() override;
-  std::unique_ptr<net::test_server::HttpResponse> HandleRequest(
-      const net::test_server::HttpRequest& request) override;
-};
-
-}  // namespace policy
-
-#endif  // COMPONENTS_POLICY_TEST_SUPPORT_REQUEST_HANDLER_FOR_BROWSER_PUBLIC_KEY_UPLOAD_H_
diff --git a/components/policy/test_support/request_handler_for_browser_public_key_upload_unittest.cc b/components/policy/test_support/request_handler_for_browser_public_key_upload_unittest.cc
deleted file mode 100644
index 3c2266c..0000000
--- a/components/policy/test_support/request_handler_for_browser_public_key_upload_unittest.cc
+++ /dev/null
@@ -1,217 +0,0 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "components/policy/test_support/request_handler_for_browser_public_key_upload.h"
-
-#include <optional>
-#include <utility>
-
-#include "base/base64.h"
-#include "base/containers/span.h"
-#include "components/policy/core/common/cloud/cloud_policy_constants.h"
-#include "components/policy/proto/device_management_backend.pb.h"
-#include "components/policy/test_support/embedded_policy_test_server_test_base.h"
-#include "components/policy/test_support/policy_storage.h"
-#include "crypto/keypair.h"
-#include "net/cert/x509_certificate.h"
-#include "net/http/http_status_code.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using BPKUR = enterprise_management::BrowserPublicKeyUploadRequest;
-
-namespace policy {
-
-namespace {
-
-constexpr char kDeviceId[] = "fake_device_id";
-constexpr char kProfileId[] = "fake_profile_id";
-constexpr char kDmToken[] = "dm_token";
-
-// Base64-encoded EC private key PKCS #8 PrivateKeyInfo block.
-constexpr char kEncodedPrivateKey[] =
-    "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgzsLi0tbAG43E2lR6vwq4t+"
-    "mDmBRGXhkbco2G2v5+0gKhRANCAAQ8YD0im5qm9EF6c1R/Yn9b/"
-    "vnWWcVnQwc+rk5VziUjnoRGGyBwC52+5w2R7u68SkkN2BTRGZ/RQ/bop4Mpwa/O";
-
-std::optional<crypto::keypair::PrivateKey> LoadPrivateKey() {
-  auto decoded_key = base::Base64Decode(kEncodedPrivateKey);
-  if (!decoded_key) {
-    return std::nullopt;
-  }
-
-  return crypto::keypair::PrivateKey::FromPrivateKeyInfo(decoded_key.value());
-}
-
-void VerifyIssuerCommonName(const std::string& pem_encoded_certificate,
-                            std::string_view expected_issuer_name) {
-  net::CertificateList certs =
-      net::X509Certificate::CreateCertificateListFromBytes(
-          base::as_byte_span(pem_encoded_certificate),
-          net::X509Certificate::FORMAT_AUTO);
-  ASSERT_FALSE(certs.empty());
-  ASSERT_TRUE(certs[0]);
-  EXPECT_EQ(certs[0]->issuer().common_name, expected_issuer_name);
-}
-
-}  // namespace
-
-class RequestHandlerForBrowserPublicKeyUploadTest
-    : public EmbeddedPolicyTestServerTestBase {
- public:
-  RequestHandlerForBrowserPublicKeyUploadTest() = default;
-  ~RequestHandlerForBrowserPublicKeyUploadTest() override = default;
-
-  void SetUp() override {
-    EmbeddedPolicyTestServerTestBase::SetUp();
-
-    SetRequestTypeParam(dm_protocol::kValueBrowserUploadPublicKey);
-    SetAppType(dm_protocol::kValueAppType);
-    SetDeviceType(dm_protocol::kValueDeviceType);
-    SetDeviceIdParam(kDeviceId);
-    SetDeviceTokenHeader(kDmToken);
-  }
-};
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, HandleBrowserKeyUpload) {
-  // Can set a fake public key when not requiring a cert.
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key("test_key");
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_HW_KEY);
-  request->set_key_type(BPKUR::RSA_KEY);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_OK);
-  ASSERT_TRUE(HasResponseBody());
-  auto response = GetDeviceManagementResponse();
-  EXPECT_TRUE(response.has_browser_public_key_upload_response());
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, HandleProfileKeyUpload) {
-  SetProfileIdParam(kProfileId);
-
-  // Can set a fake public key when not requiring a cert.
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key("test_key");
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_HW_KEY);
-  request->set_key_type(BPKUR::RSA_KEY);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_OK);
-  ASSERT_TRUE(HasResponseBody());
-  auto response = GetDeviceManagementResponse();
-  EXPECT_TRUE(response.has_browser_public_key_upload_response());
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, HandleBrowserCertRequest) {
-  auto ec_private_key = LoadPrivateKey();
-  ASSERT_TRUE(ec_private_key);
-  auto public_key = ec_private_key->ToSubjectPublicKeyInfo();
-
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key(public_key.data(), public_key.size());
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_OS_KEY);
-  request->set_key_type(BPKUR::EC_KEY);
-  request->set_provision_certificate(true);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_OK);
-  ASSERT_TRUE(HasResponseBody());
-  auto response = GetDeviceManagementResponse();
-  ASSERT_TRUE(response.has_browser_public_key_upload_response());
-
-  auto& upload_response = response.browser_public_key_upload_response();
-  ASSERT_TRUE(upload_response.has_pem_encoded_certificate());
-  VerifyIssuerCommonName(upload_response.pem_encoded_certificate(),
-                         "Browser Root CA");
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, HandleProfileCertRequest) {
-  auto ec_private_key = LoadPrivateKey();
-  ASSERT_TRUE(ec_private_key);
-  auto public_key = ec_private_key->ToSubjectPublicKeyInfo();
-
-  SetProfileIdParam(kProfileId);
-
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key(public_key.data(), public_key.size());
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_OS_KEY);
-  request->set_key_type(BPKUR::EC_KEY);
-  request->set_provision_certificate(true);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_OK);
-  ASSERT_TRUE(HasResponseBody());
-  auto response = GetDeviceManagementResponse();
-  ASSERT_TRUE(response.has_browser_public_key_upload_response());
-
-  auto& upload_response = response.browser_public_key_upload_response();
-  ASSERT_TRUE(upload_response.has_pem_encoded_certificate());
-  VerifyIssuerCommonName(upload_response.pem_encoded_certificate(),
-                         "Profile Root CA");
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest,
-       FailWithMissingPublicKeyData) {
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_HW_KEY);
-  request->set_key_type(BPKUR::RSA_KEY);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_BAD_REQUEST);
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, FailWithMissingTrustLevel) {
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key("test_key");
-  request->set_key_type(BPKUR::RSA_KEY);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_BAD_REQUEST);
-}
-
-TEST_F(RequestHandlerForBrowserPublicKeyUploadTest, FailWithMissingKeyType) {
-  enterprise_management::DeviceManagementRequest device_management_request;
-  auto* request =
-      device_management_request.mutable_browser_public_key_upload_request();
-  request->set_public_key("test_key");
-  request->set_key_trust_level(BPKUR::CHROME_BROWSER_HW_KEY);
-
-  SetPayload(device_management_request);
-
-  StartRequestAndWait();
-
-  EXPECT_EQ(GetResponseCode(), net::HTTP_BAD_REQUEST);
-}
-
-}  // namespace policy
diff --git a/components/policy/test_support/test_server_helpers.cc b/components/policy/test_support/test_server_helpers.cc
index 09dd290..c65ad8c 100644
--- a/components/policy/test_support/test_server_helpers.cc
+++ b/components/policy/test_support/test_server_helpers.cc
@@ -109,17 +109,6 @@
                                    dm_protocol::kOAuthTokenHeaderPrefix, out);
 }
 
-bool GetProfileIdFromRequest(const net::test_server::HttpRequest& request,
-                             std::string* out) {
-  std::string profile_id =
-      KeyValueFromUrl(request.GetURL(), dm_protocol::kParamProfileID);
-  if (profile_id.empty()) {
-    return false;
-  }
-  *out = profile_id;
-  return true;
-}
-
 std::unique_ptr<HttpResponse> CreateHttpResponse(
     net::HttpStatusCode code,
     const em::DeviceManagementResponse& proto_content) {
diff --git a/components/policy/test_support/test_server_helpers.h b/components/policy/test_support/test_server_helpers.h
index fe420c6..de1e7cfa0 100644
--- a/components/policy/test_support/test_server_helpers.h
+++ b/components/policy/test_support/test_server_helpers.h
@@ -60,11 +60,6 @@
 bool GetGoogleLoginFromRequest(const net::test_server::HttpRequest& request,
                                std::string* out);
 
-// Returns true if a Profile ID is specified in the `request` URL, and copies
-// its value to `out`.
-bool GetProfileIdFromRequest(const net::test_server::HttpRequest& request,
-                             std::string* out);
-
 // Returns a text/plain HttpResponse with a given `code` and `content`.
 std::unique_ptr<net::test_server::HttpResponse> CreateHttpResponse(
     net::HttpStatusCode code,
diff --git a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
index 43b3fa9..fedfacba1 100644
--- a/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
+++ b/components/safe_browsing/content/renderer/phishing_classifier/scorer.cc
@@ -16,7 +16,6 @@
 #include "base/memory/shared_memory_mapping.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/task_traits.h"
@@ -174,8 +173,8 @@
     return std::string();
   }
 
-  CHECK_EQ(downsampled.width(), width, base::NotFatalUntil::M125);
-  CHECK_EQ(downsampled.height(), height, base::NotFatalUntil::M125);
+  CHECK_EQ(downsampled.width(), width);
+  CHECK_EQ(downsampled.height(), height);
 
   // Format as an RGB buffer for input into the model
   std::string data;
diff --git a/components/search_engines/android/template_url_service_android.cc b/components/search_engines/android/template_url_service_android.cc
index 3f50161..dc1bcf0 100644
--- a/components/search_engines/android/template_url_service_android.cc
+++ b/components/search_engines/android/template_url_service_android.cc
@@ -18,7 +18,6 @@
 #include "base/functional/bind.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/field_trial_params.h"
-#include "base/not_fatal_until.h"
 #include "base/notreached.h"
 #include "base/strings/string_util.h"
 #include "base/strings/utf_string_conversions.h"
@@ -406,7 +405,7 @@
         jimage_translate_target_language_param_key) {
   // The function is scheduled to run only when the service is loaded, see
   // `TemplateUrlService#runWhenLoaded()`.
-  CHECK(template_url_service_->loaded(), base::NotFatalUntil::M128);
+  CHECK(template_url_service_->loaded());
 
   // Check if there is already a search engine created by a regulatory program.
   TemplateURLService::TemplateURLVector template_urls =
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
index fdb4a31..0165abc0 100644
--- a/components/search_engines/template_url_service.cc
+++ b/components/search_engines/template_url_service.cc
@@ -29,7 +29,6 @@
 #include "base/metrics/field_trial_params.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/notreached.h"
 #include "base/observer_list.h"
 #include "base/rand_util.h"
@@ -1139,7 +1138,7 @@
       // it as DSE means that we don't have a policy-enforced engine, and we
       // know that the incoming engine otherwise meets the criteria to be to be
       // set as DSE.
-      CHECK(CanMakeDefault(new_play_api_turl.get()), base::NotFatalUntil::M129);
+      CHECK(CanMakeDefault(new_play_api_turl.get()));
 
       // Clearing the member is OK here, we just have to make sure it is
       // re-populated by the time `scoper` is cleared.
@@ -1156,7 +1155,7 @@
 
   // Adding the engine should be successful, we already checked for blockers
   // above.
-  CHECK(new_play_api_turl_ptr, base::NotFatalUntil::M129);
+  CHECK(new_play_api_turl_ptr);
 
   // Part 2: Set as DSE.
   // It is still possible that policies control the DSE, so ensure we don't
@@ -1241,8 +1240,8 @@
       // kicked in after a choice screen was shown, that could be a way to
       // enter this state
       // TODO(crbug.com/328041262): Investigate mitigation options.
-      CHECK_NE(choice_made_location, search_engines::ChoiceMadeLocation::kOther,
-               base::NotFatalUntil::M127);
+      CHECK_NE(choice_made_location,
+               search_engines::ChoiceMadeLocation::kOther);
     }
   } else {
     // We rely on the DefaultSearchManager to call ApplyDefaultSearchChange if,
diff --git a/components/subresource_filter/android/ads_blocked_dialog.cc b/components/subresource_filter/android/ads_blocked_dialog.cc
index 8e84eb87..3c74bd43 100644
--- a/components/subresource_filter/android/ads_blocked_dialog.cc
+++ b/components/subresource_filter/android/ads_blocked_dialog.cc
@@ -12,7 +12,6 @@
 #include "base/android/jni_string.h"
 #include "base/check.h"
 #include "base/memory/ptr_util.h"
-#include "base/not_fatal_until.h"
 #include "content/public/browser/web_contents.h"
 #include "ui/android/window_android.h"
 
@@ -27,7 +26,7 @@
     base::OnceClosure allow_ads_clicked_callback,
     base::OnceClosure learn_more_clicked_callback,
     base::OnceClosure dialog_dismissed_callback) {
-  CHECK(web_contents, base::NotFatalUntil::M129);
+  CHECK(web_contents);
 
   ui::WindowAndroid* window_android = web_contents->GetTopLevelNativeWindow();
   if (!window_android) {
diff --git a/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc b/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
index a5a6315..b5ace67 100644
--- a/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
+++ b/components/subresource_filter/content/browser/ads_blocked_message_delegate.cc
@@ -9,7 +9,6 @@
 #include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/memory/ptr_util.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/utf_string_conversions.h"
 #include "components/messages/android/message_dispatcher_bridge.h"
 #include "components/resources/android/theme_resources.h"
@@ -116,7 +115,7 @@
 
 void AdsBlockedMessageDelegate::HandleMessageDismissed(
     messages::DismissReason dismiss_reason) {
-  CHECK(message_, base::NotFatalUntil::M129);
+  CHECK(message_);
   message_.reset();
 }
 
@@ -145,12 +144,12 @@
     // will be restored when the user navigates back to the original tab.
     return;
   }
-  CHECK(ads_blocked_dialog_, base::NotFatalUntil::M129);
+  CHECK(ads_blocked_dialog_);
   ads_blocked_dialog_.reset();
 }
 
 void AdsBlockedMessageDelegate::ShowDialog(bool should_post_dialog) {
-  CHECK(!reprompt_required_, base::NotFatalUntil::M129);
+  CHECK(!reprompt_required_);
   // Binding with base::Unretained(this) is safe here because
   // AdsBlockedMessageDelegate owns ads_blocked_dialog_. Callbacks won't be
   // called after the AdsBlockedMessageDelegate object is destroyed.
diff --git a/components/subresource_filter/content/browser/content_activation_list_utils.cc b/components/subresource_filter/content/browser/content_activation_list_utils.cc
index 7b7eb43c..491fecdc 100644
--- a/components/subresource_filter/content/browser/content_activation_list_utils.cc
+++ b/components/subresource_filter/content/browser/content_activation_list_utils.cc
@@ -5,7 +5,6 @@
 #include "components/subresource_filter/content/browser/content_activation_list_utils.h"
 
 #include "base/check.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/core/browser/subresource_filter_features.h"
 
 namespace subresource_filter {
@@ -65,7 +64,7 @@
     safe_browsing::SBThreatType threat_type,
     const safe_browsing::ThreatMetadata& threat_type_metadata,
     bool* warning) {
-  CHECK(warning, base::NotFatalUntil::M129);
+  CHECK(warning);
   bool is_phishing_interstitial =
       (threat_type == safe_browsing::SBThreatType::SB_THREAT_TYPE_URL_PHISHING);
   bool is_soc_engineering_ads_interstitial =
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
index 8ed5ff52..85700a67 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.cc
@@ -14,7 +14,6 @@
 #include "base/functional/bind.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/stringprintf.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
@@ -76,8 +75,7 @@
     VerifiedRulesetDealer::Handle* dealer_handle,
     ContentSubresourceFilterWebContentsHelper& web_contents_helper,
     content::NavigationHandle& initiating_navigation_handle) {
-  CHECK(IsInSubresourceFilterRoot(&initiating_navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(&initiating_navigation_handle));
 
   if (!base::FeatureList::IsEnabled(kSafeBrowsingSubresourceFilter)) {
     return nullptr;
@@ -331,8 +329,7 @@
           filter->activation_state(), kSafeBrowsingRulesetConfig.uma_tag);
       if (filter->activation_state().enable_logging) {
         CHECK(filter->activation_state().activation_level !=
-                  mojom::ActivationLevel::kDisabled,
-              base::NotFatalUntil::M129);
+              mojom::ActivationLevel::kDisabled);
         frame_host->AddMessageToConsole(
             blink::mojom::ConsoleMessageLevel::kWarning,
             kActivationConsoleMessage);
@@ -354,8 +351,8 @@
     ActivationStateComputingNavigationThrottle* throttle,
     content::RenderFrameHost* frame_host,
     bool& did_inherit_opener_activation) {
-  CHECK(navigation_handle, base::NotFatalUntil::M129);
-  CHECK(frame_host, base::NotFatalUntil::M129);
+  CHECK(navigation_handle);
+  CHECK(frame_host);
 
   std::unique_ptr<AsyncDocumentSubresourceFilter> filter;
   std::optional<mojom::ActivationState> activation_to_inherit;
@@ -384,8 +381,7 @@
     // navigation redirects from a URL handled by the network stack to
     // about:blank, a filter can already exist here. We replace it to match
     // behavior for other about:blank frames.
-    CHECK(!filter || navigation_handle->GetRedirectChain().size() != 1,
-          base::NotFatalUntil::M129);
+    CHECK(!filter || navigation_handle->GetRedirectChain().size() != 1);
     activation_to_inherit =
         GetFrameActivationState(navigation_handle->GetParentFrame());
   }
@@ -393,7 +389,7 @@
   if (activation_to_inherit.has_value() &&
       activation_to_inherit->activation_level !=
           mojom::ActivationLevel::kDisabled) {
-    CHECK(dealer_handle_, base::NotFatalUntil::M129);
+    CHECK(dealer_handle_);
 
     // This constructs the filter in a way that allows it to be immediately
     // used. See the AsyncDocumentSubresourceFilter constructor for details.
@@ -428,8 +424,7 @@
         content::NavigationHandle* navigation_handle,
         const mojom::ActivationLevel& activation_level,
         bool did_inherit_opener_activation) {
-  CHECK(IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(navigation_handle));
 
   UMA_HISTOGRAM_ENUMERATION("SubresourceFilter.PageLoad.ActivationState",
                             activation_level);
@@ -450,8 +445,8 @@
 }
 
 void ContentSubresourceFilterThrottleManager::DidBecomePrimaryPage() {
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK(page_->IsPrimary(), base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK(page_->IsPrimary());
   // If we tried to notify while non-primary, we didn't show UI so do that now
   // that the page became primary. This also leads to reattempting notification
   // if a page transitioned from primary to non-primary and back (BFCache).
@@ -462,8 +457,8 @@
 
 void ContentSubresourceFilterThrottleManager::OnPageCreated(
     content::Page& page) {
-  CHECK(!page.GetMainDocument().IsFencedFrameRoot(), base::NotFatalUntil::M129);
-  CHECK(!page_, base::NotFatalUntil::M129);
+  CHECK(!page.GetMainDocument().IsFencedFrameRoot());
+  CHECK(!page_);
   page_ = &page;
   profile_interaction_manager_->DidCreatePage(*page_);
 }
@@ -475,9 +470,8 @@
 void ContentSubresourceFilterThrottleManager::OnPageActivationComputed(
     content::NavigationHandle* navigation_handle,
     const mojom::ActivationState& activation_state) {
-  CHECK(IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
-  CHECK(!navigation_handle->HasCommitted(), base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(navigation_handle));
+  CHECK(!navigation_handle->HasCommitted());
 
   auto it =
       ongoing_activation_throttles_.find(navigation_handle->GetNavigationId());
@@ -505,8 +499,7 @@
 void ContentSubresourceFilterThrottleManager::OnChildFrameNavigationEvaluated(
     content::NavigationHandle* navigation_handle,
     LoadPolicy load_policy) {
-  CHECK(!IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(navigation_handle));
   if (!navigation_handle->GetParentFrameOrOuterDocument()) {
     return;
   }
@@ -533,9 +526,8 @@
     MaybeCreateAndAddNavigationThrottles(
         content::NavigationThrottleRegistry& registry) {
   content::NavigationHandle& navigation_handle = registry.GetNavigationHandle();
-  CHECK(!navigation_handle.IsSameDocument(), base::NotFatalUntil::M129);
-  CHECK(!ShouldInheritActivation(navigation_handle.GetURL()),
-        base::NotFatalUntil::M129);
+  CHECK(!navigation_handle.IsSameDocument());
+  CHECK(!ShouldInheritActivation(navigation_handle.GetURL()));
 
   if (IsInSubresourceFilterRoot(&navigation_handle) && database_manager_) {
     registry.AddThrottle(std::make_unique<SafeBrowsingPageActivationThrottle>(
@@ -548,8 +540,7 @@
   MaybeCreateAndAddChildNavigationThrottle(registry);
 
   CHECK(!base::Contains(ongoing_activation_throttles_,
-                        navigation_handle.GetNavigationId()),
-        base::NotFatalUntil::M129);
+                        navigation_handle.GetNavigationId()));
   if (auto activation_throttle =
           MaybeCreateActivationStateComputingThrottle(registry)) {
     ongoing_activation_throttles_[navigation_handle.GetNavigationId()] =
@@ -583,8 +574,8 @@
 }
 
 void ContentSubresourceFilterThrottleManager::OnReloadRequested() {
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK(page_->IsPrimary(), base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK(page_->IsPrimary());
   profile_interaction_manager_->OnReloadRequested();
 }
 
@@ -647,7 +638,7 @@
   if (!parent_filter) {
     return nullptr;
   }
-  CHECK(ruleset_handle_, base::NotFatalUntil::M129);
+  CHECK(ruleset_handle_);
   return ActivationStateComputingNavigationThrottle::CreateForChild(
       registry, ruleset_handle_.get(), parent_filter->activation_state(),
       kSafeBrowsingRulesetConfig.uma_tag);
@@ -656,8 +647,7 @@
 AsyncDocumentSubresourceFilter*
 ContentSubresourceFilterThrottleManager::GetParentFrameFilter(
     content::NavigationHandle* child_frame_navigation) {
-  CHECK(!IsInSubresourceFilterRoot(child_frame_navigation),
-        base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(child_frame_navigation));
   return GetFrameFilter(
       child_frame_navigation->GetParentFrameOrOuterDocument());
 }
@@ -674,22 +664,21 @@
 AsyncDocumentSubresourceFilter*
 ContentSubresourceFilterThrottleManager::GetFrameFilter(
     content::RenderFrameHost* frame_host) {
-  CHECK(frame_host, base::NotFatalUntil::M129);
+  CHECK(frame_host);
 
   auto it = frame_host_filter_map_.find(frame_host);
   if (it == frame_host_filter_map_.end()) {
     return nullptr;
   }
 
-  CHECK(it->second, base::NotFatalUntil::M129);
+  CHECK(it->second);
   return it->second.get();
 }
 
 void ContentSubresourceFilterThrottleManager::MaybeShowNotification(
     content::RenderFrameHost* frame_host) {
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK_EQ(&GetSubresourceFilterRootPage(frame_host), page_,
-           base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK_EQ(&GetSubresourceFilterRootPage(frame_host), page_);
 
   if (current_committed_load_has_notified_disallowed_load_) {
     return;
@@ -741,15 +730,13 @@
     bool is_ad_frame) {
   content::FrameTreeNodeId frame_tree_node_id =
       render_frame_host->GetFrameTreeNodeId();
-  CHECK(base::Contains(tracked_ad_evidence_, frame_tree_node_id),
-        base::NotFatalUntil::M129);
+  CHECK(base::Contains(tracked_ad_evidence_, frame_tree_node_id));
 
   // TODO(crbug.com/373985560): This is rarely hit. After fixing, upgrade to a
   // CHECK.
   DCHECK_EQ(tracked_ad_evidence_.at(frame_tree_node_id).IndicatesAdFrame(),
             is_ad_frame);
-  CHECK(render_frame_host->GetParentOrOuterDocument(),
-        base::NotFatalUntil::M129);
+  CHECK(render_frame_host->GetParentOrOuterDocument());
 
   // `ad_frames_` does not need updating.
   if (is_ad_frame == base::Contains(ad_frames_, frame_tree_node_id)) {
@@ -774,8 +761,7 @@
 void ContentSubresourceFilterThrottleManager::SetIsAdFrameForTesting(
     content::RenderFrameHost* render_frame_host,
     bool is_ad_frame) {
-  CHECK(render_frame_host->GetParentOrOuterDocument(),
-        base::NotFatalUntil::M129);
+  CHECK(render_frame_host->GetParentOrOuterDocument());
   if (is_ad_frame ==
       base::Contains(ad_frames_, render_frame_host->GetFrameTreeNodeId())) {
     return;
@@ -824,7 +810,7 @@
   // iframes, see `AdScriptDidCreateFencedFrame`.
   content::RenderFrameHost* render_frame_host =
       receiver_.GetCurrentTargetFrame();
-  CHECK(!render_frame_host->IsFencedFrameRoot(), base::NotFatalUntil::M129);
+  CHECK(!render_frame_host->IsFencedFrameRoot());
   OnFrameIsAd(receiver_.GetCurrentTargetFrame());
 }
 
@@ -837,9 +823,9 @@
 
 void ContentSubresourceFilterThrottleManager::OnAdsViolationTriggered(
     mojom::AdsViolation violation) {
-  CHECK(page_, base::NotFatalUntil::M129);
+  CHECK(page_);
   CHECK_EQ(&GetSubresourceFilterRootPage(receiver_.GetCurrentTargetFrame()),
-           page_, base::NotFatalUntil::M129);
+           page_);
   // TODO(bokan) How should we deal with violations coming from a fenced frame?
   // Should we pass in the fenced frame root instead? crbug.com/1263541.
   OnAdsViolationTriggered(&page_->GetMainDocument(), violation);
@@ -870,7 +856,7 @@
   // fenced frames.
 
   content::RenderFrameHost* owner_frame = receiver_.GetCurrentTargetFrame();
-  CHECK(owner_frame, base::NotFatalUntil::M129);
+  CHECK(owner_frame);
 
   auto* fenced_frame_root = content::RenderFrameHost::FromPlaceholderToken(
       owner_frame->GetProcess()->GetDeprecatedID(), placeholder_token);
@@ -894,15 +880,14 @@
   }
 
   CHECK(!base::Contains(tracked_ad_evidence_,
-                        fenced_frame_root->GetFrameTreeNodeId()),
-        base::NotFatalUntil::M129);
+                        fenced_frame_root->GetFrameTreeNodeId()));
   OnChildFrameWasCreatedByAdScript(fenced_frame_root);
 }
 
 void ContentSubresourceFilterThrottleManager::OnChildFrameWasCreatedByAdScript(
     content::RenderFrameHost* frame_host) {
-  CHECK(frame_host, base::NotFatalUntil::M129);
-  CHECK(!IsSubresourceFilterRoot(frame_host), base::NotFatalUntil::M129);
+  CHECK(frame_host);
+  CHECK(!IsSubresourceFilterRoot(frame_host));
 
   EnsureFrameAdEvidence(frame_host)
       .set_created_by_ad_script(
@@ -912,8 +897,7 @@
 blink::FrameAdEvidence&
 ContentSubresourceFilterThrottleManager::EnsureFrameAdEvidence(
     content::NavigationHandle* navigation_handle) {
-  CHECK(!IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(navigation_handle));
   auto frame_tree_node_id = navigation_handle->GetFrameTreeNodeId();
   auto parent_frame_tree_node_id =
       navigation_handle->GetParentFrameOrOuterDocument()->GetFrameTreeNodeId();
@@ -923,7 +907,7 @@
 blink::FrameAdEvidence&
 ContentSubresourceFilterThrottleManager::EnsureFrameAdEvidence(
     content::RenderFrameHost* render_frame_host) {
-  CHECK(!IsSubresourceFilterRoot(render_frame_host), base::NotFatalUntil::M129);
+  CHECK(!IsSubresourceFilterRoot(render_frame_host));
   auto frame_tree_node_id = render_frame_host->GetFrameTreeNodeId();
   auto parent_frame_tree_node_id =
       render_frame_host->GetParentOrOuterDocument()->GetFrameTreeNodeId();
@@ -934,8 +918,8 @@
 ContentSubresourceFilterThrottleManager::EnsureFrameAdEvidence(
     content::FrameTreeNodeId frame_tree_node_id,
     content::FrameTreeNodeId parent_frame_tree_node_id) {
-  CHECK(frame_tree_node_id, base::NotFatalUntil::M129);
-  CHECK(parent_frame_tree_node_id, base::NotFatalUntil::M129);
+  CHECK(frame_tree_node_id);
+  CHECK(parent_frame_tree_node_id);
   return tracked_ad_evidence_
       .emplace(frame_tree_node_id,
                /*parent_is_ad=*/base::Contains(ad_frames_,
diff --git a/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc b/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
index 4b012d7..bddc151 100644
--- a/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
+++ b/components/subresource_filter/content/browser/content_subresource_filter_web_contents_helper.cc
@@ -9,7 +9,6 @@
 
 #include "base/check.h"
 #include "base/feature_list.h"
-#include "base/not_fatal_until.h"
 #include "base/supports_user_data.h"
 #include "components/subresource_filter/content/browser/content_subresource_filter_throttle_manager.h"
 #include "components/subresource_filter/content/shared/browser/utils.h"
@@ -126,7 +125,7 @@
   // We should never be requesting the throttle manager for a navigation that
   // moves a page into the primary frame tree (e.g. prerender activation,
   // BFCache restoration).
-  CHECK(!handle.IsPageActivation(), base::NotFatalUntil::M129);
+  CHECK(!handle.IsPageActivation());
 
   if (WillCreateNewThrottleManager(handle)) {
     auto* container =
@@ -137,7 +136,7 @@
 
     ContentSubresourceFilterThrottleManager* throttle_manager =
         container->Get();
-    CHECK(throttle_manager, base::NotFatalUntil::M129);
+    CHECK(throttle_manager);
     return throttle_manager;
   }
 
@@ -151,8 +150,7 @@
   // due to a parent's navigation (where the navigation's handle's RFH may be
   // null); this does not affect the result as both frames have the same
   // throttle manager.
-  CHECK(handle.IsSameDocument() || !IsInSubresourceFilterRoot(&handle),
-        base::NotFatalUntil::M129);
+  CHECK(handle.IsSameDocument() || !IsInSubresourceFilterRoot(&handle));
   content::RenderFrameHost* rfh = IsInSubresourceFilterRoot(&handle)
                                       ? handle.GetRenderFrameHost()
                                       : handle.GetParentFrameOrOuterDocument();
@@ -182,7 +180,7 @@
 void ContentSubresourceFilterWebContentsHelper::WillDestroyThrottleManager(
     ContentSubresourceFilterThrottleManager* throttle_manager) {
   bool was_erased = throttle_managers_.erase(throttle_manager);
-  CHECK(was_erased, base::NotFatalUntil::M129);
+  CHECK(was_erased);
 }
 
 void ContentSubresourceFilterWebContentsHelper::RenderFrameDeleted(
@@ -248,13 +246,12 @@
     // TODO(bokan): Once the BFCache restoration navigation is made synchronous
     // like prerender activation we can remove this special case.
     if (!navigation_handle->HasCommitted()) {
-      CHECK(navigation_handle->IsServedFromBackForwardCache(),
-            base::NotFatalUntil::M129);
+      CHECK(navigation_handle->IsServedFromBackForwardCache());
       return;
     }
 
-    CHECK(navigation_handle->HasCommitted(), base::NotFatalUntil::M129);
-    CHECK(navigation_handle->GetRenderFrameHost(), base::NotFatalUntil::M129);
+    CHECK(navigation_handle->HasCommitted());
+    CHECK(navigation_handle->GetRenderFrameHost());
 
     ContentSubresourceFilterThrottleManager* throttle_manager =
         GetThrottleManager(navigation_handle->GetRenderFrameHost()->GetPage());
@@ -296,7 +293,7 @@
       return;
     }
 
-    CHECK(throttle_manager, base::NotFatalUntil::M129);
+    CHECK(throttle_manager);
 
     // If the navigation was successful it will have created a new page,
     // transfer the throttle manager to Page user data. If it failed, but it's
@@ -351,7 +348,7 @@
 void ContentSubresourceFilterWebContentsHelper::OnSubresourceFilterGoingAway() {
   // Stop observing here because the observer manager could be destroyed by the
   // time this class is destroyed.
-  CHECK(scoped_observation_.IsObserving(), base::NotFatalUntil::M129);
+  CHECK(scoped_observation_.IsObserving());
   scoped_observation_.Reset();
 }
 
@@ -368,8 +365,7 @@
 void ContentSubresourceFilterWebContentsHelper::OnChildFrameNavigationEvaluated(
     content::NavigationHandle* navigation_handle,
     LoadPolicy load_policy) {
-  CHECK(!IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(navigation_handle));
   if (ContentSubresourceFilterThrottleManager* throttle_manager =
           GetThrottleManager(*navigation_handle)) {
     throttle_manager->OnChildFrameNavigationEvaluated(navigation_handle,
diff --git a/components/subresource_filter/content/browser/navigation_console_logger.cc b/components/subresource_filter/content/browser/navigation_console_logger.cc
index 4586ed1..d88b5df9 100644
--- a/components/subresource_filter/content/browser/navigation_console_logger.cc
+++ b/components/subresource_filter/content/browser/navigation_console_logger.cc
@@ -7,7 +7,6 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/memory/ptr_util.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/content/shared/browser/utils.h"
 #include "content/public/browser/frame_type.h"
 #include "content/public/browser/navigation_handle.h"
@@ -19,9 +18,9 @@
     content::NavigationHandle* handle,
     blink::mojom::ConsoleMessageLevel level,
     const std::string& message) {
-  CHECK(IsInSubresourceFilterRoot(handle), base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(handle));
   CHECK_NE(handle->GetNavigatingFrameType(),
-           content::FrameType::kFencedFrameRoot, base::NotFatalUntil::M129);
+           content::FrameType::kFencedFrameRoot);
 
   if (handle->HasCommitted() && !handle->IsErrorPage()) {
     handle->GetRenderFrameHost()->AddMessageToConsole(level, message);
@@ -34,9 +33,9 @@
 // static
 NavigationConsoleLogger* NavigationConsoleLogger::CreateIfNeededForNavigation(
     content::NavigationHandle* handle) {
-  CHECK(IsInSubresourceFilterRoot(handle), base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(handle));
   CHECK_NE(handle->GetNavigatingFrameType(),
-           content::FrameType::kFencedFrameRoot, base::NotFatalUntil::M129);
+           content::FrameType::kFencedFrameRoot);
   return GetOrCreateForNavigationHandle(*handle);
 }
 
diff --git a/components/subresource_filter/content/browser/profile_interaction_manager.cc b/components/subresource_filter/content/browser/profile_interaction_manager.cc
index d0e353f8..a707918 100644
--- a/components/subresource_filter/content/browser/profile_interaction_manager.cc
+++ b/components/subresource_filter/content/browser/profile_interaction_manager.cc
@@ -6,7 +6,6 @@
 
 #include "base/check.h"
 #include "base/logging.h"
-#include "base/not_fatal_until.h"
 #include "build/build_config.h"
 #include "components/content_settings/browser/page_specific_content_settings.h"
 #include "components/content_settings/core/common/content_settings_types.h"
@@ -36,15 +35,15 @@
 void ProfileInteractionManager::DidCreatePage(content::Page& page) {
   // A new ProfileInteractionManager is created for each page so we should only
   // call this, at most, once.
-  CHECK(!page_, base::NotFatalUntil::M129);
+  CHECK(!page_);
   page_ = &page;
 }
 
 void ProfileInteractionManager::OnReloadRequested() {
   // A reload request comes from browser so it will always be associated with
   // the primary page.
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK(page_->IsPrimary(), base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK(page_->IsPrimary());
 
   ContentSubresourceFilterThrottleManager::LogAction(
       SubresourceFilterAction::kAllowlistedSite);
@@ -99,8 +98,7 @@
     content::NavigationHandle* navigation_handle,
     mojom::ActivationLevel initial_activation_level,
     ActivationDecision* decision) {
-  CHECK(IsInSubresourceFilterRoot(navigation_handle),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(navigation_handle));
 
   mojom::ActivationLevel effective_activation_level = initial_activation_level;
 
@@ -132,8 +130,8 @@
 void ProfileInteractionManager::MaybeShowNotification() {
   // The caller should make sure this is only called from pages that are
   // currently primary.
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK(page_->IsPrimary(), base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK(page_->IsPrimary());
 
   const GURL& top_level_url = page_->GetMainDocument().GetLastCommittedURL();
   if (profile_context_->settings_manager()->ShouldShowUIForSite(
@@ -174,8 +172,8 @@
 }
 
 content::WebContents* ProfileInteractionManager::GetWebContents() {
-  CHECK(page_, base::NotFatalUntil::M129);
-  CHECK(page_->IsPrimary(), base::NotFatalUntil::M129);
+  CHECK(page_);
+  CHECK(page_->IsPrimary());
   return content::WebContents::FromRenderFrameHost(&page_->GetMainDocument());
 }
 
diff --git a/components/subresource_filter/content/browser/safe_browsing_page_activation_throttle.cc b/components/subresource_filter/content/browser/safe_browsing_page_activation_throttle.cc
index d0d80d7..c22cb53 100644
--- a/components/subresource_filter/content/browser/safe_browsing_page_activation_throttle.cc
+++ b/components/subresource_filter/content/browser/safe_browsing_page_activation_throttle.cc
@@ -14,7 +14,6 @@
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/timer/timer.h"
 #include "base/trace_event/trace_event.h"
@@ -81,10 +80,9 @@
       std::move(database_manager), this,
       base::SingleThreadTaskRunner::GetCurrentDefault()));
 
-  CHECK(IsInSubresourceFilterRoot(&registry.GetNavigationHandle()),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(&registry.GetNavigationHandle()));
   CheckCurrentUrl();
-  CHECK(!check_results_.empty(), base::NotFatalUntil::M129);
+  CHECK(!check_results_.empty());
 }
 
 SafeBrowsingPageActivationThrottle::~SafeBrowsingPageActivationThrottle() =
@@ -115,9 +113,9 @@
 
 void SafeBrowsingPageActivationThrottle::OnCheckUrlResultOnUI(
     const SubresourceFilterSafeBrowsingClient::CheckResult& result) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   size_t request_id = result.request_id;
-  CHECK_LT(request_id, check_results_.size(), base::NotFatalUntil::M129);
+  CHECK_LT(request_id, check_results_.size());
 
   auto& stored_result = check_results_.at(request_id);
   CHECK(!stored_result.finished);
@@ -151,7 +149,7 @@
 SafeBrowsingPageActivationThrottle::ConfigResult::~ConfigResult() = default;
 
 void SafeBrowsingPageActivationThrottle::CheckCurrentUrl() {
-  CHECK(database_client_, base::NotFatalUntil::M129);
+  CHECK(database_client_);
   check_results_.emplace_back();
   size_t id = check_results_.size() - 1;
   database_client_->CheckUrl(navigation_handle()->GetURL(), id,
@@ -161,7 +159,7 @@
 void SafeBrowsingPageActivationThrottle::NotifyResult() {
   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
                "SafeBrowsingPageActivationThrottle::NotifyResult");
-  CHECK(!check_results_.empty(), base::NotFatalUntil::M129);
+  CHECK(!check_results_.empty());
 
   // Determine which results to consider for safebrowsing/abusive enforcement.
   // We only consider the final check result in a redirect chain.
@@ -173,8 +171,7 @@
 
   // Get the activation decision with the associated ConfigResult.
   ActivationDecision activation_decision = GetActivationDecision(selection);
-  CHECK_NE(activation_decision, ActivationDecision::UNKNOWN,
-           base::NotFatalUntil::M129);
+  CHECK_NE(activation_decision, ActivationDecision::UNKNOWN);
 
   // Notify the observers of the check results.
   SubresourceFilterObserverManager::FromWebContents(
@@ -223,7 +220,7 @@
     ActivationList matched_list,
     ActivationDecision decision,
     mojom::ActivationLevel level) const {
-  CHECK(HasFinishedAllSafeBrowsingChecks(), base::NotFatalUntil::M129);
+  CHECK(HasFinishedAllSafeBrowsingChecks());
 
   base::TimeDelta delay = defer_time_.is_null()
                               ? base::Milliseconds(0)
@@ -235,8 +232,7 @@
   ukm::builders::SubresourceFilter builder(source_id);
   builder.SetActivationDecision(static_cast<int64_t>(decision));
   if (level == mojom::ActivationLevel::kDryRun) {
-    CHECK_EQ(ActivationDecision::ACTIVATED, decision,
-             base::NotFatalUntil::M129);
+    CHECK_EQ(ActivationDecision::ACTIVATED, decision);
     builder.SetDryRun(true);
   }
 
@@ -267,7 +263,7 @@
 SafeBrowsingPageActivationThrottle::ConfigResult
 SafeBrowsingPageActivationThrottle::GetHighestPriorityConfiguration(
     const SubresourceFilterSafeBrowsingClient::CheckResult& result) {
-  CHECK(result.finished, base::NotFatalUntil::M129);
+  CHECK(result.finished);
   Configuration selected_config;
   bool warning = false;
   bool matched = false;
diff --git a/components/subresource_filter/content/browser/safe_browsing_ruleset_publisher.cc b/components/subresource_filter/content/browser/safe_browsing_ruleset_publisher.cc
index 6026672..441aa8c 100644
--- a/components/subresource_filter/content/browser/safe_browsing_ruleset_publisher.cc
+++ b/components/subresource_filter/content/browser/safe_browsing_ruleset_publisher.cc
@@ -30,9 +30,9 @@
 void SafeBrowsingRulesetPublisher::SendRulesetToRenderProcess(
     base::File* file,
     content::RenderProcessHost* rph) {
-  CHECK(rph, base::NotFatalUntil::M129);
-  CHECK(file, base::NotFatalUntil::M129);
-  CHECK(file->IsValid(), base::NotFatalUntil::M129);
+  CHECK(rph);
+  CHECK(file);
+  CHECK(file->IsValid());
   if (!rph->GetChannel()) {
     return;
   }
diff --git a/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc b/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
index cf3716d7..a767f7c 100644
--- a/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_content_settings_manager.cc
@@ -11,7 +11,6 @@
 #include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/json/values_util.h"
-#include "base/not_fatal_until.h"
 #include "base/time/default_clock.h"
 #include "base/values.h"
 #include "build/build_config.h"
@@ -55,7 +54,7 @@
     : settings_map_(settings_map),
       clock_(std::make_unique<base::DefaultClock>(base::DefaultClock())),
       should_use_smart_ui_(ShouldUseSmartUI()) {
-  CHECK(settings_map_, base::NotFatalUntil::M129);
+  CHECK(settings_map_);
 }
 
 SubresourceFilterContentSettingsManager::
@@ -115,7 +114,7 @@
   if (!is_activated &&
       ShouldDeleteDataWithNoActivation(dict, activation_source)) {
     // If we are clearing metadata, there should be no additional_data dict.
-    CHECK(!additional_data, base::NotFatalUntil::M129);
+    CHECK(!additional_data);
     SetSiteMetadata(url, std::nullopt);
     return;
   }
@@ -188,7 +187,7 @@
   if (dict && dict->Find(kNonRenewingExpiryTime)) {
     std::optional<double> metadata_expiry_time =
         dict->FindDouble(kNonRenewingExpiryTime);
-    CHECK(metadata_expiry_time, base::NotFatalUntil::M129);
+    CHECK(metadata_expiry_time);
     expiry_time = base::Time::FromSecondsSinceUnixEpoch(*metadata_expiry_time);
 
     // If the lifetime was stored explicitly, we should use that instead of
diff --git a/components/subresource_filter/content/browser/subresource_filter_profile_context.cc b/components/subresource_filter/content/browser/subresource_filter_profile_context.cc
index 438ca660..4c247b8 100644
--- a/components/subresource_filter/content/browser/subresource_filter_profile_context.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_profile_context.cc
@@ -5,7 +5,6 @@
 #include "components/subresource_filter/content/browser/subresource_filter_profile_context.h"
 
 #include "base/check.h"
-#include "base/not_fatal_until.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/subresource_filter/content/browser/ads_intervention_manager.h"
 #include "components/subresource_filter/content/browser/subresource_filter_content_settings_manager.h"
@@ -27,7 +26,7 @@
 void SubresourceFilterProfileContext::SetEmbedderData(
     std::unique_ptr<SubresourceFilterProfileContext::EmbedderData>
         embedder_data) {
-  CHECK(!embedder_data_, base::NotFatalUntil::M129);
+  CHECK(!embedder_data_);
   embedder_data_ = std::move(embedder_data);
 }
 
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
index 0724497..6f19daf 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client.cc
@@ -10,7 +10,6 @@
 #include "base/check_op.h"
 #include "base/functional/bind.h"
 #include "base/location.h"
-#include "base/not_fatal_until.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/trace_event/trace_event.h"
 #include "base/trace_event/traced_value.h"
@@ -40,7 +39,7 @@
     : database_manager_(std::move(database_manager)),
       throttle_(throttle),
       throttle_task_runner_(std::move(throttle_task_runner)) {
-  CHECK(database_manager_, base::NotFatalUntil::M129);
+  CHECK(database_manager_);
 }
 
 SubresourceFilterSafeBrowsingClient::~SubresourceFilterSafeBrowsingClient() =
@@ -49,14 +48,13 @@
 void SubresourceFilterSafeBrowsingClient::CheckUrl(const GURL& url,
                                                    size_t request_id,
                                                    base::TimeTicks start_time) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
-  CHECK(!url.is_empty(), base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
+  CHECK(!url.is_empty());
 
   auto request = std::make_unique<SubresourceFilterSafeBrowsingClientRequest>(
       request_id, start_time, database_manager_, this);
   auto* raw_request = request.get();
-  CHECK(requests_.find(raw_request) == requests_.end(),
-        base::NotFatalUntil::M129);
+  CHECK(requests_.find(raw_request) == requests_.end());
   requests_[raw_request] = std::move(request);
   TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(
       TRACE_DISABLED_BY_DEFAULT("loading"), "SubresourceFilterSBCheck",
@@ -69,11 +67,11 @@
 void SubresourceFilterSafeBrowsingClient::OnCheckBrowseUrlResult(
     SubresourceFilterSafeBrowsingClientRequest* request,
     const CheckResult& check_result) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   TRACE_EVENT_NESTABLE_ASYNC_END1(
       TRACE_DISABLED_BY_DEFAULT("loading"), "SubresourceFilterSBCheck",
       TRACE_ID_LOCAL(request), "check_result", check_result.ToTracedValue());
-  CHECK(requests_.find(request) != requests_.end(), base::NotFatalUntil::M129);
+  CHECK(requests_.find(request) != requests_.end());
   requests_.erase(request);
   if (throttle_) {
     throttle_->OnCheckUrlResultOnUI(check_result);
diff --git a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc
index cc51021..2d6a44f 100644
--- a/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc
+++ b/components/subresource_filter/content/browser/subresource_filter_safe_browsing_client_request.cc
@@ -33,12 +33,12 @@
       start_time_(start_time),
       database_manager_(std::move(database_manager)),
       client_(client) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
 SubresourceFilterSafeBrowsingClientRequest::
     ~SubresourceFilterSafeBrowsingClientRequest() {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   if (!request_completed_) {
     database_manager_->CancelCheck(this);
   }
@@ -46,7 +46,7 @@
 }
 
 void SubresourceFilterSafeBrowsingClientRequest::Start(const GURL& url) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   // Just return SAFE if the database is not supported.
   bool synchronous_finish =
       database_manager_->CheckUrlForSubresourceFilter(url, this);
@@ -68,14 +68,14 @@
     const GURL& url,
     safe_browsing::SBThreatType threat_type,
     const safe_browsing::ThreatMetadata& metadata) {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   request_completed_ = true;
   SendCheckResultToClient(true /* served_from_network */, threat_type,
                           metadata);
 }
 
 void SubresourceFilterSafeBrowsingClientRequest::OnCheckUrlTimeout() {
-  CHECK_CURRENTLY_ON(content::BrowserThread::UI, base::NotFatalUntil::M129);
+  CHECK_CURRENTLY_ON(content::BrowserThread::UI);
   SendCheckResultToClient(true /* served_from_network */,
                           safe_browsing::SBThreatType::SB_THREAT_TYPE_SAFE,
                           safe_browsing::ThreatMetadata());
diff --git a/components/subresource_filter/content/renderer/subresource_filter_agent.cc b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
index cc9d7ba..c84c7c5 100644
--- a/components/subresource_filter/content/renderer/subresource_filter_agent.cc
+++ b/components/subresource_filter/content/renderer/subresource_filter_agent.cc
@@ -11,7 +11,6 @@
 #include "base/functional/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/time/time.h"
 #include "components/subresource_filter/content/renderer/unverified_ruleset_dealer.h"
 #include "components/subresource_filter/content/renderer/web_document_subresource_filter_impl.h"
@@ -54,13 +53,13 @@
     : content::RenderFrameObserver(render_frame),
       content::RenderFrameObserverTracker<SubresourceFilterAgent>(render_frame),
       ruleset_dealer_(ruleset_dealer) {
-  CHECK(ruleset_dealer, base::NotFatalUntil::M129);
+  CHECK(ruleset_dealer);
 }
 
 void SubresourceFilterAgent::Initialize() {
   const GURL& url = GetDocumentURL();
   // The initial empty document will always inherit activation.
-  CHECK(ShouldInheritActivation(url), base::NotFatalUntil::M129);
+  CHECK(ShouldInheritActivation(url));
 
   // We must check for provisional here because in that case 2 RenderFrames will
   // be created for the same FrameTreeNode in the browser. The browser service
@@ -137,7 +136,7 @@
 bool SubresourceFilterAgent::IsParentAdFrame() {
   // A fenced frame root should never ask this since it can't see the outer
   // frame tree. Its AdEvidence is always computed by the browser.
-  CHECK(!IsFencedFrameRoot(render_frame()), base::NotFatalUntil::M129);
+  CHECK(!IsFencedFrameRoot(render_frame()));
   return render_frame()->GetWebFrame()->Parent()->IsAdFrame();
 }
 
@@ -146,14 +145,14 @@
 }
 
 bool SubresourceFilterAgent::IsFrameCreatedByAdScript() {
-  CHECK(!IsFencedFrameRoot(render_frame()), base::NotFatalUntil::M129);
+  CHECK(!IsFencedFrameRoot(render_frame()));
   return render_frame()->GetWebFrame()->IsFrameCreatedByAdScript();
 }
 
 void SubresourceFilterAgent::SetSubresourceFilterForCurrentDocument(
     std::unique_ptr<blink::WebDocumentSubresourceFilter> filter) {
   blink::WebLocalFrame* web_frame = render_frame()->GetWebFrame();
-  CHECK(web_frame->GetDocumentLoader(), base::NotFatalUntil::M129);
+  CHECK(web_frame->GetDocumentLoader());
   web_frame->GetDocumentLoader()->SetSubresourceFilter(filter.release());
 }
 
@@ -172,7 +171,7 @@
 }
 
 void SubresourceFilterAgent::SendFrameWasCreatedByAdScript() {
-  CHECK(!IsFencedFrameRoot(render_frame()), base::NotFatalUntil::M129);
+  CHECK(!IsFencedFrameRoot(render_frame()));
   GetSubresourceFilterHost()->FrameWasCreatedByAdScript();
 }
 
@@ -272,10 +271,10 @@
     const std::optional<blink::FrameAdEvidence>& ad_evidence) {
   activation_state_for_next_document_ = *activation_state;
   if (IsSubresourceFilterChild()) {
-    CHECK(ad_evidence.has_value(), base::NotFatalUntil::M129);
+    CHECK(ad_evidence.has_value());
     SetAdEvidence(ad_evidence.value());
   } else {
-    CHECK(!ad_evidence.has_value(), base::NotFatalUntil::M129);
+    CHECK(!ad_evidence.has_value());
   }
 }
 
@@ -284,9 +283,9 @@
 }
 
 void SubresourceFilterAgent::SetAdEvidenceForInitialEmptySubframe() {
-  CHECK(!IsAdFrame(), base::NotFatalUntil::M129);
-  CHECK(!AdEvidence().has_value(), base::NotFatalUntil::M129);
-  CHECK(!IsFencedFrameRoot(render_frame()), base::NotFatalUntil::M129);
+  CHECK(!IsAdFrame());
+  CHECK(!AdEvidence().has_value());
+  CHECK(!IsFencedFrameRoot(render_frame()));
 
   blink::FrameAdEvidence ad_evidence(IsParentAdFrame());
   ad_evidence.set_created_by_ad_script(
@@ -332,7 +331,7 @@
 
 const mojom::ActivationState
 SubresourceFilterAgent::GetInheritedActivationStateForNewDocument() {
-  CHECK(ShouldInheritActivation(GetDocumentURL()), base::NotFatalUntil::M129);
+  CHECK(ShouldInheritActivation(GetDocumentURL()));
   return GetInheritedActivationState(render_frame());
 }
 
diff --git a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
index 193958e..8fe52bf 100644
--- a/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
+++ b/components/subresource_filter/content/renderer/web_document_subresource_filter_impl.cc
@@ -11,7 +11,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/memory/scoped_refptr.h"
-#include "base/not_fatal_until.h"
 #include "base/task/single_thread_task_runner.h"
 #include "components/subresource_filter/content/shared/renderer/filter_utils.h"
 #include "components/subresource_filter/core/common/constants.h"
@@ -78,8 +77,7 @@
 WebLoadPolicy
 WebDocumentSubresourceFilterImpl::GetLoadPolicyForWebSocketConnect(
     const blink::WebURL& url) {
-  CHECK(url.ProtocolIs("ws") || url.ProtocolIs("wss"),
-        base::NotFatalUntil::M129);
+  CHECK(url.ProtocolIs("ws") || url.ProtocolIs("wss"));
   return getLoadPolicyImpl(url, proto::ELEMENT_TYPE_WEBSOCKET);
 }
 
@@ -128,7 +126,7 @@
 
 std::unique_ptr<blink::WebDocumentSubresourceFilter>
 WebDocumentSubresourceFilterImpl::BuilderImpl::Build() {
-  CHECK(ruleset_file_.IsValid(), base::NotFatalUntil::M129);
+  CHECK(ruleset_file_.IsValid());
   scoped_refptr<MemoryMappedRuleset> ruleset =
       MemoryMappedRuleset::CreateAndInitialize(std::move(ruleset_file_));
   if (!ruleset) {
diff --git a/components/subresource_filter/content/shared/browser/activation_state_computing_navigation_throttle.cc b/components/subresource_filter/content/shared/browser/activation_state_computing_navigation_throttle.cc
index 0c43b201..42977d2e 100644
--- a/components/subresource_filter/content/shared/browser/activation_state_computing_navigation_throttle.cc
+++ b/components/subresource_filter/content/shared/browser/activation_state_computing_navigation_throttle.cc
@@ -12,7 +12,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/memory/ptr_util.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/content/shared/browser/utils.h"
 #include "components/subresource_filter/core/browser/async_document_subresource_filter.h"
 #include "content/public/browser/navigation_handle.h"
@@ -26,8 +25,7 @@
 ActivationStateComputingNavigationThrottle::CreateForRoot(
     content::NavigationThrottleRegistry& registry,
     std::string_view uma_tag) {
-  CHECK(IsInSubresourceFilterRoot(&registry.GetNavigationHandle()),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(&registry.GetNavigationHandle()));
   return base::WrapUnique(new ActivationStateComputingNavigationThrottle(
       registry, /*parent_activation_state=*/std::nullopt,
       /*ruleset_handle*/ nullptr, uma_tag));
@@ -40,11 +38,10 @@
     VerifiedRuleset::Handle* ruleset_handle,
     const mojom::ActivationState& parent_activation_state,
     std::string_view uma_tag) {
-  CHECK(!IsInSubresourceFilterRoot(&registry.GetNavigationHandle()),
-        base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(&registry.GetNavigationHandle()));
   CHECK_NE(mojom::ActivationLevel::kDisabled,
-           parent_activation_state.activation_level, base::NotFatalUntil::M129);
-  CHECK(ruleset_handle, base::NotFatalUntil::M129);
+           parent_activation_state.activation_level);
+  CHECK(ruleset_handle);
   return base::WrapUnique(new ActivationStateComputingNavigationThrottle(
       registry, parent_activation_state, ruleset_handle, uma_tag));
 }
@@ -67,12 +64,11 @@
     NotifyPageActivationWithRuleset(
         VerifiedRuleset::Handle* ruleset_handle,
         const mojom::ActivationState& page_activation_state) {
-  CHECK(IsInSubresourceFilterRoot(navigation_handle()),
-        base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(navigation_handle()));
   CHECK_NE(mojom::ActivationLevel::kDisabled,
-           page_activation_state.activation_level, base::NotFatalUntil::M129);
+           page_activation_state.activation_level);
   parent_activation_state_ = page_activation_state;
-  CHECK(ruleset_handle, base::NotFatalUntil::M129);
+  CHECK(ruleset_handle);
   ruleset_handle_ = ruleset_handle->AsWeakPtr();
 }
 
@@ -97,10 +93,9 @@
   // If no parent activation, this is root frame that was never notified of
   // activation.
   if (!parent_activation_state_) {
-    CHECK(IsInSubresourceFilterRoot(navigation_handle()),
-          base::NotFatalUntil::M129);
-    CHECK(!async_filter_, base::NotFatalUntil::M129);
-    CHECK(!ruleset_handle_, base::NotFatalUntil::M129);
+    CHECK(IsInSubresourceFilterRoot(navigation_handle()));
+    CHECK(!async_filter_);
+    CHECK(!ruleset_handle_);
     return content::NavigationThrottle::PROCEED;
   }
 
@@ -114,11 +109,10 @@
     }
     return content::NavigationThrottle::PROCEED;
   }
-  CHECK(!deferred_, base::NotFatalUntil::M129);
+  CHECK(!deferred_);
   deferred_ = true;
   if (!async_filter_) {
-    CHECK(IsInSubresourceFilterRoot(navigation_handle()),
-          base::NotFatalUntil::M129);
+    CHECK(IsInSubresourceFilterRoot(navigation_handle()));
     CheckActivationState();
   }
   return content::NavigationThrottle::DEFER;
@@ -129,15 +123,15 @@
 }
 
 void ActivationStateComputingNavigationThrottle::CheckActivationState() {
-  CHECK(parent_activation_state_, base::NotFatalUntil::M129);
-  CHECK(ruleset_handle_, base::NotFatalUntil::M129);
+  CHECK(parent_activation_state_);
+  CHECK(ruleset_handle_);
   AsyncDocumentSubresourceFilter::InitializationParams params;
   params.document_url = navigation_handle()->GetURL();
   params.parent_activation_state = parent_activation_state_.value();
   if (!IsInSubresourceFilterRoot(navigation_handle())) {
     content::RenderFrameHost* parent =
         navigation_handle()->GetParentFrameOrOuterDocument();
-    CHECK(parent, base::NotFatalUntil::M129);
+    CHECK(parent);
     params.parent_document_origin = parent->GetLastCommittedOrigin();
   }
 
@@ -167,10 +161,9 @@
   // This method is only needed for root frame navigations that are notified of
   // page activation more than once. Even for those that are updated once, it
   // should be a no-op.
-  CHECK(IsInSubresourceFilterRoot(navigation_handle()),
-        base::NotFatalUntil::M129);
-  CHECK(parent_activation_state_, base::NotFatalUntil::M129);
-  CHECK(async_filter_, base::NotFatalUntil::M129);
+  CHECK(IsInSubresourceFilterRoot(navigation_handle()));
+  CHECK(parent_activation_state_);
+  CHECK(async_filter_);
   async_filter_->UpdateWithMoreAccurateState(*parent_activation_state_);
 }
 
@@ -195,7 +188,7 @@
 
 void ActivationStateComputingNavigationThrottle::
     WillSendActivationToRenderer() {
-  CHECK(async_filter_, base::NotFatalUntil::M129);
+  CHECK(async_filter_);
   will_send_activation_to_renderer_ = true;
 }
 
diff --git a/components/subresource_filter/content/shared/browser/child_frame_navigation_filtering_throttle.cc b/components/subresource_filter/content/shared/browser/child_frame_navigation_filtering_throttle.cc
index d8066c59..090dffe 100644
--- a/components/subresource_filter/content/shared/browser/child_frame_navigation_filtering_throttle.cc
+++ b/components/subresource_filter/content/shared/browser/child_frame_navigation_filtering_throttle.cc
@@ -15,7 +15,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/stringprintf.h"
 #include "components/subresource_filter/content/shared/browser/utils.h"
 #include "components/subresource_filter/core/browser/subresource_filter_constants.h"
@@ -39,9 +38,8 @@
       parent_frame_filter_(parent_frame_filter),
       alias_check_enabled_(alias_check_enabled),
       disallow_message_callback_(std::move(disallow_message_callback)) {
-  CHECK(!IsInSubresourceFilterRoot(&registry.GetNavigationHandle()),
-        base::NotFatalUntil::M129);
-  CHECK(parent_frame_filter_, base::NotFatalUntil::M129);
+  CHECK(!IsInSubresourceFilterRoot(&registry.GetNavigationHandle()));
+  CHECK(parent_frame_filter_);
 }
 
 ChildFrameNavigationFilteringThrottle::
@@ -59,7 +57,7 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 ChildFrameNavigationFilteringThrottle::WillProcessResponse() {
-  CHECK_NE(load_policy_, LoadPolicy::DISALLOW, base::NotFatalUntil::M129);
+  CHECK_NE(load_policy_, LoadPolicy::DISALLOW);
 
   if (alias_check_enabled_) {
     std::vector<GURL> alias_urls;
@@ -95,9 +93,8 @@
   // run mode or checking aliases.
   if (pending_load_policy_calculations_ > 0) {
     CHECK(parent_frame_filter_->activation_state().activation_level ==
-                  mojom::ActivationLevel::kDryRun ||
-              navigation_handle()->GetDnsAliases().size() > 0,
-          base::NotFatalUntil::M129);
+              mojom::ActivationLevel::kDryRun ||
+          navigation_handle()->GetDnsAliases().size() > 0);
     DeferStart(DeferStage::kWillProcessResponse);
     return DEFER;
   }
@@ -127,7 +124,7 @@
 
 content::NavigationThrottle::ThrottleCheckResult
 ChildFrameNavigationFilteringThrottle::MaybeDeferToCalculateLoadPolicy() {
-  CHECK_NE(load_policy_, LoadPolicy::DISALLOW, base::NotFatalUntil::M129);
+  CHECK_NE(load_policy_, LoadPolicy::DISALLOW);
   if (load_policy_ == LoadPolicy::WOULD_DISALLOW) {
     return PROCEED;
   }
@@ -162,8 +159,7 @@
   }
 
   CHECK(defer_stage_ == DeferStage::kWillProcessResponse ||
-            defer_stage_ == DeferStage::kWillStartOrRedirectRequest,
-        base::NotFatalUntil::M129);
+        defer_stage_ == DeferStage::kWillStartOrRedirectRequest);
 
   // If we have an activation enabled and `load_policy_` is DISALLOW, we need
   // to cancel the navigation.
@@ -196,10 +192,9 @@
 void ChildFrameNavigationFilteringThrottle::
     OnCalculatedLoadPoliciesFromAliasUrls(std::vector<LoadPolicy> policies) {
   // We deferred to check aliases in WillProcessResponse.
-  CHECK(defer_stage_ == DeferStage::kWillProcessResponse,
-        base::NotFatalUntil::M129);
+  CHECK(defer_stage_ == DeferStage::kWillProcessResponse);
   CHECK(alias_check_enabled_);
-  CHECK(!policies.empty(), base::NotFatalUntil::M129);
+  CHECK(!policies.empty());
 
   did_alias_check_ = true;
 
@@ -221,15 +216,15 @@
 }
 
 void ChildFrameNavigationFilteringThrottle::DeferStart(DeferStage stage) {
-  CHECK(defer_stage_ == DeferStage::kNotDeferring, base::NotFatalUntil::M129);
-  CHECK(stage != DeferStage::kNotDeferring, base::NotFatalUntil::M129);
+  CHECK(defer_stage_ == DeferStage::kNotDeferring);
+  CHECK(stage != DeferStage::kNotDeferring);
   defer_stage_ = stage;
   last_defer_timestamp_ = base::TimeTicks::Now();
 }
 
 void ChildFrameNavigationFilteringThrottle::UpdateDeferInfo() {
-  CHECK(defer_stage_ != DeferStage::kNotDeferring, base::NotFatalUntil::M129);
-  CHECK(!last_defer_timestamp_.is_null(), base::NotFatalUntil::M129);
+  CHECK(defer_stage_ != DeferStage::kNotDeferring);
+  CHECK(!last_defer_timestamp_.is_null());
   total_defer_time_ += base::TimeTicks::Now() - last_defer_timestamp_;
   defer_stage_ = DeferStage::kNotDeferring;
 }
diff --git a/components/subresource_filter/content/shared/browser/ruleset_publisher.cc b/components/subresource_filter/content/shared/browser/ruleset_publisher.cc
index 3780382f..c397df5 100644
--- a/components/subresource_filter/content/shared/browser/ruleset_publisher.cc
+++ b/components/subresource_filter/content/shared/browser/ruleset_publisher.cc
@@ -12,7 +12,6 @@
 #include "base/functional/bind.h"
 #include "base/location.h"
 #include "base/logging.h"
-#include "base/not_fatal_until.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/task/thread_pool.h"
@@ -37,8 +36,7 @@
           ruleset_config)) {
   best_effort_task_runner_ =
       content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT});
-  CHECK(best_effort_task_runner_->BelongsToCurrentThread(),
-        base::NotFatalUntil::M129);
+  CHECK(best_effort_task_runner_->BelongsToCurrentThread());
 }
 
 RulesetPublisher::~RulesetPublisher() = default;
@@ -57,8 +55,8 @@
 }
 
 void RulesetPublisher::PublishNewRulesetVersion(RulesetFilePtr ruleset_data) {
-  CHECK(ruleset_data, base::NotFatalUntil::M129);
-  CHECK(ruleset_data->IsValid(), base::NotFatalUntil::M129);
+  CHECK(ruleset_data);
+  CHECK(ruleset_data->IsValid());
   ruleset_data_.reset();
 
   // If Ad Tagging is running, then every request does a lookup and it's
@@ -91,7 +89,7 @@
 
 void RulesetPublisher::IndexAndStoreAndPublishRulesetIfNeeded(
     const UnindexedRulesetInfo& unindexed_ruleset_info) {
-  CHECK(ruleset_service_, base::NotFatalUntil::M129);
+  CHECK(ruleset_service_);
   ruleset_service_->IndexAndStoreAndPublishRulesetIfNeeded(
       unindexed_ruleset_info);
 }
diff --git a/components/subresource_filter/content/shared/browser/ruleset_service.cc b/components/subresource_filter/content/shared/browser/ruleset_service.cc
index 3651363..0cc96e4 100644
--- a/components/subresource_filter/content/shared/browser/ruleset_service.cc
+++ b/components/subresource_filter/content/shared/browser/ruleset_service.cc
@@ -17,7 +17,6 @@
 #include "base/location.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/not_fatal_until.h"
 #include "base/numerics/safe_conversions.h"
 #include "base/strings/strcat.h"
 #include "base/strings/string_number_conversions.h"
@@ -215,8 +214,7 @@
       is_initialized_(false),
       indexed_ruleset_base_dir_(indexed_ruleset_base_dir) {
   CHECK_NE(local_state_->GetInitializationStatus(),
-           PrefService::INITIALIZATION_STATUS_WAITING,
-           base::NotFatalUntil::M129);
+           PrefService::INITIALIZATION_STATUS_WAITING);
   publisher_ = publisher_factory.Create(this, std::move(blocking_task_runner));
   IndexedRulesetVersion most_recently_indexed_version(config.filter_tag);
   most_recently_indexed_version.ReadFromPrefs(local_state_);
@@ -230,8 +228,7 @@
     IndexedRulesetVersion(config.filter_tag).SaveToPrefs(local_state_);
   }
 
-  CHECK(publisher_->BestEffortTaskRunner()->BelongsToCurrentThread(),
-        base::NotFatalUntil::M129);
+  CHECK(publisher_->BestEffortTaskRunner()->BelongsToCurrentThread());
   publisher_->BestEffortTaskRunner()->PostTask(
       FROM_HERE, base::BindOnce(&RulesetService::FinishInitialization,
                                 weak_ptr_factory_.GetWeakPtr()));
@@ -352,7 +349,7 @@
     return IndexedRulesetVersion(config.filter_tag);
   }
 
-  CHECK(indexed_version.IsValid(), base::NotFatalUntil::M129);
+  CHECK(indexed_version.IsValid());
   return indexed_version;
 }
 
@@ -419,8 +416,7 @@
 
   // Creating a temporary directory also makes sure the path (except for the
   // final segment) gets created. ReplaceFile would not create the path.
-  CHECK(base::PathExists(indexed_ruleset_version_dir.DirName()),
-        base::NotFatalUntil::M129);
+  CHECK(base::PathExists(indexed_ruleset_version_dir.DirName()));
 
   // Need to manually delete the previously stored ruleset with the same
   // version, if any, as ReplaceFile would not overwrite a non-empty directory.
@@ -463,8 +459,7 @@
 void RulesetService::IndexAndStoreRuleset(
     const UnindexedRulesetInfo& unindexed_ruleset_info,
     WriteRulesetCallback success_callback) {
-  CHECK(!unindexed_ruleset_info.content_version.empty(),
-        base::NotFatalUntil::M129);
+  CHECK(!unindexed_ruleset_info.content_version.empty());
   background_task_runner_->PostTaskAndReplyWithResult(
       FROM_HERE,
       base::BindOnce(&RulesetService::IndexAndWriteRuleset, config_,
@@ -476,7 +471,7 @@
 
 void RulesetService::OnWrittenRuleset(WriteRulesetCallback result_callback,
                                       const IndexedRulesetVersion& version) {
-  CHECK(!result_callback.is_null(), base::NotFatalUntil::M129);
+  CHECK(!result_callback.is_null());
   if (!version.IsValid()) {
     return;
   }
diff --git a/components/subresource_filter/content/shared/browser/unindexed_ruleset_stream_generator.cc b/components/subresource_filter/content/shared/browser/unindexed_ruleset_stream_generator.cc
index bbdaeff..5dbdc44a 100644
--- a/components/subresource_filter/content/shared/browser/unindexed_ruleset_stream_generator.cc
+++ b/components/subresource_filter/content/shared/browser/unindexed_ruleset_stream_generator.cc
@@ -7,7 +7,6 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/files/file_path.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/core/browser/ruleset_version.h"
 #include "components/subresource_filter/core/common/copying_file_stream.h"
 #include "third_party/protobuf/src/google/protobuf/io/zero_copy_stream_impl.h"
@@ -20,10 +19,8 @@
     const UnindexedRulesetInfo& ruleset_info) {
   bool has_ruleset_file = !ruleset_info.ruleset_path.empty();
 
-  CHECK(has_ruleset_file || ruleset_info.resource_id,
-        base::NotFatalUntil::M129);
-  CHECK(!(has_ruleset_file && ruleset_info.resource_id),
-        base::NotFatalUntil::M129);
+  CHECK(has_ruleset_file || ruleset_info.resource_id);
+  CHECK(!(has_ruleset_file && ruleset_info.resource_id));
 
   if (has_ruleset_file) {
     GenerateStreamFromFile(ruleset_info.ruleset_path);
@@ -36,9 +33,9 @@
 
 void UnindexedRulesetStreamGenerator::GenerateStreamFromFile(
     base::FilePath ruleset_path) {
-  CHECK(!ruleset_stream_, base::NotFatalUntil::M129);
-  CHECK(!copying_stream_, base::NotFatalUntil::M129);
-  CHECK_EQ(ruleset_size_, -1, base::NotFatalUntil::M129);
+  CHECK(!ruleset_stream_);
+  CHECK(!copying_stream_);
+  CHECK_EQ(ruleset_size_, -1);
 
   base::File unindexed_ruleset_file(
       ruleset_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
diff --git a/components/subresource_filter/core/browser/async_document_subresource_filter.cc b/components/subresource_filter/core/browser/async_document_subresource_filter.cc
index 529372d5..c82c18cc 100644
--- a/components/subresource_filter/core/browser/async_document_subresource_filter.cc
+++ b/components/subresource_filter/core/browser/async_document_subresource_filter.cc
@@ -12,7 +12,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback.h"
 #include "base/location.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/core/browser/verified_ruleset_dealer.h"
 #include "components/subresource_filter/core/common/constants.h"
 #include "components/subresource_filter/core/common/document_subresource_filter.h"
@@ -30,7 +29,7 @@
     const url::Origin& parent_document_origin,
     const mojom::ActivationState& parent_activation_state,
     const MemoryMappedRuleset* ruleset) {
-  CHECK(ruleset, base::NotFatalUntil::M129);
+  CHECK(ruleset);
 
   IndexedRulesetMatcher matcher(ruleset->data());
   mojom::ActivationState activation_state = parent_activation_state;
@@ -67,8 +66,7 @@
     mojom::ActivationLevel activation_level,
     bool measure_performance)
     : document_url(std::move(document_url)) {
-  CHECK_NE(mojom::ActivationLevel::kDisabled, activation_level,
-           base::NotFatalUntil::M129);
+  CHECK_NE(mojom::ActivationLevel::kDisabled, activation_level);
   parent_activation_state.activation_level = activation_level;
   parent_activation_state.measure_performance = measure_performance;
 }
@@ -81,7 +79,7 @@
       parent_document_origin(std::move(parent_document_origin)),
       parent_activation_state(parent_activation_state) {
   CHECK_NE(mojom::ActivationLevel::kDisabled,
-           parent_activation_state.activation_level, base::NotFatalUntil::M129);
+           parent_activation_state.activation_level);
 }
 
 InitializationParams::~InitializationParams() = default;
@@ -99,8 +97,7 @@
     : task_runner_(ruleset_handle->task_runner()),
       core_(new Core(), base::OnTaskRunnerDeleter(task_runner_.get())) {
   CHECK_NE(mojom::ActivationLevel::kDisabled,
-           params.parent_activation_state.activation_level,
-           base::NotFatalUntil::M129);
+           params.parent_activation_state.activation_level);
 
   // Note: It is safe to post |ruleset_handle|'s VerifiedRuleset pointer,
   // because a task to delete it can only be posted to (and, therefore,
@@ -123,11 +120,11 @@
     std::string_view uma_tag)
     : task_runner_(ruleset_handle->task_runner()),
       core_(new Core(), base::OnTaskRunnerDeleter(task_runner_.get())) {
-  CHECK_NE(mojom::ActivationLevel::kDisabled, activation_state.activation_level,
-           base::NotFatalUntil::M129);
+  CHECK_NE(mojom::ActivationLevel::kDisabled,
+           activation_state.activation_level);
 
   VerifiedRuleset* verified_ruleset = ruleset_handle->ruleset_.get();
-  CHECK(verified_ruleset, base::NotFatalUntil::M129);
+  CHECK(verified_ruleset);
 
   // See previous constructor for the safety of posting |ruleset_handle|'s
   // VerifiedRuleset pointer.
@@ -162,7 +159,7 @@
       base::BindOnce(
           [](AsyncDocumentSubresourceFilter::Core* core,
              const GURL& subdocument_url) {
-            CHECK(core, base::NotFatalUntil::M129);
+            CHECK(core);
             DocumentSubresourceFilter* filter = core->filter();
             return filter
                        ? filter->GetLoadPolicy(
@@ -198,7 +195,7 @@
     const mojom::ActivationState& updated_page_state) {
   // DISABLED activation level implies that the ruleset is somehow invalid. Make
   // sure that we don't update the state in that case.
-  CHECK(has_activation_state(), base::NotFatalUntil::M129);
+  CHECK(has_activation_state());
   if (activation_state_->activation_level ==
       mojom::ActivationLevel::kDisabled) {
     return;
@@ -250,7 +247,7 @@
 
 void AsyncDocumentSubresourceFilter::Core::SetActivationState(
     const mojom::ActivationState& state) {
-  CHECK(filter_, base::NotFatalUntil::M129);
+  CHECK(filter_);
   filter_->set_activation_state(state);
 }
 
@@ -259,7 +256,7 @@
     VerifiedRuleset* verified_ruleset,
     std::string_view uma_tag) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(verified_ruleset, base::NotFatalUntil::M129);
+  CHECK(verified_ruleset);
 
   if (!verified_ruleset->Get()) {
     return mojom::ActivationState();
@@ -269,8 +266,8 @@
       params.document_url, params.parent_document_origin,
       params.parent_activation_state, verified_ruleset->Get());
 
-  CHECK_NE(mojom::ActivationLevel::kDisabled, activation_state.activation_level,
-           base::NotFatalUntil::M129);
+  CHECK_NE(mojom::ActivationLevel::kDisabled,
+           activation_state.activation_level);
   filter_.emplace(url::Origin::Create(params.document_url), activation_state,
                   verified_ruleset->Get(), uma_tag);
 
@@ -283,7 +280,7 @@
     VerifiedRuleset* verified_ruleset,
     std::string_view uma_tag) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(verified_ruleset, base::NotFatalUntil::M129);
+  CHECK(verified_ruleset);
 
   // Avoids a crash in the rare case that the ruleset's status has changed to
   // unavailable/corrupt since the caller checked.
@@ -292,8 +289,8 @@
     return;
   }
 
-  CHECK_NE(mojom::ActivationLevel::kDisabled, activation_state.activation_level,
-           base::NotFatalUntil::M129);
+  CHECK_NE(mojom::ActivationLevel::kDisabled,
+           activation_state.activation_level);
   filter_.emplace(inherited_document_origin, activation_state,
                   verified_ruleset->Get(), uma_tag);
 }
diff --git a/components/subresource_filter/core/browser/verified_ruleset_dealer.cc b/components/subresource_filter/core/browser/verified_ruleset_dealer.cc
index 27cb04fe..f576f92 100644
--- a/components/subresource_filter/core/browser/verified_ruleset_dealer.cc
+++ b/components/subresource_filter/core/browser/verified_ruleset_dealer.cc
@@ -11,7 +11,6 @@
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/location.h"
-#include "base/not_fatal_until.h"
 #include "base/notreached.h"
 #include "base/task/sequenced_task_runner.h"
 #include "base/trace_event/trace_event.h"
@@ -141,7 +140,7 @@
 
 void VerifiedRuleset::Initialize(VerifiedRulesetDealer* dealer) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(dealer, base::NotFatalUntil::M129);
+  CHECK(dealer);
   ruleset_ = dealer->GetRuleset();
 }
 
diff --git a/components/subresource_filter/core/common/document_subresource_filter.cc b/components/subresource_filter/core/common/document_subresource_filter.cc
index 44f4d1d6..a9321d5 100644
--- a/components/subresource_filter/core/common/document_subresource_filter.cc
+++ b/components/subresource_filter/core/common/document_subresource_filter.cc
@@ -11,7 +11,6 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/strcat.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
@@ -34,7 +33,7 @@
       ruleset_matcher_(ruleset_->data()),
       uma_tag_(uma_tag) {
   CHECK_NE(activation_state_.activation_level,
-           mojom::ActivationLevel::kDisabled, base::NotFatalUntil::M129);
+           mojom::ActivationLevel::kDisabled);
   if (!activation_state_.filtering_disabled_for_document) {
     document_origin_ =
         std::make_unique<FirstPartyOrigin>(std::move(document_origin));
@@ -83,11 +82,11 @@
       });
 
   ++statistics_.num_loads_evaluated;
-  CHECK(document_origin_, base::NotFatalUntil::M129);
+  CHECK(document_origin_);
   LoadPolicy result = ruleset_matcher_.GetLoadPolicyForResourceLoad(
       subresource_url, *document_origin_, subresource_type,
       activation_state_.generic_blocking_rules_disabled);
-  CHECK_NE(LoadPolicy::WOULD_DISALLOW, result, base::NotFatalUntil::M129);
+  CHECK_NE(LoadPolicy::WOULD_DISALLOW, result);
   if (result == LoadPolicy::DISALLOW) {
     ++statistics_.num_loads_matching_rules;
     if (activation_state_.activation_level ==
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc
index 0ecc10e..6e3c34d 100644
--- a/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -7,7 +7,6 @@
 #include "base/check.h"
 #include "base/hash/hash.h"
 #include "base/metrics/histogram_functions.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/strcat.h"
 #include "base/trace_event/trace_event.h"
 #include "components/subresource_filter/core/common/first_party_origin.h"
@@ -82,7 +81,7 @@
     blocklist_.IndexUrlRule(offset);
   } else {
     const auto* flat_rule = flatbuffers::GetTemporaryPointer(builder_, offset);
-    CHECK(flat_rule, base::NotFatalUntil::M129);
+    CHECK(flat_rule);
     if (flat_rule->element_types()) {
       allowlist_.IndexUrlRule(offset);
     }
diff --git a/components/subresource_filter/core/common/memory_mapped_ruleset.cc b/components/subresource_filter/core/common/memory_mapped_ruleset.cc
index 877caf1..53afa5e 100644
--- a/components/subresource_filter/core/common/memory_mapped_ruleset.cc
+++ b/components/subresource_filter/core/common/memory_mapped_ruleset.cc
@@ -7,7 +7,6 @@
 #include <utility>
 
 #include "base/check.h"
-#include "base/not_fatal_until.h"
 
 namespace subresource_filter {
 
@@ -26,7 +25,7 @@
       !ruleset->ruleset_.Initialize(std::move(ruleset_file))) {
     return nullptr;
   }
-  CHECK(ruleset->ruleset_.IsValid(), base::NotFatalUntil::M129);
+  CHECK(ruleset->ruleset_.IsValid());
   return ruleset;
 }
 
diff --git a/components/subresource_filter/core/common/ruleset_dealer.cc b/components/subresource_filter/core/common/ruleset_dealer.cc
index 63ad55c7..1ff02a0 100644
--- a/components/subresource_filter/core/common/ruleset_dealer.cc
+++ b/components/subresource_filter/core/common/ruleset_dealer.cc
@@ -5,7 +5,6 @@
 #include "components/subresource_filter/core/common/ruleset_dealer.h"
 
 #include "base/check.h"
-#include "base/not_fatal_until.h"
 #include "components/subresource_filter/core/common/memory_mapped_ruleset.h"
 
 namespace subresource_filter {
@@ -18,7 +17,7 @@
 
 void RulesetDealer::SetRulesetFile(base::File ruleset_file) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  CHECK(ruleset_file.IsValid(), base::NotFatalUntil::M129);
+  CHECK(ruleset_file.IsValid());
   ruleset_file_ = std::move(ruleset_file);
   weak_cached_ruleset_.reset();
 }
diff --git a/components/subresource_filter/core/common/unindexed_ruleset.cc b/components/subresource_filter/core/common/unindexed_ruleset.cc
index c76b9de..1522a097d 100644
--- a/components/subresource_filter/core/common/unindexed_ruleset.cc
+++ b/components/subresource_filter/core/common/unindexed_ruleset.cc
@@ -6,7 +6,6 @@
 
 #include "base/check.h"
 #include "base/check_op.h"
-#include "base/not_fatal_until.h"
 #include "base/numerics/safe_conversions.h"
 #include "components/url_pattern_index/proto/rules.pb.h"
 #include "third_party/protobuf/src/google/protobuf/io/coded_stream.h"
@@ -45,23 +44,22 @@
     : coded_stream_(stream), max_rules_per_chunk_(max_rules_per_chunk) {}
 
 UnindexedRulesetWriter::~UnindexedRulesetWriter() {
-  CHECK_EQ(pending_chunk_.url_rules_size(), 0, base::NotFatalUntil::M129);
-  CHECK_EQ(pending_chunk_.css_rules_size(), 0, base::NotFatalUntil::M129);
+  CHECK_EQ(pending_chunk_.url_rules_size(), 0);
+  CHECK_EQ(pending_chunk_.css_rules_size(), 0);
 }
 
 bool UnindexedRulesetWriter::AddUrlRule(const proto::UrlRule& rule) {
-  CHECK(!had_error(), base::NotFatalUntil::M129);
+  CHECK(!had_error());
   pending_chunk_.add_url_rules()->CopyFrom(rule);
   if (pending_chunk_.url_rules_size() >= max_rules_per_chunk_) {
-    CHECK_EQ(pending_chunk_.url_rules_size(), max_rules_per_chunk_,
-             base::NotFatalUntil::M129);
+    CHECK_EQ(pending_chunk_.url_rules_size(), max_rules_per_chunk_);
     return WritePendingChunk();
   }
   return true;
 }
 
 bool UnindexedRulesetWriter::Finish() {
-  CHECK(!had_error(), base::NotFatalUntil::M129);
+  CHECK(!had_error());
   const bool success = !pending_chunk_.url_rules_size() || WritePendingChunk();
   if (success) {
     coded_stream_.Trim();
@@ -70,8 +68,8 @@
 }
 
 bool UnindexedRulesetWriter::WritePendingChunk() {
-  CHECK(!had_error(), base::NotFatalUntil::M129);
-  CHECK_GT(pending_chunk_.url_rules_size(), 0, base::NotFatalUntil::M129);
+  CHECK(!had_error());
+  CHECK_GT(pending_chunk_.url_rules_size(), 0);
 
   proto::FilteringRules chunk;
   chunk.Swap(&pending_chunk_);
diff --git a/components/subresource_filter/tools/rule_parser/rule.cc b/components/subresource_filter/tools/rule_parser/rule.cc
index a8759b2f..582a025 100644
--- a/components/subresource_filter/tools/rule_parser/rule.cc
+++ b/components/subresource_filter/tools/rule_parser/rule.cc
@@ -11,7 +11,6 @@
 
 #include "base/check_op.h"
 #include "base/logging.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/string_util.h"
 
 namespace subresource_filter {
@@ -277,8 +276,7 @@
     if (rule.element_types() &
         type_mask_for(url_pattern_index::proto::ELEMENT_TYPE_POPUP)) {
       const auto& popup_type = kElementTypes[11];
-      CHECK_EQ(url_pattern_index::proto::ELEMENT_TYPE_POPUP, popup_type.type,
-               base::NotFatalUntil::M129);
+      CHECK_EQ(url_pattern_index::proto::ELEMENT_TYPE_POPUP, popup_type.type);
       options.push_back(popup_type.name);
     }
   }
@@ -294,8 +292,7 @@
   // element_types == kDefaultElementTypes instead of 0.
   if (!rule.element_types() && !rule.activation_types()) {
     const auto& image_type = kElementTypes[2];
-    CHECK_EQ(url_pattern_index::proto::ELEMENT_TYPE_IMAGE, image_type.type,
-             base::NotFatalUntil::M129);
+    CHECK_EQ(url_pattern_index::proto::ELEMENT_TYPE_IMAGE, image_type.type);
     options.push_back(image_type.name);
     options.push_back(std::string("~") + image_type.name);
   }
diff --git a/components/subresource_filter/tools/rule_parser/rule_parser.cc b/components/subresource_filter/tools/rule_parser/rule_parser.cc
index f1ce3cf..6c54f8e 100644
--- a/components/subresource_filter/tools/rule_parser/rule_parser.cc
+++ b/components/subresource_filter/tools/rule_parser/rule_parser.cc
@@ -12,7 +12,6 @@
 #include "base/check.h"
 #include "base/check_op.h"
 #include "base/logging.h"
-#include "base/not_fatal_until.h"
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "components/subresource_filter/tools/rule_parser/rule_options.h"
@@ -71,8 +70,8 @@
 
     // Creates a generic option.
     OptionDetails(OptionType type, int flags) : type(type), flags(flags) {
-      CHECK_NE(type, OPTION_ELEMENT_TYPE, base::NotFatalUntil::M129);
-      CHECK_NE(type, OPTION_ACTIVATION_TYPE, base::NotFatalUntil::M129);
+      CHECK_NE(type, OPTION_ELEMENT_TYPE);
+      CHECK_NE(type, OPTION_ACTIVATION_TYPE);
     }
 
     bool requires_value() const { return flags & FLAG_REQUIRES_VALUE; }
@@ -168,7 +167,7 @@
 void KeywordMap::AddOption(std::string_view name,
                            const OptionDetails& details) {
   auto inserted = options_.insert(std::make_pair(std::string(name), details));
-  CHECK(inserted.second, base::NotFatalUntil::M129);
+  CHECK(inserted.second);
 }
 
 KeywordMap* GetKeywordsMapSingleton() {
@@ -326,7 +325,7 @@
   bool has_seen_element_or_activation_type = false;
   for (std::string_view piece : base::SplitStringPiece(
            options, ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
-    CHECK(!piece.empty(), base::NotFatalUntil::M129);
+    CHECK(!piece.empty());
 
     TriState tri_state = TriState::YES;
     if (base::StartsWith(piece, "~", base::CompareCase::SENSITIVE)) {
@@ -389,7 +388,7 @@
           }
           url_rule_.type_mask |= type_mask_for(option_details->element_type);
         } else {
-          CHECK(tri_state == TriState::NO, base::NotFatalUntil::M129);
+          CHECK(tri_state == TriState::NO);
           url_rule_.type_mask &= ~type_mask_for(option_details->element_type);
         }
         has_seen_element_or_activation_type = true;
@@ -429,13 +428,12 @@
 
   // Check for a list of domains.
   if (css_section_start) {
-    CHECK(css_section_start != std::string_view::npos,
-          base::NotFatalUntil::M129);
+    CHECK(css_section_start != std::string_view::npos);
     auto pieces = base::SplitStringPiece(part.substr(0, css_section_start), ",",
                                          base::TRIM_WHITESPACE,
                                          base::SPLIT_WANT_NONEMPTY);
     for (std::string_view domain : pieces) {
-      CHECK(!domain.empty(), base::NotFatalUntil::M129);
+      CHECK(!domain.empty());
       css_rule_.domains.push_back(std::string(domain));
     }
   }
@@ -468,8 +466,8 @@
 void RuleParser::SetParseError(ParseError::ErrorCode code,
                                std::string_view origin,
                                const char* error_begin) {
-  CHECK(code != ParseError::NONE, base::NotFatalUntil::M129);
-  CHECK(error_begin >= origin.data(), base::NotFatalUntil::M129);
+  CHECK(code != ParseError::NONE);
+  CHECK(error_begin >= origin.data());
 
   parse_error_.error_code = code;
   parse_error_.line = std::string(origin);
diff --git a/components/variations/variations_ids_provider.cc b/components/variations/variations_ids_provider.cc
index 35a3faf..384ad77e 100644
--- a/components/variations/variations_ids_provider.cc
+++ b/components/variations/variations_ids_provider.cc
@@ -229,7 +229,7 @@
 
 void VariationsIdsProvider::AddObserver(Observer* observer) {
   base::AutoLock scoped_lock(lock_);
-  CHECK(!base::Contains(observer_list_, observer), base::NotFatalUntil::M126);
+  CHECK(!base::Contains(observer_list_, observer));
   observer_list_.push_back(observer);
 }
 
diff --git a/components/viz/common/resources/shared_image_format.cc b/components/viz/common/resources/shared_image_format.cc
index 181cbe9..2e8d568 100644
--- a/components/viz/common/resources/shared_image_format.cc
+++ b/components/viz/common/resources/shared_image_format.cc
@@ -131,11 +131,6 @@
 // that operator==() is just memcmp(). That would probably require something
 // like manually packing bits into a single uint64_t for storage.
 
-bool SharedImageFormat::IsBitmapFormatSupported() const {
-  return is_single_plane() &&
-         singleplanar_format() == mojom::SingleplanarFormat::RGBA_8888;
-}
-
 int SharedImageFormat::NumberOfPlanes() const {
   if (is_single_plane()) {
     return 1;
diff --git a/components/viz/common/resources/shared_image_format.h b/components/viz/common/resources/shared_image_format.h
index e50178ff..6ae7a49 100644
--- a/components/viz/common/resources/shared_image_format.h
+++ b/components/viz/common/resources/shared_image_format.h
@@ -130,10 +130,6 @@
 #endif
   }
 
-  // Returns whether the resource format can be used as a software bitmap for
-  // export to the display compositor.
-  bool IsBitmapFormatSupported() const;
-
   // Return the number of planes associated with the format.
   int NumberOfPlanes() const;
 
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
index e92d889..933abcca 100644
--- a/content/browser/BUILD.gn
+++ b/content/browser/BUILD.gn
@@ -2407,6 +2407,8 @@
     "webid/fedcm_accounts_fetcher.h",
     "webid/fedcm_config_fetcher.cc",
     "webid/fedcm_config_fetcher.h",
+    "webid/fedcm_idp_registration_handler.cc",
+    "webid/fedcm_idp_registration_handler.h",
     "webid/fedcm_mappers.cc",
     "webid/fedcm_mappers.h",
     "webid/fedcm_metrics.cc",
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc
index 27841d4..f4283806 100644
--- a/content/browser/child_process_launcher.cc
+++ b/content/browser/child_process_launcher.cc
@@ -192,9 +192,11 @@
     // process.
     auto* port_provider = ChildProcessTaskPortProvider::GetInstance();
     CHECK(port_provider);
-    CHECK(port_provider->TaskForHandle(process_.process.Handle()) ==
-          MACH_PORT_NULL);
-    scoped_port_provider_observation_.Observe(port_provider);
+    if (port_provider->TaskForHandle(process_.process.Handle()) ==
+        MACH_PORT_NULL) {
+      // In the most common case, the task port is not available at launch time.
+      scoped_port_provider_observation_.Observe(port_provider);
+    }
 #endif
 
     // Note:: May delete |this|.
@@ -220,9 +222,15 @@
     return;
   }
 
-  if (process_.process.Handle() == process_handle && priority_) {
+  // Ignore notifications about different processes.
+  if (process_.process.Handle() != process_handle) {
+    return;
+  }
+
+  scoped_port_provider_observation_.Reset();
+
+  if (priority_) {
     SetProcessPriorityImpl(*priority_);
-    scoped_port_provider_observation_.Reset();
   }
 }
 #endif
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
index 6041f1e..e5795154 100644
--- a/content/browser/web_contents/web_contents_impl.cc
+++ b/content/browser/web_contents/web_contents_impl.cc
@@ -3231,6 +3231,7 @@
 }
 
 void WebContentsImpl::AttachUnownedInnerWebContents(
+    base::PassKey<UnownedInnerWebContentsClient>,
     WebContents* inner_web_contents,
     RenderFrameHost* render_frame_host) {
   AttachInnerWebContentsImpl(inner_web_contents, render_frame_host,
@@ -3358,6 +3359,12 @@
 }
 
 void WebContentsImpl::DetachUnownedInnerWebContents(
+    base::PassKey<UnownedInnerWebContentsClient>,
+    WebContents* inner_web_contents) {
+  DetachUnownedInnerWebContents(inner_web_contents);
+}
+
+void WebContentsImpl::DetachUnownedInnerWebContents(
     WebContents* inner_web_contents) {
   CHECK(base::FeatureList::IsEnabled(features::kAttachUnownedInnerWebContents));
   CHECK(node_.IsUnownedInnerWebContents(inner_web_contents));
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
index bb00cc8..478c9df 100644
--- a/content/browser/web_contents/web_contents_impl.h
+++ b/content/browser/web_contents/web_contents_impl.h
@@ -483,9 +483,13 @@
       std::unique_ptr<WebContents> inner_web_contents,
       RenderFrameHost* render_frame_host,
       bool is_full_page) override;
-  void AttachUnownedInnerWebContents(WebContents* inner_web_contents,
-    RenderFrameHost* render_frame_host) override;
-  void DetachUnownedInnerWebContents(WebContents* inner_web_contents) override;
+  void AttachUnownedInnerWebContents(
+      base::PassKey<UnownedInnerWebContentsClient>,
+      WebContents* inner_web_contents,
+      RenderFrameHost* render_frame_host) override;
+  void DetachUnownedInnerWebContents(
+      base::PassKey<UnownedInnerWebContentsClient>,
+      WebContents* inner_web_contents) override;
   void AttachGuestPage(std::unique_ptr<GuestPageHolder> guest_page,
                        RenderFrameHost* outer_render_frame_host) override;
   bool IsInnerWebContentsForGuest() override;
@@ -1997,6 +2001,10 @@
     bool is_full_page,
     bool should_take_ownership);
 
+  // Internal implementation of DetachUnownedInnerWebContents() that does not
+  // require a pass key. Called by ~WebContentsImpl.
+  void DetachUnownedInnerWebContents(WebContents* inner_web_contents);
+
   // Called just after an inner web contents is attached.
   void InnerWebContentsAttached(WebContents* inner_web_contents);
 
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
index 0f21fe9..03f2182 100644
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
@@ -69,6 +69,7 @@
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/render_widget_host_view.h"
 #include "content/public/browser/site_isolation_policy.h"
+#include "content/public/browser/unowned_inner_web_contents_client.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_contents_delegate.h"
 #include "content/public/browser/web_contents_observer.h"
@@ -4492,7 +4493,9 @@
     run_loop.Quit();
     return false;
   }));
-  outer_wc->AttachUnownedInnerWebContents(inner_wc.get(), iframe_rfh);
+  outer_wc->AttachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get(), iframe_rfh);
 
   // The outer RFH was unloaded while attaching the inner WC. The RFH was marked
   // as offline by the asynchronous UnloadACK().
@@ -4551,11 +4554,15 @@
   WebContentsImpl* inner_wc_impl =
       static_cast<WebContentsImpl*>(inner_wc.get());
   ASSERT_TRUE(NavigateToURL(inner_wc.get(), inner_url));
-  outer_wc->AttachUnownedInnerWebContents(inner_wc.get(), iframe_rfh);
+  outer_wc->AttachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get(), iframe_rfh);
   ASSERT_EQ(outer_wc, inner_wc->GetOuterWebContents());
 
   // Detach the inner WebContents
-  outer_wc->DetachUnownedInnerWebContents(inner_wc.get());
+  outer_wc->DetachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get());
 
   // Verify that the connection is broken.
   EXPECT_EQ(nullptr, inner_wc->GetOuterWebContents());
@@ -4603,13 +4610,19 @@
 
   // Attach the inner WebContents
   ASSERT_TRUE(NavigateToURL(inner_wc.get(), inner_url));
-  outer_wc->AttachUnownedInnerWebContents(inner_wc.get(), iframe_rfh);
+  outer_wc->AttachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get(), iframe_rfh);
   ASSERT_EQ(outer_wc, inner_wc->GetOuterWebContents());
 
   // Detach and then reattach the inner WebContents
-  outer_wc->DetachUnownedInnerWebContents(inner_wc.get());
+  outer_wc->DetachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get());
   ASSERT_EQ(nullptr, inner_wc->GetOuterWebContents());
-  outer_wc->AttachUnownedInnerWebContents(inner_wc.get(), iframe_rfh);
+  outer_wc->AttachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get(), iframe_rfh);
   ASSERT_EQ(outer_wc, inner_wc->GetOuterWebContents());
 }
 
@@ -4637,7 +4650,9 @@
   ASSERT_TRUE(NavigateToURL(inner_wc.get(), inner_url));
 
   // Attach the inner WebContents
-  outer_wc->AttachUnownedInnerWebContents(inner_wc.get(), iframe_rfh);
+  outer_wc->AttachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get(), iframe_rfh);
   ASSERT_EQ(outer_wc, inner_wc->GetOuterWebContents());
 
   // Verify RenderFrameHost is created for the inner WebContents
@@ -4674,7 +4689,9 @@
             rfh_b2->GetView());
 
   // Detach the inner WebContents
-  outer_wc->DetachUnownedInnerWebContents(inner_wc.get());
+  outer_wc->DetachUnownedInnerWebContents(
+      UnownedInnerWebContentsClient::GetPassKeyForTesting(),
+      inner_wc.get());
   ASSERT_EQ(nullptr, inner_wc->GetOuterWebContents());
 
   // Verify that the inner WebContents's RFHs are still alive.
@@ -4705,7 +4722,6 @@
   EXPECT_TRUE(static_cast<RenderViewHostImpl*>(
       rfh_b2->GetRenderViewHost())->IsRenderViewLive());
 }
-
 #endif  // !BUILDFLAG(IS_ANDROID)
 
 IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
diff --git a/content/browser/webid/fedcm_accounts_fetcher.cc b/content/browser/webid/fedcm_accounts_fetcher.cc
index 0ba3094..9d69260 100644
--- a/content/browser/webid/fedcm_accounts_fetcher.cc
+++ b/content/browser/webid/fedcm_accounts_fetcher.cc
@@ -215,13 +215,9 @@
       }
     }
 
-    // The login url should be valid unless IdP login status API is
-    // disabled.
-    if (idp_info->metadata.idp_login_url.is_valid()) {
-      federated_auth_request_impl_->SetIdpLoginInfo(
-          idp_info->metadata.idp_login_url, idp_info->provider->login_hint,
-          idp_info->provider->domain_hint);
-    }
+    federated_auth_request_impl_->SetIdpLoginInfo(
+        idp_info->metadata.idp_login_url, idp_info->provider->login_hint,
+        idp_info->provider->domain_hint);
 
     // Make sure that we don't fetch accounts if the IDP sign-in bit is
     // reset to false during the API call. e.g. by the login/logout HEADER.
diff --git a/content/browser/webid/fedcm_idp_registration_handler.cc b/content/browser/webid/fedcm_idp_registration_handler.cc
new file mode 100644
index 0000000..0d4147a
--- /dev/null
+++ b/content/browser/webid/fedcm_idp_registration_handler.cc
@@ -0,0 +1,36 @@
+// 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 "content/browser/webid/fedcm_idp_registration_handler.h"
+
+#include "content/browser/webid/fedcm_config_fetcher.h"
+#include "content/browser/webid/idp_network_request_manager.h"
+#include "url/gurl.h"
+
+namespace content {
+
+FedCmIdpRegistrationHandler::FedCmIdpRegistrationHandler(
+    RenderFrameHost& render_frame_host,
+    IdpNetworkRequestManager* network_manager,
+    const GURL& idp_url)
+    : render_frame_host_(render_frame_host),
+      network_manager_(network_manager),
+      idp_url_(idp_url) {}
+
+FedCmIdpRegistrationHandler::~FedCmIdpRegistrationHandler() = default;
+
+void FedCmIdpRegistrationHandler::FetchConfig(
+    FedCmConfigFetcher::RequesterCallback callback) {
+  std::vector<FedCmConfigFetcher::FetchRequest> fetch_requests;
+  fetch_requests.emplace_back(idp_url_,
+                              /*force_skip_well_known_enforcement=*/true);
+
+  config_fetcher_ = std::make_unique<FedCmConfigFetcher>(*render_frame_host_,
+                                                         network_manager_);
+  config_fetcher_->Start(fetch_requests, blink::mojom::RpMode::kPassive,
+                         /*icon_ideal_size=*/0, /*icon_minimum_size=*/0,
+                         std::move(callback));
+}
+
+}  // namespace content
diff --git a/content/browser/webid/fedcm_idp_registration_handler.h b/content/browser/webid/fedcm_idp_registration_handler.h
new file mode 100644
index 0000000..6b998c1a
--- /dev/null
+++ b/content/browser/webid/fedcm_idp_registration_handler.h
@@ -0,0 +1,39 @@
+// 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 CONTENT_BROWSER_WEBID_FEDCM_IDP_REGISTRATION_HANDLER_H_
+#define CONTENT_BROWSER_WEBID_FEDCM_IDP_REGISTRATION_HANDLER_H_
+
+#include "content/browser/webid/fedcm_config_fetcher.h"
+#include "url/gurl.h"
+
+namespace content {
+
+class RenderFrameHost;
+
+class CONTENT_EXPORT FedCmIdpRegistrationHandler {
+ public:
+  FedCmIdpRegistrationHandler(RenderFrameHost& render_frame_host,
+                              IdpNetworkRequestManager* network_manager,
+                              const GURL& idp_url);
+  ~FedCmIdpRegistrationHandler();
+
+  FedCmIdpRegistrationHandler(const FedCmIdpRegistrationHandler&) = delete;
+  FedCmIdpRegistrationHandler& operator=(const FedCmIdpRegistrationHandler&) =
+      delete;
+
+  void FetchConfig(FedCmConfigFetcher::RequesterCallback callback);
+
+ private:
+  // Owned by FederatedAuthRequestImpl.
+  raw_ref<RenderFrameHost> render_frame_host_;
+  raw_ptr<IdpNetworkRequestManager> network_manager_;
+
+  GURL idp_url_;
+  std::unique_ptr<FedCmConfigFetcher> config_fetcher_;
+};
+
+}  // namespace content
+
+#endif  // CONTENT_BROWSER_WEBID_FEDCM_IDP_REGISTRATION_HANDLER_H_
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc
index 0798b89..5458912 100644
--- a/content/browser/webid/federated_auth_request_impl.cc
+++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -677,6 +677,29 @@
     return;
   }
 
+  if (!network_manager_) {
+    network_manager_ = CreateNetworkManager();
+  }
+
+  fedcm_idp_registration_handler_ =
+      std::make_unique<FedCmIdpRegistrationHandler>(
+          render_frame_host(), network_manager_.get(), idp);
+  fedcm_idp_registration_handler_->FetchConfig(
+      base::BindOnce(&FederatedAuthRequestImpl::OnIdpRegistrationConfigFetched,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(callback), idp));
+}
+
+void FederatedAuthRequestImpl::OnIdpRegistrationConfigFetched(
+    RegisterIdPCallback callback,
+    const GURL& idp,
+    std::vector<FedCmConfigFetcher::FetchResult> fetch_results) {
+  CHECK_EQ(fetch_results.size(), 1u);
+  fedcm_idp_registration_handler_.reset();
+  if (fetch_results[0].error) {
+    std::move(callback).Run(RegisterIdpStatus::kErrorInvalidConfig);
+    return;
+  }
+
   if (!request_dialog_controller_) {
     request_dialog_controller_ = CreateDialogController();
   }
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h
index 709df42..768a918 100644
--- a/content/browser/webid/federated_auth_request_impl.h
+++ b/content/browser/webid/federated_auth_request_impl.h
@@ -16,6 +16,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/time/time.h"
 #include "content/browser/webid/fedcm_accounts_fetcher.h"
+#include "content/browser/webid/fedcm_idp_registration_handler.h"
 #include "content/browser/webid/fedcm_metrics.h"
 #include "content/browser/webid/fedcm_url_computations.h"
 #include "content/browser/webid/federated_sd_jwt_handler.h"
@@ -429,6 +430,10 @@
       std::optional<IdpNetworkRequestManager::FedCmErrorUrlType>
           error_url_type);
 
+  void OnIdpRegistrationConfigFetched(
+      RegisterIdPCallback callback,
+      const GURL& idp,
+      std::vector<FedCmConfigFetcher::FetchResult> fetch_results);
   void OnRegisterIdPPermissionResponse(RegisterIdPCallback callback,
                                        const GURL& idp,
                                        bool accepted);
@@ -519,6 +524,8 @@
 
   std::unique_ptr<FederatedSdJwtHandler> federated_sdjwt_handler_;
 
+  std::unique_ptr<FedCmIdpRegistrationHandler> fedcm_idp_registration_handler_;
+
   // Set of pending user info requests.
   base::flat_set<std::unique_ptr<FederatedAuthUserInfoRequest>>
       user_info_requests_;
diff --git a/content/browser/webid/federated_auth_request_impl_registry_unittest.cc b/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
index f9ee54d2..ded42fa 100644
--- a/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
+++ b/content/browser/webid/federated_auth_request_impl_registry_unittest.cc
@@ -54,6 +54,38 @@
   }
 };
 
+class TestIdpNetworkRequestManager : public MockIdpNetworkRequestManager {
+ public:
+  void FetchWellKnown(const GURL& provider,
+                      FetchWellKnownCallback callback) override {
+    // Assume that the well-known file is not found for a registered IDP.
+    IdpNetworkRequestManager::WellKnown well_known;
+    FetchStatus fetch_status = {ParseStatus::kHttpNotFoundError, 404};
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE,
+        base::BindOnce(std::move(callback), fetch_status, well_known));
+  }
+
+  void FetchConfig(const GURL& provider,
+                   blink::mojom::RpMode rp_mode,
+                   int idp_brand_icon_ideal_size,
+                   int idp_brand_icon_minimum_size,
+                   FetchConfigCallback callback) override {
+    IdpNetworkRequestManager::Endpoints endpoints;
+    endpoints.token = GURL("https://idp.example/token");
+    endpoints.accounts = GURL("https://idp.example/accounts");
+
+    IdentityProviderMetadata idp_metadata;
+    idp_metadata.config_url = provider;
+    idp_metadata.idp_login_url = GURL("https://idp.example/login");
+    idp_metadata.types = {"idp-type"};
+    FetchStatus fetch_status = {ParseStatus::kSuccess, 200};
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback), fetch_status, endpoints,
+                                  idp_metadata));
+  }
+};
+
 }  // namespace
 
 class FederatedAuthRequestImplRegistryTest
@@ -86,6 +118,10 @@
         std::make_unique<NiceMock<MockIdentityRequestDialogController>>();
     federated_auth_request_impl_->SetDialogControllerForTests(
         std::move(mock_dialog_controller));
+    std::unique_ptr<TestIdpNetworkRequestManager> network_request_manager =
+        std::make_unique<TestIdpNetworkRequestManager>();
+    federated_auth_request_impl_->SetNetworkManagerForTests(
+        std::move(network_request_manager));
   }
 
   void TearDown() override {
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc
index 78755491..401e170 100644
--- a/content/browser/webid/idp_network_request_manager.cc
+++ b/content/browser/webid/idp_network_request_manager.cc
@@ -650,7 +650,7 @@
   idp_metadata.idp_login_url =
       ExtractEndpoint(provider, response, kLoginUrlKey);
 
-  if (IsFedCmIdPRegistrationEnabled()) {
+  if (IsFedCmDelegationEnabled()) {
     const base::Value::List* formats = response.FindList(kFormatsKey);
     if (formats) {
       for (const auto& format : *formats) {
@@ -1212,7 +1212,7 @@
 
   if (idp_blindness) {
     // IdP blindness can only be used when the feature is enabled.
-    DCHECK(IsFedCmIdPRegistrationEnabled());
+    DCHECK(IsFedCmDelegationEnabled());
     // We have to set this to a Origin: null because the underlying loader
     // will  not let us send a request without Origin header if the request
     // method is POST.
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc
index 7c2e7b0..5add42b8 100644
--- a/content/browser/webid/webid_browsertest.cc
+++ b/content/browser/webid/webid_browsertest.cc
@@ -937,6 +937,38 @@
   EXPECT_EQ(std::string(kToken), EvalJs(shell(), get_script));
 }
 
+IN_PROC_BROWSER_TEST_F(WebIdIdPRegistryBrowserTest,
+                       RegistrationFailsWithInvalidLoginUrl) {
+  GURL configURL = GURL(BaseIdpUrl());
+  auto details = BuildValidConfigDetails();
+  // Set this as empty so that the login URL is invalid.
+  details.login_url = "";
+  idp_server()->SetConfigResponseDetails(details);
+
+  auto mock = std::make_unique<
+      ::testing::NiceMock<MockIdentityRequestDialogController>>();
+  test_browser_client_->SetIdentityRequestDialogController(std::move(mock));
+
+  // We navigate to the IdP's configURL so that we can run
+  // the script below with the IdP's origin as the top level
+  // first party context.
+  EXPECT_TRUE(NavigateToURL(shell(), configURL));
+
+  std::string script = R"(
+        (async () => {
+          await IdentityProvider.register(')" +
+                       configURL.spec() + R"(');
+          // The permission was accepted if the promise resolves.
+          return true;
+        }) ()
+    )";
+
+  EXPECT_EQ("NotAllowedError: Invalid identity provider registration config.",
+            ExtractJsError(EvalJs(shell(), script)));
+
+  EXPECT_TRUE(sharing_context()->GetRegisteredIdPs().empty());
+}
+
 // Verify that IDP sign-in headers work.
 IN_PROC_BROWSER_TEST_F(WebIdIdpSigninStatusBrowserTest, IdpSigninToplevel) {
   GURL url = https_server().GetURL(kRpHostName, "/header/signin");
@@ -1913,9 +1945,6 @@
     std::vector<base::test::FeatureRef> features;
     features.push_back(features::kFedCm);
     features.push_back(features::kFedCmDelegation);
-    // Needs to reconcile well with the IdP Registration and Multi-IdP API
-    features.push_back(features::kFedCmIdPRegistration);
-    features.push_back(features::kFedCmMultipleIdentityProviders);
     scoped_feature_list_.InitWithFeatures(features, {});
     command_line->AppendSwitch(switches::kIgnoreCertificateErrors);
   }
diff --git a/content/common/features.cc b/content/common/features.cc
index 100617a5..e5fec52 100644
--- a/content/common/features.cc
+++ b/content/common/features.cc
@@ -29,13 +29,6 @@
              "AndroidDragDropOopif",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-// Whether to allow attaching an inner WebContents not owned by the outer
-// WebContents. This is for prototyping purposes and should not be enabled in
-// production.
-BASE_FEATURE(kAttachUnownedInnerWebContents,
-             "AttachUnownedInnerWebContents",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Synchronously continuing with navigation can lead to trying to start another
 // navigation synchronously while the first navigation is still being processed
 // on the stack. This results in re-entrancy which is unsafe and triggers a
diff --git a/content/common/features.h b/content/common/features.h
index 9c62eee..ccc1ab3 100644
--- a/content/common/features.h
+++ b/content/common/features.h
@@ -16,7 +16,6 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAllowContentInitiatedDataUrlNavigations);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAndroidDownloadableFontsMatching);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAndroidDragDropOopif);
-CONTENT_EXPORT BASE_DECLARE_FEATURE(kAttachUnownedInnerWebContents);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAvoidUnnecessaryBeforeUnloadCheckSync);
 // Please check the code comment on
 // ContentBrowserClient::SupportsAvoidUnnecessaryBeforeUnloadCheckSync() in the
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 081f2a1..2714f3b8 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -470,6 +470,8 @@
     "tts_controller.h",
     "tts_platform.h",
     "tts_utterance.h",
+    "unowned_inner_web_contents_client.cc",
+    "unowned_inner_web_contents_client.h",
     "url_data_source.cc",
     "url_data_source.h",
     "url_loader_request_interceptor.cc",
diff --git a/content/public/browser/unowned_inner_web_contents_client.cc b/content/public/browser/unowned_inner_web_contents_client.cc
new file mode 100644
index 0000000..ac25c5d4
--- /dev/null
+++ b/content/public/browser/unowned_inner_web_contents_client.cc
@@ -0,0 +1,21 @@
+// 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 "content/public/browser/unowned_inner_web_contents_client.h"
+
+namespace content {
+
+// static
+UnownedInnerWebContentsClient::PassKey
+UnownedInnerWebContentsClient::GetPassKeyForTesting() {
+  return GetPassKey();
+}
+
+// static
+UnownedInnerWebContentsClient::PassKey
+UnownedInnerWebContentsClient::GetPassKey() {
+  return PassKey();
+}
+
+}  // namespace content
diff --git a/content/public/browser/unowned_inner_web_contents_client.h b/content/public/browser/unowned_inner_web_contents_client.h
new file mode 100644
index 0000000..ef2822c9
--- /dev/null
+++ b/content/public/browser/unowned_inner_web_contents_client.h
@@ -0,0 +1,39 @@
+// 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 CONTENT_PUBLIC_BROWSER_UNOWNED_INNER_WEB_CONTENTS_CLIENT_H_
+#define CONTENT_PUBLIC_BROWSER_UNOWNED_INNER_WEB_CONTENTS_CLIENT_H_
+
+#include "base/types/pass_key.h"
+#include "content/common/content_export.h"
+
+namespace guest_contents {
+class GuestContentsHandle;
+}  // namespace guest_contents
+
+namespace content {
+
+// A static class that provides PassKeys for clients of unowned inner web
+// contents to use WebContents::AttachUnownedInnerWebContents() and
+// DetachUnownedInnerWebContents(). These APIs are experimental and are intended
+// to be used by //components/guest_contents only. If you intend to add new
+// clients, please reach out to //components/guest_contents owners and content
+// owners. See an explanation of guest-contents at crbug.com/415626990.
+class CONTENT_EXPORT UnownedInnerWebContentsClient {
+ public:
+  using PassKey = base::PassKey<UnownedInnerWebContentsClient>;
+
+  UnownedInnerWebContentsClient() = delete;
+
+  static PassKey GetPassKeyForTesting();
+
+ private:
+  friend class guest_contents::GuestContentsHandle;
+
+  static PassKey GetPassKey();
+};
+
+}  // namespace content
+
+#endif  // CONTENT_PUBLIC_BROWSER_UNOWNED_INNER_WEB_CONTENTS_CLIENT_H_
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
index 700e292..ab2df2f 100644
--- a/content/public/browser/web_contents.h
+++ b/content/public/browser/web_contents.h
@@ -124,6 +124,7 @@
 class RenderWidgetHostView;
 class ScreenOrientationDelegate;
 class SiteInstance;
+class UnownedInnerWebContentsClient;
 class WebContentsDelegate;
 class WebUI;
 struct DropData;
@@ -955,6 +956,7 @@
   // TODO(crbug.com/416609971): Remove this method once we find a way to attach
   // inner WebContents without using WebContents trees.
   virtual void AttachUnownedInnerWebContents(
+      base::PassKey<UnownedInnerWebContentsClient>,
       WebContents* inner_web_contents,
       RenderFrameHost* render_frame_host) = 0;
 
@@ -964,6 +966,7 @@
   // TODO(crbug.com/416609971): Remove this method once we find a way to attach
   // inner WebContents without using WebContents trees.
   virtual void DetachUnownedInnerWebContents(
+      base::PassKey<UnownedInnerWebContentsClient>,
       WebContents* inner_web_contents) = 0;
 
   // Attaches `guest_page` to the container frame `outer_render_frame_host`,
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index 75a5d885..41315d1 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -72,6 +72,13 @@
 const base::FeatureParam<bool> kAndroidSpareRendererKillWhenBackgrounded{
     &kAndroidWarmUpSpareRendererWithTimeout, "kill_when_backgrounded", false};
 
+// Whether to allow attaching an inner WebContents not owned by the outer
+// WebContents. This is for prototyping purposes and should not be enabled in
+// production.
+BASE_FEATURE(kAttachUnownedInnerWebContents,
+    "AttachUnownedInnerWebContents",
+    base::FEATURE_DISABLED_BY_DEFAULT);
+
 // Launches the audio service on the browser startup.
 BASE_FEATURE(kAudioServiceLaunchOnStartup,
              "AudioServiceLaunchOnStartup",
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index 5cf8fd3..d3d813f 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -45,6 +45,7 @@
     kAndroidSpareRendererMemoryThreshold;
 CONTENT_EXPORT extern const base::FeatureParam<bool>
     kAndroidSpareRendererKillWhenBackgrounded;
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kAttachUnownedInnerWebContents);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAudioServiceLaunchOnStartup);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAudioServiceOutOfProcess);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAudioServiceSandbox);
diff --git a/content/test/test_web_contents.h b/content/test/test_web_contents.h
index 3aee1810..f678753 100644
--- a/content/test/test_web_contents.h
+++ b/content/test/test_web_contents.h
@@ -246,7 +246,6 @@
                             const std::u16string& suggested_filename,
                             RenderFrameHost* rfh,
                             bool is_subresource) override;
-  void ReattachToOuterWebContentsFrame() override {}
   void SetPageFrozen(bool frozen) override;
   bool IsBackForwardCacheSupported() override;
   const std::optional<blink::mojom::PictureInPictureWindowOptions>&
diff --git a/gpu/ipc/client/gpu_channel_host.cc b/gpu/ipc/client/gpu_channel_host.cc
index 5ee6c2a..fd0aac0 100644
--- a/gpu/ipc/client/gpu_channel_host.cc
+++ b/gpu/ipc/client/gpu_channel_host.cc
@@ -381,7 +381,7 @@
 GpuChannelHost::ConnectionTracker::ConnectionTracker() = default;
 
 GpuChannelHost::ConnectionTracker::~ConnectionTracker() {
-  CHECK(observer_list_.empty(), base::NotFatalUntil::M126);
+  CHECK(observer_list_.empty());
 }
 
 void GpuChannelHost::ConnectionTracker::OnDisconnectedFromGpuProcess() {
@@ -392,7 +392,7 @@
 void GpuChannelHost::ConnectionTracker::AddObserver(
     GpuChannelLostObserver* obs) {
   AutoLock lock(channel_obs_lock_);
-  CHECK(!base::Contains(observer_list_, obs), base::NotFatalUntil::M126);
+  CHECK(!base::Contains(observer_list_, obs));
   observer_list_.push_back(obs);
 }
 
diff --git a/gpu/vulkan/android/vulkan_implementation_android.cc b/gpu/vulkan/android/vulkan_implementation_android.cc
index ffb15d28..9388b65b 100644
--- a/gpu/vulkan/android/vulkan_implementation_android.cc
+++ b/gpu/vulkan/android/vulkan_implementation_android.cc
@@ -5,7 +5,6 @@
 #include "gpu/vulkan/android/vulkan_implementation_android.h"
 
 #include "base/android/android_hardware_buffer_compat.h"
-#include "base/feature_list.h"
 #include "base/files/file_path.h"
 #include "base/functional/callback_helpers.h"
 #include "base/logging.h"
@@ -20,16 +19,6 @@
 #include "ui/gfx/gpu_memory_buffer.h"
 
 namespace gpu {
-namespace {
-
-// VK_KHR_external_memory_capabilities + VK_KHR_external_semaphore_capabilities
-// were promoted in Vulkan 1.1 so we shouldn't need to list them in the required
-// extensions.
-BASE_FEATURE(kRequirePromotedVulkanExtensions,
-             "RequirePromotedVulkanExtensions",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
-}  // namespace
 
 VulkanImplementationAndroid::VulkanImplementationAndroid() = default;
 
@@ -39,13 +28,6 @@
   DCHECK(using_surface);
   std::vector<const char*> required_extensions = {
       VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_ANDROID_SURFACE_EXTENSION_NAME};
-  if (base::FeatureList::IsEnabled(kRequirePromotedVulkanExtensions)) {
-    required_extensions.push_back(
-        VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME);
-    required_extensions.push_back(
-        VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME);
-  }
-
   return vulkan_instance_.Initialize(base::FilePath("libvulkan.so"),
                                      required_extensions, {});
 }
diff --git a/infra/config/generated/builders/ci/android-12l-x64-rel-cq/targets/chromium.android.json b/infra/config/generated/builders/ci/android-12l-x64-rel-cq/targets/chromium.android.json
index ccee355..a70cfe0 100644
--- a/infra/config/generated/builders/ci/android-12l-x64-rel-cq/targets/chromium.android.json
+++ b/infra/config/generated/builders/ci/android-12l-x64-rel-cq/targets/chromium.android.json
@@ -3,7 +3,7 @@
     "gtest_tests": [
       {
         "args": [
-          "--annotation=Restriction=Tablet,ImportantFormFactors=Tablet",
+          "--annotation=Restriction=Tablet,Restriction=TabletOrDesktop,ImportantFormFactors=Tablet,ImportantFormFactors=TabletOrDesktop",
           "--git-revision=${got_revision}",
           "--avd-config=../../tools/android/avd/proto/android_32_google_apis_x64_foldable.textpb",
           "--gs-results-bucket=chromium-result-details",
diff --git a/infra/config/generated/builders/try/android-12l-x64-rel-cq/targets/chromium.android.json b/infra/config/generated/builders/try/android-12l-x64-rel-cq/targets/chromium.android.json
index ccee355..a70cfe0 100644
--- a/infra/config/generated/builders/try/android-12l-x64-rel-cq/targets/chromium.android.json
+++ b/infra/config/generated/builders/try/android-12l-x64-rel-cq/targets/chromium.android.json
@@ -3,7 +3,7 @@
     "gtest_tests": [
       {
         "args": [
-          "--annotation=Restriction=Tablet,ImportantFormFactors=Tablet",
+          "--annotation=Restriction=Tablet,Restriction=TabletOrDesktop,ImportantFormFactors=Tablet,ImportantFormFactors=TabletOrDesktop",
           "--git-revision=${got_revision}",
           "--avd-config=../../tools/android/avd/proto/android_32_google_apis_x64_foldable.textpb",
           "--gs-results-bucket=chromium-result-details",
diff --git a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json
index ec84f9d3..a5e11d6 100644
--- a/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json
+++ b/infra/config/generated/builders/try/android-x64-rel/targets/chromium.android.json
@@ -3,7 +3,7 @@
     "gtest_tests": [
       {
         "args": [
-          "--annotation=Restriction=Tablet,ImportantFormFactors=Tablet",
+          "--annotation=Restriction=Tablet,Restriction=TabletOrDesktop,ImportantFormFactors=Tablet,ImportantFormFactors=TabletOrDesktop",
           "--git-revision=${got_revision}",
           "--avd-config=../../tools/android/avd/proto/android_32_google_apis_x64_foldable.textpb",
           "--gs-results-bucket=chromium-result-details",
diff --git a/infra/config/targets/tests.star b/infra/config/targets/tests.star
index e0fec9f..306d5f0f 100644
--- a/infra/config/targets/tests.star
+++ b/infra/config/targets/tests.star
@@ -558,7 +558,7 @@
         "skia_gold_test",
     ],
     args = [
-        "--annotation=Restriction=Tablet,ImportantFormFactors=Tablet",
+        "--annotation=Restriction=Tablet,Restriction=TabletOrDesktop,ImportantFormFactors=Tablet,ImportantFormFactors=TabletOrDesktop",
     ],
     binary = "chrome_public_test_apk",
 )
diff --git a/internal b/internal
index d001483..f8e36dc 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit d001483ef1f2440291ad1fa8c15b897b7be0e72f
+Subproject commit f8e36dcd08ab67bfc9e717b3ed315fef7e8e6cba
diff --git a/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.h b/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.h
index 7373b45..7b70114 100644
--- a/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.h
+++ b/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.h
@@ -12,7 +12,6 @@
 #import "components/breadcrumbs/core/breadcrumb_manager_browser_agent.h"
 #import "ios/chrome/browser/overlays/model/public/overlay_presenter.h"
 #import "ios/chrome/browser/overlays/model/public/overlay_presenter_observer.h"
-#import "ios/chrome/browser/shared/model/browser/browser_observer.h"
 #import "ios/chrome/browser/shared/model/browser/browser_user_data.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list_observer.h"
 
@@ -47,7 +46,6 @@
 
 class BreadcrumbManagerBrowserAgent
     : public breadcrumbs::BreadcrumbManagerBrowserAgent,
-      public BrowserObserver,
       public OverlayPresenterObserver,
       public BrowserUserData<BreadcrumbManagerBrowserAgent>,
       public WebStateListObserver {
@@ -65,9 +63,6 @@
   // breadcrumbs::BreadcrumbManagerBrowserAgent:
   void PlatformLogEvent(const std::string& event) override;
 
-  // BrowserObserver:
-  void BrowserDestroyed(Browser* browser) override;
-
   // WebStateListObserver:
   void WebStateListDidChange(WebStateList* web_state_list,
                              const WebStateListChange& change,
@@ -81,8 +76,6 @@
                        bool initial_presentation) override;
   void OverlayPresenterDestroyed(OverlayPresenter* presenter) override;
 
-  raw_ptr<Browser> browser_ = nullptr;
-
   // Keeps track of WebState mutation count to avoid logging every event.
   // Created in WillBeginBatchOperation and destroyed in BatchOperationEnded.
   // Final mutation count is logged in BatchOperationEnded.
diff --git a/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.mm b/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.mm
index 192055c..9e25c60 100644
--- a/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.mm
+++ b/ios/chrome/browser/crash_report/model/breadcrumbs/breadcrumb_manager_browser_agent.mm
@@ -39,19 +39,15 @@
 const char kBreadcrumbOverlayJsPrompt[] = "#js-prompt";
 
 BreadcrumbManagerBrowserAgent::BreadcrumbManagerBrowserAgent(Browser* browser)
-    : BrowserUserData(browser), browser_(browser) {
-  browser_->AddObserver(this);
+    : BrowserUserData(browser) {
   browser_->GetWebStateList()->AddObserver(this);
 
   overlay_observation_.Observe(
       OverlayPresenter::FromBrowser(browser, OverlayModality::kWebContentArea));
 }
 
-BreadcrumbManagerBrowserAgent::~BreadcrumbManagerBrowserAgent() = default;
-
-void BreadcrumbManagerBrowserAgent::BrowserDestroyed(Browser* browser) {
+BreadcrumbManagerBrowserAgent::~BreadcrumbManagerBrowserAgent() {
   browser_->GetWebStateList()->RemoveObserver(this);
-  browser_->RemoveObserver(this);
 }
 
 void BreadcrumbManagerBrowserAgent::PlatformLogEvent(const std::string& event) {
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.h b/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.h
index 2f66253f..963f844f 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.h
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.h
@@ -10,7 +10,6 @@
 #import "base/memory/raw_ptr.h"
 #import "base/scoped_observation.h"
 #import "components/webauthn/core/browser/passkey_model.h"
-#import "ios/chrome/browser/shared/model/browser/browser_observer.h"
 #import "ios/chrome/browser/shared/model/browser/browser_user_data.h"
 
 namespace webauthn {
@@ -21,7 +20,6 @@
 // notification when required.
 class CredentialProviderBrowserAgent
     : public BrowserUserData<CredentialProviderBrowserAgent>,
-      public BrowserObserver,
       public webauthn::PasskeyModel::Observer {
  public:
   ~CredentialProviderBrowserAgent() override;
@@ -40,23 +38,15 @@
 
   void RemoveObservers();
 
-  // BrowserObserver::
-  void BrowserDestroyed(Browser* browser) override;
-
   // webauthn::PasskeyModel::Observer:
   void OnPasskeysChanged(
       const std::vector<webauthn::PasskeyModelChange>& changes) override;
   void OnPasskeyModelShuttingDown() override;
   void OnPasskeyModelIsReady(bool is_ready) override;
 
-  // The owning Browser
-  raw_ptr<Browser> browser_;
-
   // Owned by the IOSPasskeyModelFactory which should outlive this class
   raw_ptr<webauthn::PasskeyModel> model_;
 
-  base::ScopedObservation<Browser, BrowserObserver> browser_observation_{this};
-
   base::ScopedObservation<webauthn::PasskeyModel,
                           webauthn::PasskeyModel::Observer>
       model_observation_{this};
diff --git a/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.mm b/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.mm
index 40e6cc1..db67f70 100644
--- a/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.mm
+++ b/ios/chrome/browser/credential_provider/model/credential_provider_browser_agent.mm
@@ -18,20 +18,20 @@
 #import "ios/chrome/browser/webauthn/model/ios_passkey_model_factory.h"
 #import "ios/web/public/web_state.h"
 
+namespace {
 // Maximum amount of time since a passkey was created for it to count as a
 // recently added passkey.
-static constexpr base::TimeDelta kRecentlyAddedDelay = base::Seconds(5);
+constexpr base::TimeDelta kRecentlyAddedDelay = base::Seconds(5);
+}  // namespace
 
 CredentialProviderBrowserAgent::CredentialProviderBrowserAgent(Browser* browser)
     : BrowserUserData(browser),
-      browser_(browser),
       model_(IOSPasskeyModelFactory::GetForProfile(
           // Here, we want to observe the user's passkey model, so we need the
           // original profile.
           browser_->GetProfile()->GetOriginalProfile())) {
   if (model_) {
     model_observation_.Observe(model_.get());
-    browser_observation_.Observe(browser_.get());
   }
 }
 
@@ -43,7 +43,7 @@
 
 void CredentialProviderBrowserAgent::DisplayInfoBar(
     const sync_pb::WebauthnCredentialSpecifics& passkey) {
-  if (!browser_ || !infobar_allowed_) {
+  if (!infobar_allowed_) {
     return;
   }
 
@@ -81,12 +81,6 @@
 
 void CredentialProviderBrowserAgent::RemoveObservers() {
   model_observation_.Reset();
-  browser_observation_.Reset();
-  browser_ = nullptr;
-}
-
-void CredentialProviderBrowserAgent::BrowserDestroyed(Browser* browser) {
-  RemoveObservers();
 }
 
 void CredentialProviderBrowserAgent::OnPasskeysChanged(
diff --git a/ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.mm b/ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.mm
index e6156fd..fff8b07 100644
--- a/ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.mm
+++ b/ios/chrome/browser/default_promo/ui_bundled/default_browser_promo_non_modal_metrics_util.mm
@@ -85,7 +85,7 @@
 
     default:
       // TODO(crbug.com/327429982): M124 validation necessary.
-      NOTREACHED(base::NotFatalUntil::M126);
+      NOTREACHED();
   }
 
   UmaHistogramEnumeration(histogramString, action);
diff --git a/ios/chrome/browser/first_run/ui_bundled/best_features/ui/best_features_view_controller.mm b/ios/chrome/browser/first_run/ui_bundled/best_features/ui/best_features_view_controller.mm
index 77cf3b5..6c37e9f 100644
--- a/ios/chrome/browser/first_run/ui_bundled/best_features/ui/best_features_view_controller.mm
+++ b/ios/chrome/browser/first_run/ui_bundled/best_features/ui/best_features_view_controller.mm
@@ -107,7 +107,7 @@
 #pragma mark - BestFeaturesScreenConsumer
 
 - (void)setBestFeaturesItems:(NSArray<BestFeaturesItem*>*)items {
-  CHECK([items count] == 3, base::NotFatalUntil::M128);
+  CHECK([items count] == 3);
   _bestFeaturesItems = items;
 }
 
@@ -173,7 +173,7 @@
 // Creates the data source for the table view.
 - (UITableViewDiffableDataSource<NSNumber*, NSNumber*>*)
     createAndFillDataSource {
-  CHECK(_bestFeaturesItems, base::NotFatalUntil::M128);
+  CHECK(_bestFeaturesItems);
   __weak __typeof(self) weakSelf = self;
   UITableViewDiffableDataSource<NSNumber*, NSNumber*>* dataSource =
       [[UITableViewDiffableDataSource alloc]
diff --git a/ios/chrome/browser/infobars/ui_bundled/modals/permissions/infobar_permissions_table_view_controller.mm b/ios/chrome/browser/infobars/ui_bundled/modals/permissions/infobar_permissions_table_view_controller.mm
index bdd4ad6ea..2b85501 100644
--- a/ios/chrome/browser/infobars/ui_bundled/modals/permissions/infobar_permissions_table_view_controller.mm
+++ b/ios/chrome/browser/infobars/ui_bundled/modals/permissions/infobar_permissions_table_view_controller.mm
@@ -297,7 +297,7 @@
 
   if (tableViewLoaded) {
     NSIndexPath* index = [self.tableViewModel indexPathForItemType:itemType];
-    CHECK_NE(index, nil, base::NotFatalUntil::M128);
+    CHECK_NE(index, nil);
     [self.tableView insertRowsAtIndexPaths:@[ index ]
                           withRowAnimation:UITableViewRowAnimationAutomatic];
     [self.presentationHandler resizeInfobarModal];
diff --git a/ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.mm b/ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.mm
index c5145f7..7b6e3577 100644
--- a/ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.mm
+++ b/ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.mm
@@ -160,8 +160,7 @@
       destination_tab_group));
   // Check that the source browser has one less group.
   CHECK_EQ(source_group_count,
-           source_browser->GetWebStateList()->GetGroups().size() + 1,
-           base::NotFatalUntil::M128);
+           source_browser->GetWebStateList()->GetGroups().size() + 1);
 }
 
 void MoveTabGroupToBrowser(const TabGroup* source_tab_group,
diff --git a/ios/chrome/browser/search_engine_choice/ui_bundled/snippet_search_engine_button.mm b/ios/chrome/browser/search_engine_choice/ui_bundled/snippet_search_engine_button.mm
index 8a0c085..39d2b5eb 100644
--- a/ios/chrome/browser/search_engine_choice/ui_bundled/snippet_search_engine_button.mm
+++ b/ios/chrome/browser/search_engine_choice/ui_bundled/snippet_search_engine_button.mm
@@ -500,7 +500,7 @@
 #pragma mark - Accessibility
 
 - (NSString*)accessibilityLabel {
-  CHECK_NE(self.snippetText.length, 0ul, base::NotFatalUntil::M127)
+  CHECK_NE(self.snippetText.length, 0ul)
       << base::SysNSStringToUTF8(self.searchEngineName) << " "
       << base::SysNSStringToUTF8(self.snippetText);
   return [NSString
@@ -508,7 +508,7 @@
 }
 
 - (NSArray<NSString*>*)accessibilityUserInputLabels {
-  CHECK_NE(self.searchEngineName.length, 0ul, base::NotFatalUntil::M127)
+  CHECK_NE(self.searchEngineName.length, 0ul)
       << base::SysNSStringToUTF8(self.searchEngineName) << " "
       << base::SysNSStringToUTF8(self.snippetText);
   return @[ self.searchEngineName ];
diff --git a/ios/chrome/browser/sessions/model/web_state_list_serialization.mm b/ios/chrome/browser/sessions/model/web_state_list_serialization.mm
index 603cfb18..56e5e98 100644
--- a/ios/chrome/browser/sessions/model/web_state_list_serialization.mm
+++ b/ios/chrome/browser/sessions/model/web_state_list_serialization.mm
@@ -433,7 +433,7 @@
     if (base::FeatureList::IsEnabled(
             session::features::kSessionRestorationSessionIDCheck)) {
       web::WebStateID web_state_id = web_state->GetUniqueIdentifier();
-      CHECK(web_state_id.valid(), base::NotFatalUntil::M125);
+      CHECK(web_state_id.valid());
       if (!max_identifier.is_valid() ||
           max_identifier.id() < web_state_id.identifier()) {
         max_identifier = web_state_id.ToSessionID();
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_coordinator.mm
index fecbe69..72751a9 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_sync_settings_coordinator.mm
@@ -191,7 +191,7 @@
 
   self.mediator.consumer = viewController;
 
-  CHECK(_baseNavigationController, base::NotFatalUntil::M129);
+  CHECK(_baseNavigationController);
   [self.baseNavigationController pushViewController:viewController
                                            animated:YES];
   _syncObserver = std::make_unique<SyncObserverBridge>(self, self.syncService);
@@ -321,8 +321,7 @@
         // `baseNavigationController`, `baseNavigationController` needs to be
         // closed.
         CHECK([self.baseNavigationController
-                  isKindOfClass:[SettingsNavigationController class]],
-              base::NotFatalUntil::M129);
+            isKindOfClass:[SettingsNavigationController class]]);
         [self.baseNavigationController
             performSelector:@selector(closeSettings)];
       } else {
diff --git a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
index 3b432f4a..2e5e4fa 100644
--- a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
@@ -409,6 +409,10 @@
         [[NotificationsSettingsObserver alloc] initWithPrefService:prefService
                                                         localState:localState];
     _notificationsObserver.delegate = self;
+
+    // TODO(crbug.com/41344225): -loadModel should not be called from
+    // initializer. A possible fix is to move this call to -viewDidLoad.
+    [self loadModel];
   }
   return self;
 }
@@ -432,8 +436,6 @@
 
   self.navigationItem.largeTitleDisplayMode =
       UINavigationItemLargeTitleDisplayModeAlways;
-
-  [self loadModel];
 }
 
 - (void)viewWillAppear:(BOOL)animated {
diff --git a/ios/chrome/browser/settings/ui_bundled/sync/sync_create_passphrase_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/sync/sync_create_passphrase_table_view_controller.mm
index bba9ae60..e5571842 100644
--- a/ios/chrome/browser/settings/ui_bundled/sync/sync_create_passphrase_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/sync/sync_create_passphrase_table_view_controller.mm
@@ -37,17 +37,16 @@
         l10n_util::GetNSString(IDS_IOS_NEW_SYNC_ENCRYPTION_PASSPHRASE_INFO_UNO);
     self.processingMessage =
         l10n_util::GetNSString(IDS_IOS_SYNC_PASSPHRASE_ENCRYPTING);
+
+    // TODO(crbug.com/41344225): -loadModel should not be called from
+    // initializer. A possible fix is to move this call to -viewDidLoad.
+    [self loadModel];
   }
   return self;
 }
 
 #pragma mark - UIViewController
 
-- (void)viewDidLoad {
-  [super viewDidLoad];
-  [self loadModel];
-}
-
 - (void)didReceiveMemoryWarning {
   [super didReceiveMemoryWarning];
   if (![self isViewLoaded]) {
diff --git a/ios/chrome/browser/shared/model/prefs/pref_backed_boolean.mm b/ios/chrome/browser/shared/model/prefs/pref_backed_boolean.mm
index d30494e..f9b3717 100644
--- a/ios/chrome/browser/shared/model/prefs/pref_backed_boolean.mm
+++ b/ios/chrome/browser/shared/model/prefs/pref_backed_boolean.mm
@@ -30,8 +30,7 @@
 }
 
 - (void)dealloc {
-  CHECK(_stopped, base::NotFatalUntil::M140)
-      << "-stop should be called on PrefBackedBoolean";
+  CHECK(_stopped) << "-stop should be called on PrefBackedBoolean";
 }
 
 - (BOOL)value {
diff --git a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm
index 96bb2ef..cc412c3 100644
--- a/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm
+++ b/ios/chrome/browser/shared/model/web_state_list/web_state_list.mm
@@ -858,7 +858,7 @@
   // Figure out the pivot index.
   int pivot_index = kInvalidIndex;
   const int first_index = *indices.begin();
-  CHECK(ContainsIndex(first_index), base::NotFatalUntil::M128);
+  CHECK(ContainsIndex(first_index));
   if (IsWebStatePinnedAt(first_index)) {
     // Move to the last pinned tab.
     pivot_index = pinned_tabs_count_;
@@ -980,7 +980,7 @@
   // keep ungrouped WebStates in the order they were in the group.
   for (auto it = indices.rbegin(); it != indices.rend(); ++it) {
     const int index = *it;
-    CHECK(ContainsIndex(index), base::NotFatalUntil::M128);
+    CHECK(ContainsIndex(index));
     const TabGroup* group = GetGroupOfWebStateAt(index);
     if (group) {
       const int to_index = group->range().range_end() - 1;
diff --git a/ios/chrome/browser/signin/model/BUILD.gn b/ios/chrome/browser/signin/model/BUILD.gn
index 14f4b9f..8ef6c5d8 100644
--- a/ios/chrome/browser/signin/model/BUILD.gn
+++ b/ios/chrome/browser/signin/model/BUILD.gn
@@ -77,7 +77,9 @@
     "//google_apis",
     "//ios/chrome/app:change_profile_commands",
     "//ios/chrome/app:tests_hook",
+    "//ios/chrome/browser/authentication/ui_bundled:continuation",
     "//ios/chrome/browser/authentication/ui_bundled/account_menu:constants",
+    "//ios/chrome/browser/authentication/ui_bundled/signin:signin_headers",
     "//ios/chrome/browser/bookmarks/model:model_utils",
     "//ios/chrome/browser/content_settings/model",
     "//ios/chrome/browser/crash_report/model",
diff --git a/ios/chrome/browser/signin/model/DEPS b/ios/chrome/browser/signin/model/DEPS
index 454baaf..8563902 100644
--- a/ios/chrome/browser/signin/model/DEPS
+++ b/ios/chrome/browser/signin/model/DEPS
@@ -19,6 +19,10 @@
 ]
 
 specific_include_rules = {
+  "^account_consistency_browser_agent.mm": [
+    "+ios/chrome/browser/authentication/ui_bundled/continuation.h",
+    "+ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator.h",
+  ],
   # TODO(crbug.com/331781927): remove when kIdentityDiscAccountMenu launches.
   "^authentication_service_delegate_impl.cc": [
     "+ios/chrome/browser/ntp/ui_bundled/new_tab_page_feature.h",
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent.h b/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
index 1ce3692..8afe5dcf28 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent.h
@@ -15,6 +15,9 @@
 @protocol SettingsCommands;
 class Browser;
 @class SceneState;
+@class SigninCoordinator;
+typedef NS_ENUM(NSUInteger, SigninCoordinatorResult);
+@protocol SystemIdentity;
 @class ManageAccountsDelegateBridge;
 @class UIViewController;
 
@@ -49,6 +52,9 @@
  private:
   friend class BrowserUserData<AccountConsistencyBrowserAgent>;
 
+  void StopSigninCoordinator(SigninCoordinatorResult result,
+                             id<SystemIdentity> identity);
+
   // `base_view_controller` is the view controller which UI will be presented
   // from.
   AccountConsistencyBrowserAgent(Browser* browser,
@@ -68,6 +74,7 @@
   UIViewController* base_view_controller_;
   id<ApplicationCommands> application_handler_;
   id<SettingsCommands> settings_handler_;
+  SigninCoordinator* add_account_coordinator_;
 
   // Bridge object to act as the delegate.
   ManageAccountsDelegateBridge* bridge_;
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
index 13b858c..f1696e77 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent.mm
@@ -6,9 +6,12 @@
 
 #import <UIKit/UIKit.h>
 
+#import "base/functional/callback_helpers.h"
 #import "components/signin/core/browser/account_reconcilor.h"
 #import "components/signin/ios/browser/account_consistency_service.h"
 #import "ios/chrome/browser/authentication/ui_bundled/account_menu/account_menu_constants.h"
+#import "ios/chrome/browser/authentication/ui_bundled/continuation.h"
+#import "ios/chrome/browser/authentication/ui_bundled/signin/signin_coordinator.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/profile/features.h"
 #import "ios/chrome/browser/shared/model/profile/profile_attributes_storage_ios.h"
@@ -37,7 +40,16 @@
       HandlerForProtocol(browser_->GetCommandDispatcher(), SettingsCommands);
 }
 
-AccountConsistencyBrowserAgent::~AccountConsistencyBrowserAgent() {}
+AccountConsistencyBrowserAgent::~AccountConsistencyBrowserAgent() {
+  StopSigninCoordinator(SigninCoordinatorResultInterrupted, nil);
+}
+
+void AccountConsistencyBrowserAgent::StopSigninCoordinator(
+    SigninCoordinatorResult result,
+    id<SystemIdentity> identity) {
+  [add_account_coordinator_ stop];
+  add_account_coordinator_ = nil;
+}
 
 void AccountConsistencyBrowserAgent::InstallDependency(
     web::WebState* web_state) {
@@ -105,13 +117,20 @@
   if (ShouldShowAccountMenu()) {
     ShowAccountMenu(url);
   } else {
-    ShowSigninCommand* command = [[ShowSigninCommand alloc]
-        initWithOperation:AuthenticationOperation::kAddAccount
-              accessPoint:signin_metrics::AccessPoint::
-                              kAccountConsistencyService];
-    command.skipIfUINotAvailable = YES;
-    [application_handler_ showSignin:command
-                  baseViewController:base_view_controller_];
+    signin_metrics::AccessPoint access_point =
+        signin_metrics::AccessPoint::kAccountConsistencyService;
+    SigninContextStyle context_style = SigninContextStyle::kDefault;
+    add_account_coordinator_ = [SigninCoordinator
+        addAccountCoordinatorWithBaseViewController:base_view_controller_
+                                            browser:browser_
+                                       contextStyle:context_style
+                                        accessPoint:access_point
+                               continuationProvider:
+                                   DoNothingContinuationProvider()];
+    add_account_coordinator_.signinCompletion = CallbackToBlock(
+        base::BindOnce(&AccountConsistencyBrowserAgent::StopSigninCoordinator,
+                       base::Unretained(this)));
+    [add_account_coordinator_ start];
   }
 }
 
diff --git a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
index b127579..4965549 100644
--- a/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
+++ b/ios/chrome/browser/signin/model/account_consistency_browser_agent_unittest.mm
@@ -146,28 +146,22 @@
   // is a strict mock.
 }
 
-// Tests OnAddAccount() to send ShowSigninCommand if there is no view presented
-// on top of the base view controller.
-// See http://crbug.com/1399464.
+// Tests OnAddAccount() to show present a view controller if there is no view
+// presented on top of the base view controller. See http://crbug.com/1399464.
 TEST_P(AccountConsistencyBrowserAgentTest, OnAddAccountWithoutPresentedView) {
   OCMStub([base_view_controller_mock_ presentedViewController])
       .andReturn((id)nil);
-  __block ShowSigninCommand* received_command = nil;
-  OCMExpect([application_commands_mock_
-              showSignin:[OCMArg
-                             checkWithBlock:^BOOL(ShowSigninCommand* command) {
-                               received_command = command;
-                               return YES;
-                             }]
-      baseViewController:base_view_controller_mock_]);
+  __block void (^completion)() = nil;
+  OCMExpect([base_view_controller_mock_
+      presentViewController:[OCMArg any]
+                   animated:YES
+                 completion:[OCMArg checkWithBlock:^BOOL(id value) {
+                   completion = value;
+                   return YES;
+                 }]]);
   agent_->OnAddAccount(GURL());
-  EXPECT_NE(received_command, nil);
-  EXPECT_EQ(received_command.operation, AuthenticationOperation::kAddAccount);
-  EXPECT_EQ(received_command.identity, nil);
-  EXPECT_EQ(received_command.accessPoint,
-            signin_metrics::AccessPoint::kAccountConsistencyService);
-  EXPECT_EQ(received_command.promoAction,
-            signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO);
+  CHECK(completion);
+  completion();
 }
 
 TEST_F(AccountConsistencyBrowserAgentWithSeparateProfilesTest,
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn
index 0d8044e..baf157f 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/BUILD.gn
@@ -24,6 +24,7 @@
     "tab_snapshot_and_favicon_configurator.mm",
     "tab_switcher_item.h",
     "tab_switcher_item.mm",
+    "tab_switcher_item_snapshot_and_favicon_data_source.h",
     "web_state_tab_switcher_item.h",
     "web_state_tab_switcher_item.mm",
   ]
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.h
index 935032c..d63ccb7 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.h
@@ -16,6 +16,7 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_page_mutator.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_grid_paging.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/toolbars/tab_grid_toolbars_grid_delegate.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 
 @class ActivityLabelData;
 @class BaseGridMediator;
@@ -50,13 +51,15 @@
 @end
 
 // Mediates between model layer and tab grid UI layer.
-@interface BaseGridMediator : NSObject <BaseGridMediatorItemProvider,
-                                        GridCommands,
-                                        GridViewControllerMutator,
-                                        SuggestedActionsDelegate,
-                                        TabCollectionDragDropHandler,
-                                        TabGridPageMutator,
-                                        TabGridToolbarsGridDelegate>
+@interface BaseGridMediator
+    : NSObject <BaseGridMediatorItemProvider,
+                GridCommands,
+                GridViewControllerMutator,
+                SuggestedActionsDelegate,
+                TabCollectionDragDropHandler,
+                TabGridPageMutator,
+                TabGridToolbarsGridDelegate,
+                TabSwitcherItemSnapShotAndFaviconDataSource>
 
 // The source browser.
 @property(nonatomic, assign) Browser* browser;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm
index f9d85b2..2a4d1c3 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator.mm
@@ -9,6 +9,7 @@
 
 #import <memory>
 
+#import "base/apple/foundation_util.h"
 #import "base/debug/dump_without_crashing.h"
 #import "base/functional/bind.h"
 #import "base/metrics/histogram_functions.h"
@@ -2033,4 +2034,17 @@
       tabGroupItem, webStateList, completion);
 }
 
+#pragma mark - TabSwitcherItemSnapShotAndFaviconDataSource
+
+// Fetches the `item` info and executes the given `completion` block.
+- (void)fetchTabSnapshotAndFavicon:(TabSwitcherItem*)item
+                        completion:
+                            (TabSnapshotAndFaviconFetchingCompletionBlock)
+                                completion {
+  WebStateTabSwitcherItem* tabSwitcherItem =
+      base::apple::ObjCCastStrict<WebStateTabSwitcherItem>(item);
+  _tabImagesConfigurator->FetchSnapshotAndFaviconForTabSwitcherItem(
+      tabSwitcherItem, completion);
+}
+
 @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm
index e6a30185..53bc128a 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_mediator_unittest.mm
@@ -14,6 +14,7 @@
 #import "base/strings/sys_string_conversions.h"
 #import "base/test/ios/wait_util.h"
 #import "base/test/metrics/histogram_tester.h"
+#import "base/test/test_timeouts.h"
 #import "base/time/time.h"
 #import "components/commerce/core/commerce_feature_list.h"
 #import "components/saved_tab_groups/public/saved_tab_group.h"
@@ -36,6 +37,7 @@
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/snapshots/model/snapshot_browser_agent.h"
+#import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_item_identifier.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.h"
@@ -1287,6 +1289,27 @@
   ExpectThatDragItemOriginMetricLogged(DragItemOrigin::kOther);
 }
 
+// Tests that `fetchTabSnapshotAndFavicon:completion:` is calling `completion`
+// twice.
+TEST_P(BaseGridMediatorTest, FetchTabSnapshotAndFavicon) {
+  auto fake_web_state = std::make_unique<web::FakeWebState>();
+  web::FakeWebState* web_state = fake_web_state.get();
+  SnapshotTabHelper::CreateForWebState(web_state);
+  WebStateTabSwitcherItem* item =
+      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state];
+  __block int completion_block_called = 0;
+  auto completion_block = ^(TabSwitcherItem* inner_item,
+                            TabSnapshotAndFavicon* tab_snapshot_and_favicon) {
+    completion_block_called++;
+    ASSERT_LE(completion_block_called, 2);
+  };
+  [mediator_ fetchTabSnapshotAndFavicon:item completion:completion_block];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      TestTimeouts::action_timeout(), ^bool() {
+        return completion_block_called == 2;
+      }));
+}
+
 INSTANTIATE_TEST_SUITE_P(
     /* No InstantiationName */,
     BaseGridMediatorTest,
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.h
index a23960c7..bda658f 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.h
@@ -25,9 +25,10 @@
 @protocol TabContextMenuProvider;
 @protocol TabCollectionDragDropHandler;
 @protocol TabGridCommands;
-@protocol TabGroupConfirmationCommands;
 @class TabGridTransitionItem;
 class TabGroup;
+@protocol TabGroupConfirmationCommands;
+@protocol TabSwitcherItemSnapShotAndFaviconDataSource;
 
 namespace web {
 class WebStateID;
@@ -162,6 +163,9 @@
     tabGroupConfirmationHandler;
 // The layout guide center to use to refer to the selected cell.
 @property(nonatomic, strong) LayoutGuideCenter* layoutGuideCenter;
+// Handles snapshots and favicons fetches.
+@property(nonatomic, weak) id<TabSwitcherItemSnapShotAndFaviconDataSource>
+    snapshotAndfaviconDataSource;
 
 // Returns the layout of the grid for use in an animated transition.
 - (LegacyGridTransitionLayout*)transitionLayout;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm
index 61e07d5..ca166e7 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/base_grid_view_controller.mm
@@ -44,7 +44,9 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/legacy_grid_transition_layout.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_item.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_utils.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
@@ -1723,19 +1725,18 @@
     cell.layoutGuideCenter = self.layoutGuideCenter;
     [cell registerAsSelectedCellGuide];
   }
-  [item fetchFavicon:^(TabSwitcherItem* innerItem, UIImage* icon) {
-    // Only update the icon if the cell is not already reused for another item.
-    if ([cell.itemIdentifier.tabSwitcherItem isEqual:innerItem]) {
-      cell.icon = icon;
-    }
-  }];
 
-  [item fetchSnapshot:^(TabSwitcherItem* innerItem, UIImage* snapshot) {
-    // Only update the icon if the cell is not already reused for another item.
+  auto completion = ^(TabSwitcherItem* innerItem,
+                      TabSnapshotAndFavicon* tabSnapshotAndFavicon) {
+    // Only apply changes if the cell is not already reused for another
+    // item.
     if ([cell.itemIdentifier.tabSwitcherItem isEqual:innerItem]) {
-      cell.snapshot = snapshot;
+      cell.icon = tabSnapshotAndFavicon.favicon;
+      cell.snapshot = tabSnapshotAndFavicon.snapshot;
     }
-  }];
+  };
+  [self.snapshotAndfaviconDataSource fetchTabSnapshotAndFavicon:item
+                                                     completion:completion];
 
   web::WebStateID itemID = item.identifier;
   [self.priceCardDataSource
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/incognito/incognito_grid_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/incognito/incognito_grid_coordinator.mm
index 387c80b3..514d77a 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/incognito/incognito_grid_coordinator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/incognito/incognito_grid_coordinator.mm
@@ -228,6 +228,7 @@
   gridViewController.mutator = _mediator;
   gridViewController.gridProvider = _mediator;
   gridViewController.gridHandler = _mediator;
+  gridViewController.snapshotAndfaviconDataSource = _mediator;
   gridViewController.incognitoGridHandler = self;
   // TODO(crbug.com/40273478): Move the following lines to the grid itself when
   // specific grid file will be created.
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm
index 4bffab7..0b68d28d 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_coordinator.mm
@@ -157,6 +157,7 @@
   gridViewController.mutator = _mediator;
   gridViewController.gridProvider = _mediator;
   gridViewController.menuProvider = _contextMenuProvider;
+  gridViewController.snapshotAndfaviconDataSource = _mediator;
 
   // If regular is enabled then the grid exists and it is not disabled.
   // TODO(crbug.com/40273478): Get disabled status from the mediator.
@@ -187,6 +188,7 @@
     _pinnedTabsMediator.browser = self.browser;
     pinnedTabsViewController.menuProvider = _contextMenuProvider;
     pinnedTabsViewController.dragDropHandler = _pinnedTabsMediator;
+    pinnedTabsViewController.snapshotAndfaviconDataSource = _pinnedTabsMediator;
   }
 
   [super start];
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/BUILD.gn
index b83bc32..7282780f 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/BUILD.gn
@@ -23,6 +23,7 @@
     "//ios/chrome/browser/shared/ui/symbols",
     "//ios/chrome/browser/snapshots/model",
     "//ios/chrome/browser/tab_switcher/ui_bundled",
+    "//ios/chrome/browser/tab_switcher/ui_bundled:items",
     "//ios/chrome/browser/tab_switcher/ui_bundled:utils",
     "//ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid:grid_ui",
     "//ios/chrome/browser/url_loading/model",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.h
index 5bca305..fed082ba 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.h
@@ -8,12 +8,15 @@
 #import <Foundation/Foundation.h>
 
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_handler.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 
 class Browser;
 @protocol PinnedTabCollectionConsumer;
 
 // Mediates between model layer and pinned tabs collection UI layer.
-@interface PinnedTabsMediator : NSObject <TabCollectionDragDropHandler>
+@interface PinnedTabsMediator
+    : NSObject <TabCollectionDragDropHandler,
+                TabSwitcherItemSnapShotAndFaviconDataSource>
 
 // The source browser.
 @property(nonatomic, assign) Browser* browser;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
index 02138de..e5964c9 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
@@ -7,6 +7,7 @@
 #import <UIKit/UIKit.h>
 #import <UniformTypeIdentifiers/UniformTypeIdentifiers.h>
 
+#import "base/apple/foundation_util.h"
 #import "base/metrics/histogram_functions.h"
 #import "base/metrics/user_metrics.h"
 #import "base/metrics/user_metrics_action.h"
@@ -24,6 +25,7 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/pinned_tab_collection_consumer.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_utils.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_browser_agent.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_params.h"
@@ -85,6 +87,8 @@
 
   // URL loader to open tabs when needed.
   raw_ptr<UrlLoadingBrowserAgent> _URLLoader;
+  // Helper class to configure tab item images.
+  std::unique_ptr<TabSnapshotAndFaviconConfigurator> _tabImagesConfigurator;
 }
 
 - (instancetype)initWithConsumer:(id<PinnedTabCollectionConsumer>)consumer {
@@ -102,6 +106,8 @@
         std::make_unique<base::ScopedMultiSourceObservation<
             web::WebState, web::WebStateObserver>>(
             _webStateObserverBridge.get());
+    _tabImagesConfigurator =
+        std::make_unique<TabSnapshotAndFaviconConfigurator>(nullptr);
   }
   return self;
 }
@@ -485,4 +491,17 @@
   }
 }
 
+#pragma mark - TabSwitcherItemSnapShotAndFaviconDataSource
+
+// Fetches the `item` info and executes the given `completion` block.
+- (void)fetchTabSnapshotAndFavicon:(TabSwitcherItem*)item
+                        completion:
+                            (TabSnapshotAndFaviconFetchingCompletionBlock)
+                                completion {
+  WebStateTabSwitcherItem* tabSwitcherItem =
+      base::apple::ObjCCastStrict<WebStateTabSwitcherItem>(item);
+  _tabImagesConfigurator->FetchSnapshotAndFaviconForTabSwitcherItem(
+      tabSwitcherItem, completion);
+}
+
 @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
index 4778df4..6d2b961 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.h
@@ -14,6 +14,7 @@
 @protocol TabCollectionDragDropHandler;
 @protocol TabContextMenuProvider;
 @class TabGridTransitionItem;
+@protocol TabSwitcherItemSnapShotAndFaviconDataSource;
 
 namespace web {
 class WebStateID;
@@ -77,6 +78,10 @@
 // Handles drag and drop interactions that involved the model layer.
 @property(nonatomic, weak) id<TabCollectionDragDropHandler> dragDropHandler;
 
+// Handles snapshots and favicons fetches.
+@property(nonatomic, weak) id<TabSwitcherItemSnapShotAndFaviconDataSource>
+    snapshotAndfaviconDataSource;
+
 // Tracks if a drop animation is in progress.
 @property(nonatomic, assign) BOOL dropAnimationInProgress;
 
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
index 14a0621..12612d7b 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
@@ -20,7 +20,9 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_context_menu/tab_context_menu_provider.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/legacy_grid_transition_layout.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_utils.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/util/constraints_ui_util.h"
@@ -841,20 +843,18 @@
   if (item) {
     cell.pinnedItemIdentifier = item.identifier;
     cell.title = item.title;
-    [item fetchFavicon:^(TabSwitcherItem* innerItem, UIImage* icon) {
-      // Only update the icon if the cell is not already reused for another
+
+    auto completion = ^(TabSwitcherItem* innerItem,
+                        TabSnapshotAndFavicon* tabSnapshotAndFavicon) {
+      // Only apply changes if the cell is not already reused for another
       // item.
       if (cell.pinnedItemIdentifier == innerItem.identifier) {
-        cell.icon = icon;
+        cell.icon = tabSnapshotAndFavicon.favicon;
+        cell.snapshot = tabSnapshotAndFavicon.snapshot;
       }
-    }];
-    [item fetchSnapshot:^(TabSwitcherItem* innerItem, UIImage* snapshot) {
-      // Only update the icon if the cell is not already reused for another
-      // item.
-      if (cell.pinnedItemIdentifier == innerItem.identifier) {
-        cell.snapshot = snapshot;
-      }
-    }];
+    };
+    [self.snapshotAndfaviconDataSource fetchTabSnapshotAndFavicon:item
+                                                       completion:completion];
   }
 
   cell.accessibilityIdentifier = [NSString
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/BUILD.gn
index d525c3d..8644592 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/BUILD.gn
@@ -40,6 +40,7 @@
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/model/web_state_list/test:test_support",
     "//ios/chrome/browser/shared/public/features",
+    "//ios/chrome/browser/snapshots/model",
     "//ios/chrome/browser/tab_insertion/model",
     "//ios/chrome/browser/tab_switcher/ui_bundled",
     "//ios/chrome/browser/tab_switcher/ui_bundled:items",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/pinned_tabs_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/pinned_tabs_mediator_unittest.mm
index 4f62e1d1..85ecb07 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/pinned_tabs_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/tests/pinned_tabs_mediator_unittest.mm
@@ -10,6 +10,7 @@
 #import "base/test/ios/wait_util.h"
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
+#import "base/test/test_timeouts.h"
 #import "ios/chrome/browser/drag_and_drop/model/drag_item_util.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
@@ -19,11 +20,13 @@
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
 #import "ios/chrome/browser/shared/model/web_state_list/web_state_opener.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tab_insertion/model/tab_insertion_browser_agent.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/test/fake_drag_session.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/test/fake_drop_session.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/test/fake_pinned_tab_collection_consumer.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
 #import "ios/chrome/browser/url_loading/model/fake_url_loading_delegate.h"
 #import "ios/chrome/browser/url_loading/model/scene_url_loading_service.h"
 #import "ios/chrome/browser/url_loading/model/test_scene_url_loading_service.h"
@@ -399,3 +402,29 @@
             web_state->GetNavigationManager()->GetPendingItem()->GetURL());
   ExpectThatDragItemOriginMetricLogged(DragItemOrigin::kOther);
 }
+
+// Tests that `fetchTabSnapshotAndFavicon:completion:` is calling `completion`
+// twice.
+TEST_F(PinnedTabsMediatorTest, FetchTabSnapshotAndFavicon) {
+  // The Pinned Tabs feature is not available on iPad.
+  if (!IsPinnedTabsEnabled()) {
+    return;
+  }
+
+  auto fake_web_state = std::make_unique<web::FakeWebState>();
+  web::FakeWebState* web_state = fake_web_state.get();
+  SnapshotTabHelper::CreateForWebState(web_state);
+  WebStateTabSwitcherItem* item =
+      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state];
+  __block int completion_block_called = 0;
+  auto completion_block = ^(TabSwitcherItem* inner_item,
+                            TabSnapshotAndFavicon* tab_snapshot_and_favicon) {
+    completion_block_called++;
+    ASSERT_LE(completion_block_called, 2);
+  };
+  [mediator_ fetchTabSnapshotAndFavicon:item completion:completion_block];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      TestTimeouts::action_timeout(), ^bool() {
+        return completion_block_called == 2;
+      }));
+}
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/shared_tab_groups_egtest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/shared_tab_groups_egtest.mm
index 21cef0a..5e5a1626e 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/shared_tab_groups_egtest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/shared_tab_groups_egtest.mm
@@ -884,7 +884,14 @@
 }
 
 // Ensures new tab is added when closing the last tab of a shared group.
-- (void)testCloseLastTabInSharedGroup {
+// TODO(crbug.com/420464084): Test is failing on iphone-device.
+#if TARGET_OS_SIMULATOR
+#define MAYBE_testCloseLastTabInSharedGroup testCloseLastTabInSharedGroup
+#else
+#define MAYBE_testCloseLastTabInSharedGroup \
+  DISABLED_testCloseLastTabInSharedGroup
+#endif
+- (void)MAYBE_testCloseLastTabInSharedGroup {
   if (@available(iOS 17, *)) {
   } else if ([ChromeEarlGrey isIPadIdiom]) {
     EARL_GREY_TEST_SKIPPED(@"Only available on iOS 17+ on iPad.");
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator.mm
index b3bde9cd..2a60d1bd8 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator.mm
@@ -153,6 +153,7 @@
   _viewController.gridViewController.gridProvider = _mediator;
   _viewController.gridViewController.menuProvider = _tabContextMenuHelper;
   _viewController.gridViewController.dragDropHandler = _mediator;
+  _viewController.gridViewController.snapshotAndfaviconDataSource = _mediator;
 
   [self displayViewControllerAnimated:self.animatedPresentation];
 }
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h
index 4fe1fc6..a1307d0 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h
@@ -13,6 +13,7 @@
 @class TabGroupItem;
 @class TabSnapshotAndFavicon;
 class WebStateList;
+@class WebStateTabSwitcherItem;
 
 namespace web {
 class WebState;
@@ -48,8 +49,21 @@
       web::WebState* web_state,
       void (^completion)(TabSnapshotAndFavicon* tab_snapshot_and_favicon));
 
-  // TODO(crbug.com/400966281): Add function to fetch snapshot and favicon for
-  // TabSwitcherItem.
+  // Fetches the snapshot and favicon for `tab_item`.
+  // The `completion` block is invoked twice: once when the snapshot has been
+  // fetched, and again when the favicon has been fetched.
+  void FetchSnapshotAndFaviconForTabSwitcherItem(
+      WebStateTabSwitcherItem* tab_item,
+      void (^completion)(WebStateTabSwitcherItem* item,
+                         TabSnapshotAndFavicon* tab_snapshot_and_favicon));
+
+  // Fetches the favicon for `tab_item`.
+  // The `completion` block is invoked when the favicon has been fetched.
+  // The snapshot is not fetched and always nil.
+  void FetchFaviconForTabSwitcherItem(
+      WebStateTabSwitcherItem* tab_item,
+      void (^completion)(WebStateTabSwitcherItem* item,
+                         TabSnapshotAndFavicon* tab_snapshot));
 
  private:
   // Initiates the asynchronous fetching of a snapshot and favicon for a
@@ -66,9 +80,9 @@
           TabGroupItem* item,
           NSArray<TabSnapshotAndFavicon*>* tab_snapshots_and_favicons));
 
-  // Called when the snapshot and/or favicon for a web state has been  fetched.
+  // Called when the snapshot and/or favicon for a web state has been fetched.
   // Checks if all information has been collected and calls the `completion`
-  // block.
+  // block once, with all the information.
   void OnSnapshotAndFaviconFromWebStateFetched(
       TabGroupItem* group_item,
       TabSnapshotAndFavicon* tab_snapshot_and_favicon,
@@ -81,6 +95,17 @@
           TabGroupItem* item,
           NSArray<TabSnapshotAndFavicon*>* tab_snapshots_and_favicons));
 
+  // Fetches the snapshot and favicon for `tab_item`.
+  // If `fetch_snapshot` is false, only the favicon will be fetched.
+  // The `completion` block is invoked twice: once when the snapshot
+  // has been fetched (if requested), and again when the favicon has been
+  // fetched.
+  void FetchSnapshotAndFaviconForTabSwitcherItem(
+      WebStateTabSwitcherItem* tab_item,
+      bool fetch_snapshot,
+      void (^completion)(WebStateTabSwitcherItem* item,
+                         TabSnapshotAndFavicon* tab_snapshot_and_favicon));
+
   raw_ptr<FaviconLoader> favicon_loader_ = nullptr;
 
   // Stores the UUIDs of in-progress TabGroupItem fetch requests, keyed by the
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.mm
index 1510d0f7..fcbbd1a 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.mm
@@ -16,6 +16,7 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/item_utils.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/favicon/favicon_attributes.h"
 #import "ios/chrome/common/ui/util/image_util.h"
@@ -96,6 +97,23 @@
       inner_completion);
 }
 
+void TabSnapshotAndFaviconConfigurator::
+    FetchSnapshotAndFaviconForTabSwitcherItem(
+        WebStateTabSwitcherItem* tab_item,
+        void (^completion)(WebStateTabSwitcherItem* item,
+                           TabSnapshotAndFavicon* tab_snapshot_and_favicon)) {
+  FetchSnapshotAndFaviconForTabSwitcherItem(tab_item, /*fetch_snapshot=*/true,
+                                            completion);
+}
+
+void TabSnapshotAndFaviconConfigurator::FetchFaviconForTabSwitcherItem(
+    WebStateTabSwitcherItem* tab_item,
+    void (^completion)(WebStateTabSwitcherItem* item,
+                       TabSnapshotAndFavicon* tab_snapshot)) {
+  FetchSnapshotAndFaviconForTabSwitcherItem(tab_item, /*fetch_snapshot=*/false,
+                                            completion);
+}
+
 #pragma mark - Private
 
 void TabSnapshotAndFaviconConfigurator::FetchSnapshotAndFaviconFromWebState(
@@ -233,3 +251,82 @@
   }
   completion(group_item, infos);
 }
+
+void TabSnapshotAndFaviconConfigurator::
+    FetchSnapshotAndFaviconForTabSwitcherItem(
+        WebStateTabSwitcherItem* tab_item,
+        bool fetch_snapshot,
+        void (^completion)(WebStateTabSwitcherItem* item,
+                           TabSnapshotAndFavicon* tab_snapshot_and_favicon)) {
+  if (!tab_item.webState) {
+    completion(tab_item, nil);
+    return;
+  }
+
+  TabSnapshotAndFavicon* tab_snapshot_and_favicon =
+      [[TabSnapshotAndFavicon alloc] init];
+
+  // Fetch the snapshot.
+  if (fetch_snapshot) {
+    SnapshotTabHelper::FromWebState(tab_item.webState)
+        ->RetrieveColorSnapshot(^(UIImage* snapshot) {
+          // If there is no available snapshot, configure the snapshot to be an
+          // empty image in order to pass
+          // `OnSnapshotAndFaviconForTabSwitcherItemFetched` checks.
+          tab_snapshot_and_favicon.snapshot = snapshot;
+          completion(tab_item, tab_snapshot_and_favicon);
+        });
+  }
+
+  UIImageConfiguration* configuration = [UIImageSymbolConfiguration
+      configurationWithPointSize:kFaviconSize
+                          weight:UIImageSymbolWeightBold
+                           scale:UIImageSymbolScaleMedium];
+  const GURL& url = tab_item.webState->GetVisibleURL();
+
+  // Set the NTP favicon.
+  if (IsUrlNtp(url)) {
+    // Each WebStateTabSwitcherItem subclass provides its own NTPFavicon.
+    tab_snapshot_and_favicon.favicon = tab_item.NTPFavicon;
+    completion(tab_item, tab_snapshot_and_favicon);
+    return;
+  }
+
+  // Use the favicon driver.
+  favicon::FaviconDriver* favicon_driver =
+      favicon::WebFaviconDriver::FromWebState(tab_item.webState);
+  if (favicon_driver) {
+    gfx::Image favicon = favicon_driver->GetFavicon();
+    if (!favicon.IsEmpty()) {
+      tab_snapshot_and_favicon.favicon = favicon.ToUIImage();
+      completion(tab_item, tab_snapshot_and_favicon);
+      return;
+    }
+  }
+
+  // Set the default favicon.
+  UIImage* default_favicon =
+      DefaultSymbolWithConfiguration(kGlobeAmericasSymbol, configuration);
+  if (!favicon_loader_) {
+    tab_snapshot_and_favicon.favicon = default_favicon;
+    completion(tab_item, tab_snapshot_and_favicon);
+    return;
+  }
+
+  // Fetch the favicon.
+  favicon_loader_->FaviconForPageUrl(
+      url, kFaviconSize, kFaviconMinimumSize,
+      /*fallback_to_google_server=*/true, ^(FaviconAttributes* attributes) {
+        // Synchronously returned default favicon.
+        if (attributes.usesDefaultImage) {
+          return;
+        }
+        // Asynchronously returned favicon.
+        if (attributes.faviconImage) {
+          tab_snapshot_and_favicon.favicon = attributes.faviconImage;
+        } else {
+          tab_snapshot_and_favicon.favicon = default_favicon;
+        }
+        completion(tab_item, tab_snapshot_and_favicon);
+      });
+}
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator_unittest.mm
index 746e17e..600e04cc 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator_unittest.mm
@@ -15,6 +15,7 @@
 #import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
 #import "ios/chrome/common/ui/favicon/favicon_attributes.h"
 #import "ios/web/public/test/fakes/fake_web_state.h"
 #import "ios/web/public/test/web_task_environment.h"
@@ -133,3 +134,38 @@
         return completion_block_called;
       }));
 }
+
+// Tests the default use case of `FetchSnapshotAndFaviconForTabSwitcherItem:`.
+TEST_F(TabSnapshotAndFaviconConfiguratorTest,
+       FetchSnapshotAndFaviconForTabSwitcherItem) {
+  WebStateTabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
+      initWithWebState:web_state_list_->GetWebStateAt(0)];
+  __block int completion_block_called = 0;
+  auto completion_block = ^(WebStateTabSwitcherItem* inner_item,
+                            TabSnapshotAndFavicon* tab_snapshot_and_favicon) {
+    completion_block_called++;
+  };
+  _configurator->FetchSnapshotAndFaviconForTabSwitcherItem(item,
+                                                           completion_block);
+  ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      TestTimeouts::action_timeout(), ^bool() {
+        return completion_block_called == 2;
+      }));
+}
+
+// Tests the default use case of `FetchFaviconForTabSwitcherItem:`.
+TEST_F(TabSnapshotAndFaviconConfiguratorTest, FetchFaviconForTabSwitcherItem) {
+  WebStateTabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
+      initWithWebState:web_state_list_->GetWebStateAt(0)];
+  __block int completion_block_called = 0;
+  auto completion_block =
+      ^(TabSwitcherItem* inner_item, TabSnapshotAndFavicon* tab_snapshot) {
+        completion_block_called++;
+        ASSERT_LE(completion_block_called, 2);
+      };
+  _configurator->FetchFaviconForTabSwitcherItem(item, completion_block);
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      TestTimeouts::action_timeout(), ^bool() {
+        return completion_block_called == 1;
+      }));
+}
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/BUILD.gn
index f00a786..899c6ede 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/BUILD.gn
@@ -20,8 +20,10 @@
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/collaboration/model",
     "//ios/chrome/browser/collaboration/model:collaboration_delegate",
+    "//ios/chrome/browser/collaboration/model:features",
     "//ios/chrome/browser/collaboration/model/messaging",
     "//ios/chrome/browser/drag_and_drop/model",
+    "//ios/chrome/browser/favicon/model",
     "//ios/chrome/browser/main/model",
     "//ios/chrome/browser/ntp/model:util",
     "//ios/chrome/browser/policy/model:policy_util",
@@ -78,6 +80,7 @@
     "//ios/chrome/browser/shared/model/web_state_list",
     "//ios/chrome/browser/shared/model/web_state_list:utils",
     "//ios/chrome/browser/tab_switcher/ui_bundled:items",
+    "//ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui",
     "//ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui:swift",
   ]
 }
@@ -136,6 +139,7 @@
     "//ios/chrome/browser/tab_switcher/ui_bundled",
     "//ios/chrome/browser/tab_switcher/ui_bundled:items",
     "//ios/chrome/browser/tab_switcher/ui_bundled:utils",
+    "//ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui",
     "//ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui:swift",
     "//ios/chrome/browser/url_loading/model",
     "//ios/chrome/browser/url_loading/model:test_support",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_coordinator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_coordinator.mm
index 55b73f0..f9a900a 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_coordinator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_coordinator.mm
@@ -15,8 +15,10 @@
 #import "components/strings/grit/components_strings.h"
 #import "components/tab_groups/tab_group_visual_data.h"
 #import "ios/chrome/browser/collaboration/model/collaboration_service_factory.h"
+#import "ios/chrome/browser/collaboration/model/features.h"
 #import "ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.h"
 #import "ios/chrome/browser/collaboration/model/messaging/messaging_backend_service_factory.h"
+#import "ios/chrome/browser/favicon/model/ios_chrome_favicon_loader_factory.h"
 #import "ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/shared/coordinator/alert/alert_coordinator.h"
@@ -123,12 +125,21 @@
   collaboration::CollaborationService* collaborationService =
       collaboration::CollaborationServiceFactory::GetForProfile(profile);
 
+  FaviconLoader* faviconLoader = nil;
+  // Fetch favicons if in regular mode and sync or shared tab groups is enabled.
+  if (!profile->IsOffTheRecord() &&
+      (IsTabGroupSyncEnabled() ||
+       IsSharedTabGroupsJoinEnabled(collaborationService))) {
+    faviconLoader = IOSChromeFaviconLoaderFactory::GetForProfile(profile);
+  }
+
   self.mediator =
       [[TabStripMediator alloc] initWithConsumer:self.tabStripViewController
                              tabGroupSyncService:tabGroupSyncService
                                      browserList:browserList
                                 messagingService:messagingService
-                            collaborationService:collaborationService];
+                            collaborationService:collaborationService
+                                   faviconLoader:faviconLoader];
   self.mediator.webStateList = self.browser->GetWebStateList();
   self.mediator.profile = profile;
   self.mediator.browser = self.browser;
@@ -147,6 +158,7 @@
 
   self.tabStripViewController.mutator = self.mediator;
   self.tabStripViewController.dragDropHandler = self.mediator;
+  self.tabStripViewController.snapshotAndfaviconDataSource = self.mediator;
   self.tabStripViewController.contextMenuProvider = self.contextMenuHelper;
 }
 
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.h
index f61bba4c3..8e50f18 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.h
@@ -9,9 +9,11 @@
 
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_handler.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_mutator.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 
 class Browser;
 class BrowserList;
+class FaviconLoader;
 class ProfileIOS;
 enum class TabGroupActionType;
 @protocol TabStripCommands;
@@ -42,7 +44,9 @@
 
 // This mediator used to manage model interaction for its consumer.
 @interface TabStripMediator
-    : NSObject <TabCollectionDragDropHandler, TabStripMutator>
+    : NSObject <TabCollectionDragDropHandler,
+                TabSwitcherItemSnapShotAndFaviconDataSource,
+                TabStripMutator>
 
 // The WebStateList that this mediator listens for any changes on the total
 // number of Webstates.
@@ -70,6 +74,7 @@
             (collaboration::messaging::MessagingBackendService*)messagingService
     collaborationService:
         (collaboration::CollaborationService*)collaborationService
+           faviconLoader:(FaviconLoader*)faviconLoader
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)init NS_UNAVAILABLE;
 
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.mm
index 24b98583..2eb7eb1 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator.mm
@@ -22,6 +22,7 @@
 #import "ios/chrome/browser/collaboration/model/collaboration_service_factory.h"
 #import "ios/chrome/browser/collaboration/model/messaging/messaging_backend_service_bridge.h"
 #import "ios/chrome/browser/drag_and_drop/model/drag_item_util.h"
+#import "ios/chrome/browser/favicon/model/favicon_loader.h"
 #import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
 #import "ios/chrome/browser/policy/model/policy_util.h"
 #import "ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_util.h"
@@ -48,11 +49,12 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_action_type.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon_configurator.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_utils.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/swift.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_features_utils.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_utils.h"
-#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_browser_agent.h"
 #import "ios/chrome/browser/url_loading/model/url_loading_params.h"
 #import "ios/chrome/browser/web_state_list/model/web_state_list_favicon_driver_observer.h"
@@ -286,6 +288,8 @@
   std::unique_ptr<MessagingBackendServiceBridge> _messagingBackendServiceBridge;
   // The collaboration service for shared tab group.
   raw_ptr<collaboration::CollaborationService> _collaborationService;
+  // Helper class to configure tab item images.
+  std::unique_ptr<TabSnapshotAndFaviconConfigurator> _tabImagesConfigurator;
   // A set of a tab ID that has changed and a user has not seen it yet.
   std::set<tab_groups::LocalTabID> _dirtyTabs;
   // A set of a shared group ID that has changed and a user has not seen it yet.
@@ -303,7 +307,8 @@
         messagingService:
             (collaboration::messaging::MessagingBackendService*)messagingService
     collaborationService:
-        (collaboration::CollaborationService*)collaborationService {
+        (collaboration::CollaborationService*)collaborationService
+           faviconLoader:(FaviconLoader*)faviconLoader {
   if ((self = [super init])) {
     CHECK(browserList);
     _browserList = browserList;
@@ -311,6 +316,8 @@
     _tabGroupSyncService = tabGroupSyncService;
     _consumer = consumer;
     _messagingService = messagingService;
+    _tabImagesConfigurator =
+        std::make_unique<TabSnapshotAndFaviconConfigurator>(faviconLoader);
     if (_messagingService) {
       _messagingBackendServiceBridge =
           std::make_unique<MessagingBackendServiceBridge>(self);
@@ -538,7 +545,7 @@
           change.As<WebStateListChangeDetach>();
       web::WebState* detachedWebState = detachChange.detached_web_state();
       TabStripItemIdentifier* item = [TabStripItemIdentifier
-          tabIdentifier:[[WebStateTabSwitcherItem alloc]
+          tabIdentifier:[[TabStripTabItem alloc]
                             initWithWebState:detachedWebState]];
       [self.consumer removeItems:@[ item ]];
       // Reconfigure the group items if needed.
@@ -627,11 +634,11 @@
       const WebStateListChangeReplace& replaceChange =
           change.As<WebStateListChangeReplace>();
       const int index = replaceChange.index();
-      TabSwitcherItem* oldItem = [[WebStateTabSwitcherItem alloc]
+      TabSwitcherItem* oldItem = [[TabStripTabItem alloc]
           initWithWebState:replaceChange.replaced_web_state()];
       web::WebState* newWebState = replaceChange.inserted_web_state();
       TabSwitcherItem* newItem =
-          [[WebStateTabSwitcherItem alloc] initWithWebState:newWebState];
+          [[TabStripTabItem alloc] initWithWebState:newWebState];
       TabStripItemIdentifier* newItemIdentifier =
           [TabStripItemIdentifier tabIdentifier:newItem];
       TabStripItemData* newItemData =
@@ -757,8 +764,8 @@
       [self.consumer selectItem:nil];
       return;
     }
-    TabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
-        initWithWebState:status.new_active_web_state];
+    TabSwitcherItem* item =
+        [[TabStripTabItem alloc] initWithWebState:status.new_active_web_state];
     [self.consumer selectItem:item];
     // If the active WebState is in a group, ensure that group is not collapsed.
     const TabGroup* groupOfActiveWebState =
@@ -1380,6 +1387,21 @@
   }
 }
 
+#pragma mark - TabSwitcherItemSnapShotAndFaviconDataSource
+
+// Fetches the `item` info and executes the given `completion` block.
+- (void)fetchTabSnapshotAndFavicon:(TabSwitcherItem*)item
+                        completion:
+                            (TabSnapshotAndFaviconFetchingCompletionBlock)
+                                completion {
+  TabStripTabItem* tabSwitcherItem =
+      base::apple::ObjCCastStrict<TabStripTabItem>(item);
+  // This method uses `FetchFaviconForTabSwitcherItem` that only fetches the
+  // favicon, as the snapshot is not used in the tab strip.
+  _tabImagesConfigurator->FetchFaviconForTabSwitcherItem(tabSwitcherItem,
+                                                         completion);
+}
+
 #pragma mark - Private
 
 // Adds an observation to every WebState of the current WebSateList.
@@ -1398,7 +1420,7 @@
 - (void)populateConsumerItems {
   TabSwitcherItem* selectedItem = nil;
   if (_webStateList->GetActiveWebState()) {
-    selectedItem = [[WebStateTabSwitcherItem alloc]
+    selectedItem = [[TabStripTabItem alloc]
         initWithWebState:_webStateList->GetActiveWebState()];
   }
   NSArray<TabStripItemIdentifier*>* itemIdentifiers =
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_unittest.mm
index 973f45c..0f769b6 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_unittest.mm
@@ -9,6 +9,7 @@
 #import "base/test/ios/wait_util.h"
 #import "base/test/metrics/histogram_tester.h"
 #import "base/test/scoped_feature_list.h"
+#import "base/test/test_timeouts.h"
 #import "components/collaboration/test_support/mock_messaging_backend_service.h"
 #import "components/data_sharing/public/features.h"
 #import "components/favicon/core/favicon_service.h"
@@ -44,8 +45,8 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/fake_tab_strip_consumer.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/fake_tab_strip_handler.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/swift.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h"
-#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
 #import "ios/chrome/browser/url_loading/model/fake_url_loading_delegate.h"
 #import "ios/chrome/browser/url_loading/model/scene_url_loading_service.h"
 #import "ios/chrome/browser/url_loading/model/test_scene_url_loading_service.h"
@@ -161,7 +162,8 @@
                                tabGroupSyncService:tab_group_sync_service_.get()
                                        browserList:browser_list
                                   messagingService:&messaging_backend_
-                              collaborationService:nil];
+                              collaborationService:nil
+                                     faviconLoader:nil];
 
     mediator_.profile = profile_.get();
     mediator_.webStateList = web_state_list_;
@@ -714,7 +716,7 @@
   ASSERT_EQ(1, web_state_list_->active_index());
   ASSERT_EQ(2, web_state_list_->count());
 
-  TabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
+  TabSwitcherItem* item = [[TabStripTabItem alloc]
       initWithWebState:web_state_list_->GetWebStateAt(0)];
 
   [mediator_ activateItem:item];
@@ -735,7 +737,7 @@
   ASSERT_EQ(1, web_state_list_->active_index());
   ASSERT_EQ(2, web_state_list_->count());
 
-  TabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
+  TabSwitcherItem* item = [[TabStripTabItem alloc]
       initWithWebState:web_state_list_->GetWebStateAt(1)];
   [mediator_ closeItem:item];
 
@@ -764,7 +766,7 @@
   ASSERT_EQ(4, web_state_list_->count());
   EXPECT_EQ(2, group->range().count());
 
-  TabSwitcherItem* item = [[WebStateTabSwitcherItem alloc]
+  TabSwitcherItem* item = [[TabStripTabItem alloc]
       initWithWebState:web_state_list_->GetWebStateAt(1)];
   [mediator_ removeItemFromGroup:item];
 
@@ -795,7 +797,7 @@
   EXPECT_CALL(*tab_group_sync_service_, RemoveGroup(tab_group_id)).Times(0);
 
   TabSwitcherItem* item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state_to_keep];
+      [[TabStripTabItem alloc] initWithWebState:web_state_to_keep];
   [mediator_ closeAllItemsExcept:item];
 
   ASSERT_EQ("a b* |", builder.GetWebStateListDescription());
@@ -824,7 +826,7 @@
   EXPECT_CALL(*tab_group_sync_service_, RemoveGroup(tab_group_id)).Times(0);
 
   TabSwitcherItem* item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state_to_keep];
+      [[TabStripTabItem alloc] initWithWebState:web_state_to_keep];
   [mediator_ closeAllItemsExcept:item];
 
   ASSERT_EQ("a b | d*", builder.GetWebStateListDescription());
@@ -853,7 +855,7 @@
   EXPECT_CALL(*tab_group_sync_service_, RemoveGroup(tab_group_id)).Times(0);
 
   TabSwitcherItem* item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state_to_keep];
+      [[TabStripTabItem alloc] initWithWebState:web_state_to_keep];
   [mediator_ closeAllItemsExcept:item];
 
   ASSERT_EQ("a b | f*", builder.GetWebStateListDescription());
@@ -878,7 +880,7 @@
   EXPECT_CALL(*tab_group_sync_service_, RemoveGroup(tab_group_id)).Times(0);
 
   TabSwitcherItem* item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state_to_keep];
+      [[TabStripTabItem alloc] initWithWebState:web_state_to_keep];
   [mediator_ closeAllItemsExcept:item];
 
   ASSERT_EQ("a b | [ 1 g* ]", builder.GetWebStateListDescription());
@@ -956,7 +958,7 @@
   const int web_state_index = 1;
   web::WebState* web_state = web_state_list_->GetWebStateAt(web_state_index);
   TabSwitcherItem* tab_switcher_item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state];
+      [[TabStripTabItem alloc] initWithWebState:web_state];
   [mediator_ createNewGroupWithItem:tab_switcher_item];
   EXPECT_EQ(std::set<web::WebStateID>{tab_switcher_item.identifier},
             tab_strip_handler_.identifiersForTabGroupCreation);
@@ -1159,7 +1161,7 @@
 
   web::WebState* web_state_1 = web_state_list_->GetWebStateAt(1);
   TabSwitcherItem* item_for_web_state_1 =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state_1];
+      [[TabStripTabItem alloc] initWithWebState:web_state_1];
   [mediator_ addItem:item_for_web_state_1 toGroup:group];
 
   // Check model is updated.
@@ -1721,3 +1723,24 @@
   EXPECT_EQ(consumer_.itemData[consumer_.items[2]].hasNotificationDot, NO);
   EXPECT_EQ(consumer_.itemData[consumer_.items[3]].hasNotificationDot, NO);
 }
+
+// Tests that `fetchTabSnapshotAndFavicon:completion:` is calling `completion`
+// once.
+TEST_F(TabStripMediatorTest, FetchTabSnapshotAndFavicon) {
+  auto fake_web_state = std::make_unique<web::FakeWebState>();
+  web::FakeWebState* web_state = fake_web_state.get();
+  SnapshotTabHelper::CreateForWebState(web_state);
+  TabStripTabItem* item = [[TabStripTabItem alloc] initWithWebState:web_state];
+  __block int completion_block_called = 0;
+  auto completion_block = ^(TabSwitcherItem* inner_item,
+                            TabSnapshotAndFavicon* tab_snapshot_and_favicon) {
+    completion_block_called++;
+    ASSERT_LE(completion_block_called, 1);
+  };
+  InitializeMediator();
+  [mediator_ fetchTabSnapshotAndFavicon:item completion:completion_block];
+  EXPECT_TRUE(base::test::ios::WaitUntilConditionOrTimeout(
+      TestTimeouts::action_timeout(), ^bool() {
+        return completion_block_called == 1;
+      }));
+}
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_utils.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_utils.mm
index 8d38ada..a9eea379 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_utils.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/coordinator/tab_strip_mediator_utils.mm
@@ -11,11 +11,11 @@
 #import "ios/chrome/browser/shared/model/web_state_list/tab_group.h"
 #import "ios/chrome/browser/shared/model/web_state_list/tab_utils.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/swift.h"
-#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h"
 
 TabStripItemIdentifier* CreateTabItemIdentifier(web::WebState* web_state) {
   TabSwitcherItem* tab_item =
-      [[WebStateTabSwitcherItem alloc] initWithWebState:web_state];
+      [[TabStripTabItem alloc] initWithWebState:web_state];
   TabStripItemIdentifier* tab_item_identifier =
       [TabStripItemIdentifier tabIdentifier:tab_item];
   return tab_item_identifier;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/BUILD.gn
index 18bbb4a6..cc1f6c2 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/BUILD.gn
@@ -48,6 +48,8 @@
     "tab_strip_mutator.h",
     "tab_strip_tab_cell.h",
     "tab_strip_tab_cell.mm",
+    "tab_strip_tab_item.h",
+    "tab_strip_tab_item.mm",
   ]
   deps = [
     ":swift_constants_for_objective_c",
@@ -59,6 +61,8 @@
     "//ios/chrome/browser/shared/ui/util",
     "//ios/chrome/browser/shared/ui/util",
     "//ios/chrome/browser/shared/ui/util/image",
+    "//ios/chrome/browser/tab_switcher/ui_bundled:items",
+    "//ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs:constants",
     "//ios/chrome/common/ui/colors",
     "//ios/chrome/common/ui/elements",
     "//ios/chrome/common/ui/util",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm
index d084203..eb270d0 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.mm
@@ -68,11 +68,6 @@
 constexpr CGFloat kBlueDotSize = 6 + kBlueDotStrokeWidth * 2;
 constexpr CGFloat kBlueDotInset = 1;
 
-// Returns the default favicon image.
-UIImage* DefaultFavicon() {
-  return DefaultSymbolWithPointSize(kGlobeAmericasSymbol, 14);
-}
-
 }  // namespace
 
 @implementation TabStripTabCell {
@@ -256,11 +251,7 @@
 }
 
 - (void)setFaviconImage:(UIImage*)image {
-  if (!image) {
-    _faviconView.image = DefaultFavicon();
-  } else {
-    _faviconView.image = image;
-  }
+  _faviconView.image = image;
 }
 
 #pragma mark - TabStripCell
@@ -311,7 +302,7 @@
     _activityIndicator.hidden = NO;
     [_activityIndicator startAnimating];
     _faviconView.hidden = YES;
-    _faviconView.image = DefaultFavicon();
+    _faviconView.image = nil;
   } else {
     _activityIndicator.hidden = YES;
     [_activityIndicator stopAnimating];
@@ -1038,8 +1029,7 @@
 
 // Returns a new favicon view.
 - (UIImageView*)createFaviconView {
-  UIImageView* faviconView =
-      [[UIImageView alloc] initWithImage:DefaultFavicon()];
+  UIImageView* faviconView = [[UIImageView alloc] init];
   faviconView.translatesAutoresizingMaskIntoConstraints = NO;
   faviconView.contentMode = UIViewContentModeScaleAspectFit;
   return faviconView;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h
new file mode 100644
index 0000000..8c560b9
--- /dev/null
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h
@@ -0,0 +1,16 @@
+// 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 IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_STRIP_UI_TAB_STRIP_TAB_ITEM_H_
+#define IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_STRIP_UI_TAB_STRIP_TAB_ITEM_H_
+
+#import "ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h"
+
+// Item for tabs in tab strip overriding the methods from
+// WebStateTabSwitcherItem.
+@interface TabStripTabItem : WebStateTabSwitcherItem
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_STRIP_UI_TAB_STRIP_TAB_ITEM_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.mm
new file mode 100644
index 0000000..f566478
--- /dev/null
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.mm
@@ -0,0 +1,25 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_item.h"
+
+#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/pinned_tabs/pinned_tabs_constants.h"
+
+namespace {
+
+// Size of the NTP symbol in points.
+const CGFloat kSymbolSize = 14.0;
+
+}  // namespace
+
+@implementation TabStripTabItem
+
+#pragma mark - Favicons
+
+- (UIImage*)NTPFavicon {
+  return DefaultSymbolWithPointSize(kGlobeAmericasSymbol, kSymbolSize);
+}
+
+@end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_ui_swift_bridge.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_ui_swift_bridge.h
index 31cd3ff..8fc8461 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_ui_swift_bridge.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_ui_swift_bridge.h
@@ -15,6 +15,7 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_handler.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_group_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_snapshot_and_favicon.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/context_menu/tab_strip_context_menu_provider.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_features_utils.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_group_cell.h"
@@ -22,6 +23,7 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_tab_cell.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_utils.h"
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h"
+#import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h"
 #import "ios/chrome/common/ui/colors/semantic_color_names.h"
 #import "ios/chrome/common/ui/elements/gradient_view.h"
 #import "ios/chrome/grit/ios_strings.h"
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_view_controller.swift b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_view_controller.swift
index 53fe7df..5a532f3 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_view_controller.swift
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_strip/ui/tab_strip_view_controller.swift
@@ -80,7 +80,8 @@
   public weak var dragDropHandler: TabCollectionDragDropHandler?
   /// Provides context menu for tab strip items.
   public weak var contextMenuProvider: TabStripContextMenuProvider?
-
+  /// Handles snapshots and favicons fetches.
+  public weak var snapshotAndfaviconDataSource: TabSwitcherItemSnapShotAndFaviconDataSource?
   /// Handler for tab group confirmation commands.
   public weak var tabGroupConfirmationHandler: TabGroupConfirmationCommands?
 
@@ -584,11 +585,13 @@
         }
       }
 
-      item.fetchFavicon { (item: TabSwitcherItem?, image: UIImage?) -> Void in
+      let completion = {
+        (item: TabSwitcherItem?, tabSnapshotAndFavicon: TabSnapshotAndFavicon?) -> Void in
         if let item = item, item == cell.item {
-          cell.setFaviconImage(image)
+          cell.setFaviconImage(tabSnapshotAndFavicon?.favicon)
         }
       }
+      self.snapshotAndfaviconDataSource?.fetchTabSnapshotAndFavicon(item, completion: completion)
     }
 
     // UICollectionViewDropPlaceholder uses a TabStripTabCell and needs the class to be
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h
index 483e3f4..ae2a252 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h
@@ -44,16 +44,6 @@
 @property(nonatomic, readonly) BOOL hidesTitle;
 @property(nonatomic, readonly) BOOL showsActivity;
 
-#pragma mark - Image Fetching
-
-// Fetches the favicon, calling `completion` on the calling sequence when the
-// operation completes.
-- (void)fetchFavicon:(TabSwitcherImageFetchingCompletionBlock)completion;
-
-// Fetches the snapshot, calling `completion` on the calling sequence when the
-// operation completes.
-- (void)fetchSnapshot:(TabSwitcherImageFetchingCompletionBlock)completion;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_SWITCHER_ITEM_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.mm
index c033c80d..a5384e2 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.mm
@@ -5,7 +5,6 @@
 #import "ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item.h"
 
 #import "base/check.h"
-#import "base/debug/dump_without_crashing.h"
 #import "ios/web/public/web_state_id.h"
 #import "url/gurl.h"
 
@@ -27,26 +26,4 @@
       [NSString stringWithFormat:@"Tab ID: %d", self.identifier.identifier()];
 }
 
-#pragma mark - Image Fetching
-
-- (void)fetchFavicon:(TabSwitcherImageFetchingCompletionBlock)completion {
-  // Subclasses should override this method. It is OK not to call super.
-  completion(self, nil);
-  // This should not be called in production, as only real
-  // WebStateTabSwitcherItem should be asked to fetch a favicon.
-  // TODO(crbug.com/331159004): Remove in a later milestone if we don't receive
-  // any.
-  base::debug::DumpWithoutCrashing();
-}
-
-- (void)fetchSnapshot:(TabSwitcherImageFetchingCompletionBlock)completion {
-  // Subclasses should override this method. It is OK not to call super.
-  completion(self, nil);
-  // This should not be called in production, as only real
-  // WebStateTabSwitcherItem should be asked to fetch a snapshot.
-  // TODO(crbug.com/331159004): Remove in a later milestone if we don't receive
-  // any.
-  base::debug::DumpWithoutCrashing();
-}
-
 @end
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h
new file mode 100644
index 0000000..2ea5469
--- /dev/null
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_switcher_item_snapshot_and_favicon_data_source.h
@@ -0,0 +1,31 @@
+// 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 IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_SWITCHER_ITEM_SNAPSHOT_AND_FAVICON_DATA_SOURCE_H_
+#define IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_SWITCHER_ITEM_SNAPSHOT_AND_FAVICON_DATA_SOURCE_H_
+
+@class TabSnapshotAndFavicon;
+@class TabSwitcherItem;
+
+// Block invoked when a TabSnapshotAndFavicon fetching operation completes. The
+// `tabSnapshotAndFavicon` is nil if the operation failed.
+typedef void (^TabSnapshotAndFaviconFetchingCompletionBlock)(
+    TabSwitcherItem* item,
+    TabSnapshotAndFavicon* tabSnapshotAndFavicon);
+
+// Protocol that the UI uses to retrieve snapshots and favicons for tab
+// switcher items.
+@protocol TabSwitcherItemSnapShotAndFaviconDataSource
+
+// Fetches the `item` snapshot and favicon.
+// The `completion` block is invoked twice: once when the snapshot has been
+// fetched, and again when the favicon has been fetched.
+- (void)fetchTabSnapshotAndFavicon:(TabSwitcherItem*)item
+                        completion:
+                            (TabSnapshotAndFaviconFetchingCompletionBlock)
+                                completion;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_SWITCHER_ITEM_SNAPSHOT_AND_FAVICON_DATA_SOURCE_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h b/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h
index 36447c6c..45503a6 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.h
@@ -19,13 +19,12 @@
     NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithIdentifier:(web::WebStateID)identifier NS_UNAVAILABLE;
 
+// The web state represented by this item.
+@property(nonatomic, readonly) web::WebState* webState;
+
 #pragma mark - Favicons
 
-// Default favicon to use if the tab has no favicon available yet. Default is
-// `kGlobeAmericasSymbol`.
-- (UIImage*)defaultFavicon;
-
-// Favicon to use for NTP. Default is nil.
+// Favicon to use for NTP. Default is an empty image.
 // Subclasses can override this method to customize it.
 - (UIImage*)NTPFavicon;
 
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.mm b/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.mm
index 34d10c0..35c34100 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/web_state_tab_switcher_item.mm
@@ -8,15 +8,9 @@
 #import "base/memory/weak_ptr.h"
 #import "components/favicon/ios/web_favicon_driver.h"
 #import "ios/chrome/browser/shared/model/url/url_util.h"
-#import "ios/chrome/browser/shared/ui/symbols/symbols.h"
-#import "ios/chrome/browser/snapshots/model/snapshot_tab_helper.h"
 #import "ios/chrome/browser/tabs/model/tab_title_util.h"
 #import "ios/web/public/web_state.h"
 
-namespace {
-const CGFloat kSymbolSize = 16;
-}
-
 @implementation WebStateTabSwitcherItem {
   // The web state represented by this item.
   base::WeakPtr<web::WebState> _webState;
@@ -31,6 +25,10 @@
   return self;
 }
 
+- (web::WebState*)webState {
+  return _webState.get();
+}
+
 - (GURL)URL {
   if (!_webState) {
     return GURL();
@@ -59,66 +57,10 @@
   return _webState->IsLoading();
 }
 
-#pragma mark - Image Fetching
-
-- (void)fetchFavicon:(TabSwitcherImageFetchingCompletionBlock)completion {
-  web::WebState* webState = _webState.get();
-  if (!webState) {
-    completion(self, nil);
-    return;
-  }
-
-  // NTP tabs have special treatment.
-  if (IsUrlNtp(webState->GetVisibleURL())) {
-    completion(self, [self NTPFavicon]);
-    return;
-  }
-
-  // Use the page favicon.
-  favicon::FaviconDriver* faviconDriver =
-      favicon::WebFaviconDriver::FromWebState(webState);
-  // The favicon driver may be null during testing.
-  if (faviconDriver) {
-    gfx::Image favicon = faviconDriver->GetFavicon();
-    if (!favicon.IsEmpty()) {
-      completion(self, favicon.ToUIImage());
-      return;
-    }
-  }
-
-  // Otherwise, set a default favicon.
-  completion(self, [self defaultFavicon]);
-}
-
-- (void)fetchSnapshot:(TabSwitcherImageFetchingCompletionBlock)completion {
-  web::WebState* webState = _webState.get();
-  if (!webState) {
-    completion(self, nil);
-    return;
-  }
-
-  __weak __typeof(self) weakSelf = self;
-  SnapshotTabHelper::FromWebState(webState)->RetrieveColorSnapshot(
-      ^(UIImage* snapshot) {
-        if (weakSelf) {
-          completion(weakSelf, snapshot);
-        }
-      });
-}
-
 #pragma mark - Favicons
 
-- (UIImage*)defaultFavicon {
-  UIImageConfiguration* configuration = [UIImageSymbolConfiguration
-      configurationWithPointSize:kSymbolSize
-                          weight:UIImageSymbolWeightBold
-                           scale:UIImageSymbolScaleMedium];
-  return DefaultSymbolWithConfiguration(kGlobeAmericasSymbol, configuration);
-}
-
 - (UIImage*)NTPFavicon {
-  // By default NTP tabs gets no favicon.
-  return nil;
+  return [[UIImage alloc] init];
 }
 
 #pragma mark - NSObject
@@ -130,9 +72,9 @@
   if (![object isKindOfClass:[WebStateTabSwitcherItem class]]) {
     return NO;
   }
-  WebStateTabSwitcherItem* otherTabStrip =
+  WebStateTabSwitcherItem* otherItem =
       base::apple::ObjCCastStrict<WebStateTabSwitcherItem>(object);
-  return self.identifier == otherTabStrip.identifier;
+  return self.identifier == otherItem.identifier;
 }
 
 - (NSUInteger)hash {
diff --git a/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm b/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm
index 90936bb..3b8e708 100644
--- a/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm
+++ b/ios/chrome/browser/web/model/font_size/font_size_tab_helper.mm
@@ -260,7 +260,7 @@
 }
 
 void FontSizeTabHelper::WebStateRealized(web::WebState* web_state) {
-  CHECK(!notification_observer_, base::NotFatalUntil::M125);
+  CHECK(!notification_observer_);
   CreateNotificationObserver();
 }
 
diff --git a/ios/chrome/browser/web/model/sad_tab_tab_helper.mm b/ios/chrome/browser/web/model/sad_tab_tab_helper.mm
index e999c4b..2791b10 100644
--- a/ios/chrome/browser/web/model/sad_tab_tab_helper.mm
+++ b/ios/chrome/browser/web/model/sad_tab_tab_helper.mm
@@ -134,7 +134,7 @@
 }
 
 void SadTabTabHelper::WebStateRealized(web::WebState* web_state) {
-  CHECK(!background_notification_observer_, base::NotFatalUntil::M125);
+  CHECK(!background_notification_observer_);
   CreateNotificationObserver();
 }
 
diff --git a/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h b/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h
index 1e86c1b..7bd018d 100644
--- a/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h
+++ b/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.h
@@ -71,9 +71,6 @@
   void WebStateRealized(web::WebState* web_state) override;
   void WebStateDestroyed(web::WebState* web_state) override;
 
-  // The browser whose WebStates' web usage is being managed.
-  raw_ptr<Browser> browser_ = nullptr;
-
   // Whether web usage is enabled for the WebState in `web_state_list_`.
   bool web_usage_enabled_ = false;
 
diff --git a/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.mm b/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.mm
index d9044403..2cc845e3 100644
--- a/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.mm
+++ b/ios/chrome/browser/web_state_list/model/web_usage_enabler/web_usage_enabler_browser_agent.mm
@@ -8,7 +8,7 @@
 #import "ios/web/public/navigation/navigation_manager.h"
 
 WebUsageEnablerBrowserAgent::WebUsageEnablerBrowserAgent(Browser* browser)
-    : BrowserUserData(browser), browser_(browser) {
+    : BrowserUserData(browser) {
   browser_observation_.Observe(browser_.get());
 
   WebStateList* web_state_list = browser_->GetWebStateList();
diff --git a/ios_internal b/ios_internal
index caa545d..a5c6f36 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit caa545d88ae49b674a6d9542f80c5514d0cfc18e
+Subproject commit a5c6f36c55a93150abaf43134d5c40dc42112f9d
diff --git a/media/audio/win/audio_low_latency_input_win.cc b/media/audio/win/audio_low_latency_input_win.cc
index 123a527..2271e41 100644
--- a/media/audio/win/audio_low_latency_input_win.cc
+++ b/media/audio/win/audio_low_latency_input_win.cc
@@ -32,6 +32,7 @@
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/synchronization/waitable_event.h"
+#include "base/timer/elapsed_timer.h"
 #include "base/trace_event/common/trace_event_common.h"
 #include "base/trace_event/trace_event.h"
 #include "base/win/core_winrt_util.h"
@@ -77,6 +78,10 @@
 // device) being played out.
 constexpr uint32_t kWindowsSystemProcessId = 4;
 
+// HRESULT_FROM_WIN32(WAIT_TIMEOUT) yields 0x80070102, which is a well-known COM
+// error for timeouts.
+constexpr HRESULT kActivationTimeoutHr = HRESULT_FROM_WIN32(WAIT_TIMEOUT);
+
 // Converts a COM error into a human-readable string.
 std::string ErrorToString(HRESULT hresult) {
   return CoreAudioUtil::ErrorToString(hresult);
@@ -522,7 +527,7 @@
                                 base::TimeDelta async_activation_timeout_ms) {
     // Wait for a maximum of 10 seconds for the activation to complete.
     if (!wait_event_.TimedWait(async_activation_timeout_ms)) {
-      return E_FAIL;
+      return kActivationTimeoutHr;
     }
 
     // If the activation was successful, move the audio client to the output
@@ -1526,6 +1531,8 @@
           },
   };
 
+  TRACE_EVENT("audio", "AudioClientActivation");
+  base::ElapsedTimer timer;
   ComPtr<AudioClientActivationHandler> completion_handler =
       Microsoft::WRL::Make<AudioClientActivationHandler>();
   ComPtr<IActivateAudioInterfaceAsyncOperation> async_op;
@@ -1533,11 +1540,25 @@
       VIRTUAL_AUDIO_DEVICE_PROCESS_LOOPBACK, __uuidof(IAudioClient),
       &propvariant, completion_handler.Get(), &async_op);
   if (FAILED(hr)) {
+    TRACE_EVENT_INSTANT0("audio", "ActivateAudioInterfaceAsync failed",
+                         TRACE_EVENT_SCOPE_THREAD);
     return hr;
   }
 
-  return completion_handler->WaitAndGetAudioClient(
-      &audio_client_, async_activation_timeout_ms_);
+  hr = completion_handler->WaitAndGetAudioClient(&audio_client_,
+                                                 async_activation_timeout_ms_);
+  const bool timed_out = (hr == kActivationTimeoutHr);
+  base::UmaHistogramBoolean("Media.Audio.Capture.Win.GetAudioClientTimedOut",
+                            timed_out);
+  if (!timed_out) {
+    base::UmaHistogramTimes("Media.Audio.Capture.Win.TimeToGetAudioClient",
+                            timer.Elapsed());
+  } else {
+    TRACE_EVENT_INSTANT0("audio", "GetAudioClient timed out",
+                         TRACE_EVENT_SCOPE_THREAD);
+  }
+
+  return hr;
 }
 
 bool WASAPIAudioInputStream::RawProcessingSupported() {
diff --git a/media/audio/win/audio_low_latency_input_win.h b/media/audio/win/audio_low_latency_input_win.h
index 482fd72..7ab264e 100644
--- a/media/audio/win/audio_low_latency_input_win.h
+++ b/media/audio/win/audio_low_latency_input_win.h
@@ -379,8 +379,6 @@
 
   // Timeout period for waiting on the OS to activate the audio interface for
   // application loopback capture.
-  // TODO(crbug.com/40947205): Add UMA stats to track the actual wait time in
-  // the field
   base::TimeDelta async_activation_timeout_ms_ = base::Seconds(10);
 
   SEQUENCE_CHECKER(sequence_checker_);
diff --git a/media/audio/win/audio_low_latency_input_win_unittest.cc b/media/audio/win/audio_low_latency_input_win_unittest.cc
index cb15f8c0..6e7f74ac 100644
--- a/media/audio/win/audio_low_latency_input_win_unittest.cc
+++ b/media/audio/win/audio_low_latency_input_win_unittest.cc
@@ -879,10 +879,15 @@
   AudioParameters params_;
   ScopedAudioInputStream stream_;
   FakeWinWASAPIEnvironment fake_wasapi_environment_;
+  base::HistogramTester histogram_tester_;
 };
 
 TEST_P(WinAudioProcessLoopbackTest, OpenStreamSuccess) {
   ASSERT_THAT(stream_->Open(), Eq(AudioInputStream::OpenOutcome::kSuccess));
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 1);
+  histogram_tester_.ExpectBucketCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", false, 1);
 }
 
 TEST_P(WinAudioProcessLoopbackTest,
@@ -890,6 +895,10 @@
   fake_wasapi_environment_.SimulateError(
       WASAPITestErrorCode::kActivateAudioInterfaceAsyncFailed);
   EXPECT_EQ(stream_->Open(), AudioInputStream::OpenOutcome::kFailed);
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 0);
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", 0);
 }
 
 TEST_P(WinAudioProcessLoopbackTest,
@@ -900,6 +909,10 @@
   // timeout is 10 seconds.
   OverrideAsyncActivationTimeout(kShortAsyncActivationTimeoutMs);
   EXPECT_EQ(stream_->Open(), AudioInputStream::OpenOutcome::kFailed);
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 0);
+  histogram_tester_.ExpectBucketCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", true, 1);
 }
 
 TEST_P(WinAudioProcessLoopbackTest,
@@ -910,12 +923,20 @@
   // timeout is 10 seconds.
   OverrideAsyncActivationTimeout(kShortAsyncActivationTimeoutMs);
   EXPECT_EQ(stream_->Open(), AudioInputStream::OpenOutcome::kFailed);
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 0);
+  histogram_tester_.ExpectBucketCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", true, 1);
 }
 
 TEST_P(WinAudioProcessLoopbackTest, OpenStreamAudioClientActivationFailed) {
   fake_wasapi_environment_.SimulateError(
       WASAPITestErrorCode::kAudioClientActivationFailed);
   EXPECT_EQ(stream_->Open(), AudioInputStream::OpenOutcome::kFailed);
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 1);
+  histogram_tester_.ExpectBucketCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", false, 1);
 }
 
 TEST_P(WinAudioProcessLoopbackTest, SuccessfulCapture) {
@@ -931,6 +952,10 @@
   EXPECT_EQ(sink.num_callbacks(), 2);
   EXPECT_GT(sink.num_received_audio_frames(), 0);
   EXPECT_FALSE(sink.error());
+  histogram_tester_.ExpectTotalCount(
+      "Media.Audio.Capture.Win.TimeToGetAudioClient", 1);
+  histogram_tester_.ExpectBucketCount(
+      "Media.Audio.Capture.Win.GetAudioClientTimedOut", false, 1);
 }
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc
index b914ce3..e1090c3 100644
--- a/net/cookies/cookie_monster.cc
+++ b/net/cookies/cookie_monster.cc
@@ -1735,7 +1735,7 @@
   // source type to kOther (or kHTTP/kScript where applicable). See
   // CookieSourceType in net/cookies/cookie_constants.h for more.
   if (cc->SourceType() == CookieSourceType::kUnknown) {
-    CHECK_IS_TEST(base::NotFatalUntil::M126);
+    CHECK_IS_TEST();
   }
 #endif
 
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 41a0418..a4c0a57 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2025-05-25 12:54 UTC
+# Last updated: 2025-05-26 12:53 UTC
 PinsListTimestamp
-1748177688
+1748264017
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index e91b8bc9..b5ec592 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2025-05-25 12:54 UTC
+// Last updated: 2025-05-26 12:53 UTC
 //
 {
   "pinsets": [
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index b04abba..9310c544 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -7776,21 +7776,6 @@
             ]
         }
     ],
-    "DeviceIdValidation": [
-        {
-            "platforms": [
-                "chromeos"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "DeviceIdValidation"
-                    ]
-                }
-            ]
-        }
-    ],
     "DexFixer": [
         {
             "platforms": [
@@ -11660,21 +11645,6 @@
             ]
         }
     ],
-    "IOSDeleteAllSavedCredentials": [
-        {
-            "platforms": [
-                "ios"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "IOSEnableDeleteAllSavedCredentials"
-                    ]
-                }
-            ]
-        }
-    ],
     "IOSDeprecateFeedHeader": [
         {
             "platforms": [
@@ -16887,14 +16857,14 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_Uniform_20250520",
+                    "name": "Enabled_Uniform_20250526",
                     "params": {
                         "en_site_id": "N5wFxEDQr0ugnJ3q1cK0SNopqcEc",
                         "hats_histogram_name": "Feedback.HappinessTrackingSurvey.PerformanceControlsPPMSurvey",
                         "hats_survey_ukm_id": "1027171324",
                         "ppm_survey_segment_name1": "ChromeOS",
                         "ppm_survey_uniform_sample": "true",
-                        "probability": "0.108",
+                        "probability": "1.0",
                         "survey": "performance-ppm"
                     },
                     "enable_features": [
@@ -16909,7 +16879,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_Uniform_20250520",
+                    "name": "Enabled_Uniform_20250526",
                     "params": {
                         "en_site_id": "N5wFxEDQr0ugnJ3q1cK0SNopqcEc",
                         "hats_histogram_name": "Feedback.HappinessTrackingSurvey.PerformanceControlsPPMSurvey",
@@ -16931,7 +16901,7 @@
             ],
             "experiments": [
                 {
-                    "name": "Enabled_Uniform_20250520",
+                    "name": "Enabled_Uniform_20250526",
                     "params": {
                         "en_site_id": "N5wFxEDQr0ugnJ3q1cK0SNopqcEc",
                         "hats_histogram_name": "Feedback.HappinessTrackingSurvey.PerformanceControlsPPMSurvey",
@@ -16948,32 +16918,6 @@
                     ]
                 }
             ]
-        },
-        {
-            "platforms": [
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled_Uniform_20250520",
-                    "params": {
-                        "en_site_id": "N5wFxEDQr0ugnJ3q1cK0SNopqcEc",
-                        "hats_histogram_name": "Feedback.HappinessTrackingSurvey.PerformanceControlsPPMSurvey",
-                        "hats_survey_ukm_id": "1027171324",
-                        "ppm_survey_segment_max_memory_gb1": "4",
-                        "ppm_survey_segment_max_memory_gb2": "8",
-                        "ppm_survey_segment_name1": "Windows, up to 4 GB",
-                        "ppm_survey_segment_name2": "",
-                        "ppm_survey_segment_name3": "",
-                        "ppm_survey_uniform_sample": "true",
-                        "probability": "0.088",
-                        "survey": "performance-ppm"
-                    },
-                    "enable_features": [
-                        "PerformanceControlsPPMSurvey"
-                    ]
-                }
-            ]
         }
     ],
     "PerformanceInterventionAlgorithm": [
diff --git a/third_party/angle b/third_party/angle
index a38ac25..2a18fdb 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit a38ac25bd93c1fdaf393e2513f9c254b493e18bb
+Subproject commit 2a18fdbf4c8c20e37734611064d21a83658f6236
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc
index cf912d0..d79907cf 100644
--- a/third_party/blink/common/features.cc
+++ b/third_party/blink/common/features.cc
@@ -1933,6 +1933,10 @@
                    "memory_cache_strong_ref_resource_size_threshold",
                    3 * 1024 * 1024);
 
+BASE_FEATURE(kMemoryPurgeOnFreezeLimit,
+             "MemoryPurgeOnFreezeLimit",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kMemorySaverModeRenderTuning,
              "MemorySaverModeRenderTuning",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/blink_resources.grd b/third_party/blink/public/blink_resources.grd
index 38d5b1b..3ae770d 100644
--- a/third_party/blink/public/blink_resources.grd
+++ b/third_party/blink/public/blink_resources.grd
@@ -56,6 +56,11 @@
       </if>
       <include name="IDR_AUDIO_SPATIALIZATION_COMPOSITE" file="../renderer/platform/audio/resources/Composite.flac" type="BINDATA"/>
       <include name="IDR_UASTYLE_JSON_DOCUMENT_CSS" file="../renderer/core/css/json-document.css" type="BINDATA" compress="brotli"/>
+      <include name="IDR_PERMISSION_ICON_CAMERA_SVG" file="../renderer/core/html/resources/images/permission_icon_camera.svg" type="BINDATA" compress="brotli"/>
+      <include name="IDR_PERMISSION_ICON_MICROPHONE_SVG" file="../renderer/core/html/resources/images/permission_icon_microphone.svg" type="BINDATA" compress="brotli"/>
+      <include name="IDR_PERMISSION_ICON_LOCATION_SVG" file="../renderer/core/html/resources/images/permission_icon_location.svg" type="BINDATA" compress="brotli"/>
+      <include name="IDR_PERMISSION_ICON_LOCATION_PRECISE_SVG" file="../renderer/core/html/resources/images/permission_icon_location_precise.svg" type="BINDATA" compress="brotli"/>
+
     </includes>
   </release>
 </grit>
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h
index 97923fb..b65eb508 100644
--- a/third_party/blink/public/common/features.h
+++ b/third_party/blink/public/common/features.h
@@ -1298,6 +1298,12 @@
     int,
     kMemoryCacheStrongReferenceResourceSizeThresholdParam);
 
+// Limits the number of memory purge performed on page freezing to 1 per
+// interval in which the renderer is backgrounded. Without this, memory purge is
+// performed every time all pages in a renderer become frozen, which can happen
+// periodically with periodic unfreezing.
+BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kMemoryPurgeOnFreezeLimit);
+
 // Enables v8 memory saver mode on low memory thresholds.
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kMemorySaverModeRenderTuning);
 BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE_PARAM(
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
index acc83701..f5bc1b95 100644
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -3012,6 +3012,7 @@
       file-selector-button
       details-content
       picker
+      permission-icon
 
   # Shadow root type.
   type ShadowRootType extends string
diff --git a/third_party/blink/public/mojom/webid/federated_auth_request.mojom b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
index 093c5ab..b192ce2 100644
--- a/third_party/blink/public/mojom/webid/federated_auth_request.mojom
+++ b/third_party/blink/public/mojom/webid/federated_auth_request.mojom
@@ -4,10 +4,10 @@
 
 module blink.mojom;
 
-import "third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom";
-import "url/mojom/url.mojom";
-import "url/mojom/origin.mojom";
 import "mojo/public/mojom/base/time.mojom";
+import "third_party/blink/public/mojom/credentialmanagement/credential_manager.mojom";
+import "url/mojom/origin.mojom";
+import "url/mojom/url.mojom";
 
 // Implementation of the proposed FedCM API.
 //
@@ -39,26 +39,26 @@
 enum DisconnectStatus {
   kSuccess,
   kErrorTooManyRequests,
-  kError
+  kError,
 };
 
 enum IdpSigninStatus {
   kSignedIn,
-  kSignedOut
+  kSignedOut,
 };
 
 enum RpContext {
   kSignIn,
   kSignUp,
   kUse,
-  kContinue
+  kContinue,
 };
 
 // Don't change the meaning or the order of these values because they are
 // being recorded in metrics and in sync with the counterpart in enums.xml.
 enum RpMode {
   kActive,
-  kPassive
+  kPassive,
 };
 
 // The result of a call to IdentityProvider.register().
@@ -67,7 +67,8 @@
   kErrorFeatureDisabled,
   kErrorCrossOriginConfig,
   kErrorNoTransientActivation,
-  kErrorDeclined
+  kErrorDeclined,
+  kErrorInvalidConfig,
 };
 
 // The details of a federated identity provider.
@@ -136,7 +137,8 @@
   string account_hint;
 };
 
-// The list of user information that can be returned to an identity provider during a UserInfo API call.
+// The list of user information that can be returned to an identity provider
+// during a UserInfo API call.
 struct IdentityUserInfo {
   string email;
   string given_name;
@@ -196,17 +198,17 @@
   // - The error which occurred during the retrieval of a token.
   // - Whether the account was automatically selected.
   RequestToken(array<IdentityProviderGetParameters> idp_get_params,
-      CredentialMediationRequirement requirement) =>
-      (RequestTokenStatus status,
-      url.mojom.Url? selected_identity_provider_config_url,
-      string? token,
-      TokenError? error,
-      bool is_auto_selected);
+               CredentialMediationRequirement requirement)
+      => (RequestTokenStatus status,
+          url.mojom.Url? selected_identity_provider_config_url,
+          string? token,
+          TokenError? error,
+          bool is_auto_selected);
 
   // Requests user info to be generated, given an IDP config.
   // Returns an IdentityUserInfo for each of the user's accounts.
-  RequestUserInfo(IdentityProviderConfig provider) =>
-      (RequestUserInfoStatus status, array<IdentityUserInfo>? user_info);
+  RequestUserInfo(IdentityProviderConfig provider)
+      => (RequestUserInfoStatus status, array<IdentityUserInfo>? user_info);
 
   // Cancels the pending token request, if any.
   CancelTokenRequest();
@@ -220,7 +222,8 @@
 
   // Marks the user as logged in/out to the IDP on this origin. 'origin' must
   // not be opaque.
-  SetIdpSigninStatus(url.mojom.Origin origin, IdpSigninStatus status,
+  SetIdpSigninStatus(url.mojom.Origin origin,
+                     IdpSigninStatus status,
                      LoginStatusOptions? options);
 
   // Registers the url as an IdP's configURL of the user's preference.
@@ -233,7 +236,8 @@
   CloseModalDialogView();
 
   // Require user mediation with navigator.credentials.preventSilentAccess() as
-  // defined in https://w3c.github.io/webappsec-credential-management/#user-mediation
+  // defined in
+  // https://w3c.github.io/webappsec-credential-management/#user-mediation
   // TODO(https://crbug.com/1441075): There's `PreventSilentAccess` in
   // credential_manager.mojom but that's specific to PasswordManager and it's
   // hard to reuse it as-is. We should unify the implementation for different
@@ -242,6 +246,6 @@
 
   // Disconnects the sharing permission for the specified |account_id| from
   // |provider| for the RP identified by |client_id|.
-  Disconnect(IdentityCredentialDisconnectOptions options) =>
-      (DisconnectStatus status);
+  Disconnect(IdentityCredentialDisconnectOptions options)
+      => (DisconnectStatus status);
 };
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 5e89373f..3e985636 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -3314,8 +3314,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_filesystemhandle_wellknowndirectory.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpuautolayoutmode_gpupipelinelayout.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpuautolayoutmode_gpupipelinelayout.h",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.cc",
-  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubuffer_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpubuffer_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_offscreen_rendering_context.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_offscreen_rendering_context.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_union_gpuextent3ddict_unsignedlongenforcerangesequence.cc",
diff --git a/third_party/blink/renderer/core/css/css_selector.cc b/third_party/blink/renderer/core/css/css_selector.cc
index 9990bda..1851536 100644
--- a/third_party/blink/renderer/core/css/css_selector.cc
+++ b/third_party/blink/renderer/core/css/css_selector.cc
@@ -379,6 +379,8 @@
       return kPseudoIdFileSelectorButton;
     case kPseudoDetailsContent:
       return kPseudoIdDetailsContent;
+    case kPseudoPermissionIcon:
+      return kPseudoIdPermissionIcon;
     case kPseudoPicker:
       // NOTE: When we support more than one argument to ::picker() we will
       // need to refactor something here (possibly the callers of this method)
@@ -643,6 +645,7 @@
     {"out-of-range", CSSSelector::kPseudoOutOfRange},
     {"past", CSSSelector::kPseudoPastCue},
     {"paused", CSSSelector::kPseudoPaused},
+    {"permission-icon", CSSSelector::kPseudoPermissionIcon},
     {"picker-icon", CSSSelector::kPseudoPickerIcon},
     {"picture-in-picture", CSSSelector::kPseudoPictureInPicture},
     {"placeholder", CSSSelector::kPseudoPlaceholder},
@@ -927,6 +930,11 @@
         bits_.set<PseudoTypeField>(kPseudoUnknown);
       }
       break;
+    case kPseudoPermissionIcon:
+      if (Match() != kPseudoElement) {
+        bits_.set<PseudoTypeField>(kPseudoUnknown);
+      }
+      break;
     case kPseudoBlinkInternalElement:
       if (Match() != kPseudoElement || mode != kUASheetMode) {
         bits_.set<PseudoTypeField>(kPseudoUnknown);
@@ -1635,7 +1643,8 @@
 
 /* static */ bool CSSSelector::IsElementBackedPseudoElement(
     CSSSelector::PseudoType pseudo) {
-  return pseudo == kPseudoDetailsContent || pseudo == kPseudoPicker;
+  return pseudo == kPseudoDetailsContent || pseudo == kPseudoPicker ||
+         pseudo == kPseudoPermissionIcon;
 }
 
 bool CSSSelector::IsElementBackedPseudoElement() const {
@@ -1685,6 +1694,7 @@
     case kPseudoWebKitCustomElement:
     case kPseudoBlinkInternalElement:
     case kPseudoDetailsContent:
+    case kPseudoPermissionIcon:
     case kPseudoViewTransition:
     case kPseudoViewTransitionGroup:
     case kPseudoViewTransitionImagePair:
diff --git a/third_party/blink/renderer/core/css/css_selector.h b/third_party/blink/renderer/core/css/css_selector.h
index 0e6a24fb..df6655b 100644
--- a/third_party/blink/renderer/core/css/css_selector.h
+++ b/third_party/blink/renderer/core/css/css_selector.h
@@ -289,6 +289,7 @@
     kPseudoPermissionElementInvalidStyle,
     kPseudoPermissionElementOccluded,
     kPseudoPermissionGranted,
+    kPseudoPermissionIcon,
     kPseudoPlaceholder,
     kPseudoPlaceholderShown,
     kPseudoReadOnly,
diff --git a/third_party/blink/renderer/core/css/css_syntax_definition.cc b/third_party/blink/renderer/core/css/css_syntax_definition.cc
index 8ce5455..6ea37f21 100644
--- a/third_party/blink/renderer/core/css/css_syntax_definition.cc
+++ b/third_party/blink/renderer/core/css/css_syntax_definition.cc
@@ -362,4 +362,13 @@
   return builder.ToString();
 }
 
+CSSSyntaxDefinition CSSSyntaxDefinition::CreateNumericSyntax() {
+  CSSParserTokenStream stream(
+      "<number> | <length> | <percentage> | <angle> | <time> | <resolution>");
+  std::optional<CSSSyntaxDefinition> syntax_definition =
+      CSSSyntaxDefinition::Consume(stream);
+  DCHECK(syntax_definition.has_value());
+  return *syntax_definition;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/css_syntax_definition.h b/third_party/blink/renderer/core/css/css_syntax_definition.h
index d7f23dfd..2d11faf 100644
--- a/third_party/blink/renderer/core/css/css_syntax_definition.h
+++ b/third_party/blink/renderer/core/css/css_syntax_definition.h
@@ -57,6 +57,12 @@
   // https://drafts.css-houdini.org/css-properties-values-api-1/#universal-syntax-descriptor
   static CSSSyntaxDefinition CreateUniversal();
 
+  // Returns syntax: <number> | <length> | <percentage> | <angle> | <time> |
+  // <resolution>.
+  // Used for container style range queries,
+  // https://github.com/w3c/csswg-drafts/issues/8376#issuecomment-2751161553.
+  static CSSSyntaxDefinition CreateNumericSyntax();
+
  private:
   friend class CSSSyntaxStringParser;
   friend class CSSSyntaxStringParserTest;
diff --git a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc
index 95698854c..40fad2e 100644
--- a/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc
+++ b/third_party/blink/renderer/core/css/invalidation/rule_invalidation_data_visitor.cc
@@ -100,6 +100,7 @@
     case CSSSelector::kPseudoNot:
     case CSSSelector::kPseudoPlaceholder:
     case CSSSelector::kPseudoDetailsContent:
+    case CSSSelector::kPseudoPermissionIcon:
     case CSSSelector::kPseudoFileSelectorButton:
     case CSSSelector::kPseudoResizer:
     case CSSSelector::kPseudoRoot:
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.cc b/third_party/blink/renderer/core/css/media_query_evaluator.cc
index 4d29caa1..6487f3c 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.cc
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.cc
@@ -1726,13 +1726,8 @@
     return KleeneValue::kUnknown;
   }
 
-  if (feature.HasStyleRange()) {
-    // TODO(crbug.com/408011559): Add support for container style queries
-    // ranges.
-    return KleeneValue::kFalse;
-  }
-
-  if (CSSVariableParser::IsValidVariableName(feature.Name())) {
+  if (feature.HasStyleRange() ||
+      CSSVariableParser::IsValidVariableName(feature.Name())) {
     return EvalStyleFeature(feature, result_flags);
   }
 
@@ -1819,6 +1814,8 @@
   const MediaQueryExpBounds& bounds = feature.Bounds();
 
   if (bounds.IsRange()) {
+    DCHECK(feature.HasStyleRange());
+    DCHECK(RuntimeEnabledFeatures::CSSContainerStyleQueriesRangeEnabled());
     // TODO(crbug.com/408011559): Add support for container style queries
     // ranges.
     return KleeneValue::kFalse;
@@ -1874,4 +1871,28 @@
   return KleeneValue::kFalse;
 }
 
+KleeneValue MediaQueryEvaluator::EvalIfRange(const CSSValue& reference_value,
+                                             const CSSValue& query_value,
+                                             MediaQueryOperator op,
+                                             bool reverse_op) {
+  const CSSNumericLiteralValue* reference_numeric =
+      DynamicTo<CSSNumericLiteralValue>(reference_value);
+  const CSSNumericLiteralValue* query_numeric =
+      DynamicTo<CSSNumericLiteralValue>(query_value);
+
+  if (!reference_numeric || !query_numeric ||
+      reference_numeric->GetType() != query_numeric->GetType()) {
+    return KleeneValue::kFalse;
+  }
+
+  if (reverse_op) {
+    op = ReverseOperator(op);
+  }
+
+  return CompareDoubleValue(reference_numeric->DoubleValue(),
+                            query_numeric->DoubleValue(), op)
+             ? KleeneValue::kTrue
+             : KleeneValue::kFalse;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/css/media_query_evaluator.h b/third_party/blink/renderer/core/css/media_query_evaluator.h
index 4845479..28d09f3 100644
--- a/third_party/blink/renderer/core/css/media_query_evaluator.h
+++ b/third_party/blink/renderer/core/css/media_query_evaluator.h
@@ -38,10 +38,12 @@
 
 namespace blink {
 
+class CSSValue;
 class LocalFrame;
 class MediaQuery;
 class MediaQueryExpNode;
 class MediaQueryFeatureExpNode;
+enum class MediaQueryOperator;
 class MediaQuerySet;
 class MediaQuerySetResult;
 class MediaValues;
@@ -97,6 +99,11 @@
   KleeneValue Eval(const MediaQueryExpNode&) const;
   KleeneValue Eval(const MediaQueryExpNode&, MediaQueryResultFlags*) const;
 
+  static KleeneValue EvalIfRange(const CSSValue& reference_value,
+                                 const CSSValue& query_value,
+                                 MediaQueryOperator op,
+                                 bool reverse_op);
+
   // Returns true if any of the media queries in the results lists changed its
   // evaluation.
   bool DidResultsChange(const HeapVector<MediaQuerySetResult>& results) const;
diff --git a/third_party/blink/renderer/core/css/media_query_exp.h b/third_party/blink/renderer/core/css/media_query_exp.h
index b9326c3..db63af8 100644
--- a/third_party/blink/renderer/core/css/media_query_exp.h
+++ b/third_party/blink/renderer/core/css/media_query_exp.h
@@ -410,6 +410,11 @@
     return exp_.MediaFeature();
   }
 
+  const CSSUnparsedDeclarationValue& ReferenceValue() const {
+    DCHECK(HasStyleRange());
+    return exp_.ReferenceValue();
+  }
+
   bool HasMediaFeature() const { return exp_.HasMediaFeature(); }
   bool HasStyleRange() const { return exp_.HasStyleRange(); }
 
diff --git a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
index eb02917..99e5729e 100644
--- a/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/css_selector_parser.cc
@@ -69,6 +69,7 @@
     case CSSSelector::PseudoType::kPseudoPlaceholder:
     case CSSSelector::PseudoType::kPseudoFileSelectorButton:
     case CSSSelector::PseudoType::kPseudoPicker:
+    case CSSSelector::PseudoType::kPseudoPermissionIcon:
       return CSSSelector::RelationType::kUAShadow;
     case CSSSelector::PseudoType::kPseudoPart:
       return CSSSelector::RelationType::kShadowPart;
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.cc b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
index 020899e5..8f9e76f4 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.cc
@@ -243,6 +243,18 @@
   return evaluator.EvalAndAdd(query, change, match_result);
 }
 
+bool IsVariableNameOnly(StringView str) {
+  if (!CSSVariableParser::IsValidVariableName(str)) {
+    return false;
+  }
+  CSSParserTokenStream stream(str);
+  if (stream.Peek().GetType() != kIdentToken) {
+    return false;
+  }
+  stream.ConsumeIncludingWhitespace();
+  return stream.AtEnd();
+}
+
 }  // namespace
 
 MatchResult& StyleCascade::MutableMatchResult() {
@@ -2319,6 +2331,88 @@
   return false;
 }
 
+const CSSValue* StyleCascade::CoerceIntoNumericValue(
+    const CSSUnparsedDeclarationValue& unparsed_value,
+    const TreeScope* tree_scope,
+    CascadeResolver& resolver,
+    const CSSParserContext& context,
+    FunctionContext* function_context) {
+  StringView unparsed_value_str(
+      unparsed_value.VariableDataValue()->OriginalText());
+  CSSVariableData* data = nullptr;
+  if (IsVariableNameOnly(unparsed_value_str)) {
+    data = ResolveLikeVar(AtomicString(unparsed_value_str), resolver, context,
+                          function_context);
+  } else {
+    CSSParserTokenStream decl_value_stream(unparsed_value_str);
+    TokenSequence substituted_token_sequence;
+    if (ResolveTokensInto(
+            decl_value_stream, tree_scope, resolver, context, function_context,
+            /* stop_type */ kEOFToken, substituted_token_sequence)) {
+      data = substituted_token_sequence.BuildVariableData();
+    }
+  }
+
+  if (!data) {
+    return nullptr;
+  }
+
+  CSSSyntaxDefinition syntax_definition =
+      CSSSyntaxDefinition::CreateNumericSyntax();
+  const CSSValue* parsed_value = syntax_definition.Parse(
+      data->OriginalText(), context,
+      /* is_animation_tainted= */ data->IsAnimationTainted(),
+      /* is_attr_tainted= */ data->IsAttrTainted());
+
+  if (!parsed_value) {
+    return nullptr;
+  }
+
+  const auto* primitive_value = DynamicTo<CSSPrimitiveValue>(parsed_value);
+
+  if (!primitive_value) {
+    return nullptr;
+  }
+
+  if (!primitive_value->IsCalculated() &&
+      (primitive_value->IsPx() || primitive_value->IsPercentage())) {
+    return parsed_value;
+  }
+
+  if (primitive_value->IsLength() || primitive_value->IsPercentage() ||
+      !primitive_value->IsResolvableBeforeLayout()) {
+    Length length = primitive_value->ConvertToLength(
+        state_.CssToLengthConversionData().Unzoomed());
+    return CSSPrimitiveValue::CreateFromLength(length, 1);
+  }
+
+  if (primitive_value->IsNumber()) {
+    return CSSNumericLiteralValue::Create(
+        primitive_value->ComputeNumber(state_.CssToLengthConversionData()),
+        CSSPrimitiveValue::UnitType::kNumber);
+  }
+
+  if (primitive_value->IsAngle()) {
+    return CSSNumericLiteralValue::Create(
+        primitive_value->ComputeDegrees(state_.CssToLengthConversionData()),
+        CSSPrimitiveValue::UnitType::kDegrees);
+  }
+
+  if (primitive_value->IsTime()) {
+    return CSSNumericLiteralValue::Create(
+        primitive_value->ComputeSeconds(state_.CssToLengthConversionData()),
+        CSSPrimitiveValue::UnitType::kSeconds);
+  }
+
+  if (primitive_value->IsResolution()) {
+    return CSSNumericLiteralValue::Create(
+        primitive_value->ComputeDotsPerPixel(
+            state_.CssToLengthConversionData()),
+        CSSPrimitiveValue::UnitType::kDotsPerPixel);
+  }
+  return nullptr;
+}
+
 KleeneValue StyleCascade::EvalIfStyleFeature(
     const MediaQueryFeatureExpNode& feature,
     const TreeScope* tree_scope,
@@ -2328,10 +2422,41 @@
     bool& is_attr_tainted) {
   const MediaQueryExpBounds& bounds = feature.Bounds();
 
-  if (feature.HasStyleRange() || bounds.IsRange()) {
-    // TODO(crbug.com/408011559): Add support for container style queries
-    // ranges.
-    return KleeneValue::kFalse;
+  if (bounds.IsRange()) {
+    DCHECK(RuntimeEnabledFeatures::CSSContainerStyleQueriesRangeEnabled());
+    DCHECK(feature.HasStyleRange());
+    KleeneValue result = KleeneValue::kTrue;
+    const CSSValue* reference =
+        CoerceIntoNumericValue(feature.ReferenceValue(), tree_scope, resolver,
+                               context, function_context);
+    if (!reference) {
+      return KleeneValue::kFalse;
+    }
+    if (bounds.left.IsValid()) {
+      const auto& left =
+          To<CSSUnparsedDeclarationValue>(bounds.left.value.GetCSSValue());
+      const CSSValue* left_resolved = CoerceIntoNumericValue(
+          left, tree_scope, resolver, context, function_context);
+      if (!left_resolved) {
+        return KleeneValue::kFalse;
+      }
+      result = KleeneAnd(
+          result, MediaQueryEvaluator::EvalIfRange(*reference, *left_resolved,
+                                                   bounds.left.op, true));
+    }
+    if (bounds.right.IsValid()) {
+      const auto& right =
+          To<CSSUnparsedDeclarationValue>(bounds.right.value.GetCSSValue());
+      const CSSValue* right_resolved = CoerceIntoNumericValue(
+          right, tree_scope, resolver, context, function_context);
+      if (!right_resolved) {
+        return KleeneValue::kFalse;
+      }
+      result = KleeneAnd(
+          result, MediaQueryEvaluator::EvalIfRange(*reference, *right_resolved,
+                                                   bounds.right.op, false));
+    }
+    return result;
   }
 
   DCHECK(bounds.right.op == MediaQueryOperator::kNone);
diff --git a/third_party/blink/renderer/core/css/resolver/style_cascade.h b/third_party/blink/renderer/core/css/resolver/style_cascade.h
index fe29719..727b04e 100644
--- a/third_party/blink/renderer/core/css/resolver/style_cascade.h
+++ b/third_party/blink/renderer/core/css/resolver/style_cascade.h
@@ -523,6 +523,11 @@
                                   const CSSParserContext&,
                                   FunctionContext*);
 
+  const CSSValue* CoerceIntoNumericValue(const CSSUnparsedDeclarationValue&,
+                                         const TreeScope*,
+                                         CascadeResolver&,
+                                         const CSSParserContext&,
+                                         FunctionContext*);
   KleeneValue EvalIfTest(const IfCondition& node,
                          const TreeScope* tree_scope,
                          CascadeResolver& resolver,
diff --git a/third_party/blink/renderer/core/css/rule_set.cc b/third_party/blink/renderer/core/css/rule_set.cc
index acb67fb..6cf3e861 100644
--- a/third_party/blink/renderer/core/css/rule_set.cc
+++ b/third_party/blink/renderer/core/css/rule_set.cc
@@ -298,6 +298,7 @@
     case CSSSelector::kPseudoPlaceholder:
     case CSSSelector::kPseudoFileSelectorButton:
     case CSSSelector::kPseudoDetailsContent:
+    case CSSSelector::kPseudoPermissionIcon:
     case CSSSelector::kPseudoPicker:
     case CSSSelector::kPseudoWebKitCustomElement:
     case CSSSelector::kPseudoBlinkInternalElement:
@@ -358,6 +359,7 @@
         case CSSSelector::kPseudoFocusVisible:
         case CSSSelector::kPseudoPlaceholder:
         case CSSSelector::kPseudoDetailsContent:
+        case CSSSelector::kPseudoPermissionIcon:
         case CSSSelector::kPseudoFileSelectorButton:
         case CSSSelector::kPseudoHost:
         case CSSSelector::kPseudoHostContext:
diff --git a/third_party/blink/renderer/core/css/selector_checker.cc b/third_party/blink/renderer/core/css/selector_checker.cc
index ddcd99a..da0e0a7 100644
--- a/third_party/blink/renderer/core/css/selector_checker.cc
+++ b/third_party/blink/renderer/core/css/selector_checker.cc
@@ -2568,6 +2568,9 @@
     case CSSSelector::kPseudoDetailsContent:
       return MatchesUAShadowElement(element,
                                     shadow_element_names::kIdDetailsContent);
+    case CSSSelector::kPseudoPermissionIcon:
+      return MatchesUAShadowElement(element,
+                                    shadow_element_names::kIdPermissionIcon);
     case CSSSelector::kPseudoWebKitCustomElement:
       return MatchesUAShadowElement(element, selector.Value());
     case CSSSelector::kPseudoBlinkInternalElement:
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
index 23a07e44..f7f8c07f 100644
--- a/third_party/blink/renderer/core/dom/element.cc
+++ b/third_party/blink/renderer/core/dom/element.cc
@@ -8420,6 +8420,7 @@
     DCHECK(type == CSSSelector::kPseudoWebKitCustomElement ||
            type == CSSSelector::kPseudoBlinkInternalElement ||
            type == CSSSelector::kPseudoDetailsContent ||
+           type == CSSSelector::kPseudoPermissionIcon ||
            id == shadow_element_names::kPickerSelect)
         << "type: " << type << ", id: " << id;
   }
diff --git a/third_party/blink/renderer/core/html/build.gni b/third_party/blink/renderer/core/html/build.gni
index dc1c04a3..5fc5aa7 100644
--- a/third_party/blink/renderer/core/html/build.gni
+++ b/third_party/blink/renderer/core/html/build.gni
@@ -371,6 +371,8 @@
   "html_param_element.h",
   "html_permission_element.cc",
   "html_permission_element.h",
+  "html_permission_icon_element.cc",
+  "html_permission_icon_element.h",
   "html_permission_element_strings_map.h",
   "html_picture_element.cc",
   "html_picture_element.h",
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
index 5e399256..814e71c 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.cc
@@ -235,9 +235,6 @@
           : !!dispatcher;
 
   if (!provider && use_software_shared_image_provider) {
-    CHECK(format == viz::SharedImageFormat::N32Format() ||
-          format == viz::SinglePlaneFormat::kRGBA_F16);
-
     provider =
         CanvasResourceProvider::CreateSharedImageProviderForSoftwareCompositor(
             Size(), format, alpha_type, color_space, kShouldInitialize,
@@ -333,8 +330,6 @@
           : !!dispatcher;
 
   if (!provider && use_software_shared_image_provider) {
-    CHECK(format == viz::SharedImageFormat::N32Format() ||
-          format == viz::SinglePlaneFormat::kRGBA_F16);
     // In this case, we are using CPU raster and CPU compositing. Create a
     // CanvasResourceProvider that uses a SharedImage backed by a shared-memory
     // buffer that can be written by canvas raster and read by the compositor.
diff --git a/third_party/blink/renderer/core/html/html_permission_element.cc b/third_party/blink/renderer/core/html/html_permission_element.cc
index 6d0efa4e..3e0a29d8 100644
--- a/third_party/blink/renderer/core/html/html_permission_element.cc
+++ b/third_party/blink/renderer/core/html/html_permission_element.cc
@@ -450,6 +450,7 @@
   visitor->Trace(permission_service_);
   visitor->Trace(embedded_permission_control_receiver_);
   visitor->Trace(permission_text_span_);
+  visitor->Trace(permission_internal_icon_);
   visitor->Trace(intersection_observer_);
   visitor->Trace(disable_reason_expire_timer_);
   HTMLElement::Trace(visitor);
@@ -783,6 +784,12 @@
 }
 
 void HTMLPermissionElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
+  if (RuntimeEnabledFeatures::PermissionElementIconEnabled(
+          GetDocument().GetExecutionContext())) {
+    permission_internal_icon_ =
+        MakeGarbageCollected<HTMLPermissionIconElement>(GetDocument());
+    root.AppendChild(permission_internal_icon_);
+  }
   permission_text_span_ = MakeGarbageCollected<HTMLSpanElement>(GetDocument());
   permission_text_span_->SetShadowPseudoId(
       shadow_element_names::kPseudoInternalPermissionTextSpan);
@@ -1398,7 +1405,16 @@
     permission_name = permission_status_map_.begin()->key;
     permission_count = permission_status_map_.size();
   }
-
+  if (RuntimeEnabledFeatures::PermissionElementIconEnabled(
+          GetDocument().GetExecutionContext())) {
+    GetTaskRunner()->PostTask(
+        FROM_HERE,
+        WTF::BindOnce(&HTMLPermissionIconElement::SetIcon,
+                      WrapWeakPersistent(permission_internal_icon_.Get()),
+                      permission_count == 1 ? permission_name
+                                            : PermissionName::VIDEO_CAPTURE,
+                      is_precise_location_));
+  }
   AtomicString language_string = ComputeInheritedLanguage().LowerASCII();
 
   uint16_t untranslated_message_id =
@@ -1727,7 +1743,10 @@
   UserAgentShadowRoot()->AppendChild(
       MakeGarbageCollected<HTMLSlotElement>(GetDocument()));
   UserAgentShadowRoot()->RemoveChild(permission_text_span_);
-
+  if (RuntimeEnabledFeatures::PermissionElementIconEnabled(
+          GetDocument().GetExecutionContext())) {
+    UserAgentShadowRoot()->RemoveChild(permission_internal_icon_);
+  }
   MaybeDispatchValidationChangeEvent();
 }
 
diff --git a/third_party/blink/renderer/core/html/html_permission_element.h b/third_party/blink/renderer/core/html/html_permission_element.h
index 0f64c4f..7341cd1 100644
--- a/third_party/blink/renderer/core/html/html_permission_element.h
+++ b/third_party/blink/renderer/core/html/html_permission_element.h
@@ -18,6 +18,7 @@
 #include "third_party/blink/renderer/core/frame/cached_permission_status.h"
 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
 #include "third_party/blink/renderer/core/html/html_element.h"
+#include "third_party/blink/renderer/core/html/html_permission_icon_element.h"
 #include "third_party/blink/renderer/core/intersection_observer/intersection_observer.h"
 #include "third_party/blink/renderer/core/scroll/scroll_snapshot_client.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_vector.h"
@@ -535,6 +536,7 @@
   HashMap<DisableReason, base::TimeTicks> clicking_disabled_reasons_;
 
   Member<HTMLSpanElement> permission_text_span_;
+  Member<HTMLPermissionIconElement> permission_internal_icon_;
   Member<IntersectionObserver> intersection_observer_;
 
   // Keeps track of the time a request was created.
diff --git a/third_party/blink/renderer/core/html/html_permission_icon_element.cc b/third_party/blink/renderer/core/html/html_permission_icon_element.cc
new file mode 100644
index 0000000..91673d5
--- /dev/null
+++ b/third_party/blink/renderer/core/html/html_permission_icon_element.cc
@@ -0,0 +1,45 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/html/html_permission_icon_element.h"
+
+#include "third_party/blink/public/resources/grit/blink_resources.h"
+#include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
+#include "third_party/blink/renderer/platform/data_resource_helper.h"
+
+namespace blink {
+
+using mojom::blink::PermissionName;
+
+HTMLPermissionIconElement::HTMLPermissionIconElement(Document& document)
+    : HTMLSpanElement(document) {
+  SetIdAttribute(shadow_element_names::kIdPermissionIcon);
+  SetShadowPseudoId(shadow_element_names::kIdPermissionIcon);
+}
+
+void HTMLPermissionIconElement::SetIcon(PermissionName permission_type,
+                                        bool is_precise_location) {
+  if (is_icon_set_) {
+    return;
+  }
+  switch (permission_type) {
+    case PermissionName::GEOLOCATION:
+      setInnerHTML(UncompressResourceAsASCIIString(
+          is_precise_location ? IDR_PERMISSION_ICON_LOCATION_PRECISE_SVG
+                              : IDR_PERMISSION_ICON_LOCATION_SVG));
+      break;
+    case PermissionName::VIDEO_CAPTURE:
+      setInnerHTML(String(
+          UncompressResourceAsASCIIString(IDR_PERMISSION_ICON_CAMERA_SVG)));
+      break;
+    case PermissionName::AUDIO_CAPTURE:
+      setInnerHTML(
+          UncompressResourceAsASCIIString(IDR_PERMISSION_ICON_MICROPHONE_SVG));
+      break;
+    default:
+      return;
+  }
+  is_icon_set_ = true;
+}
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/html/html_permission_icon_element.h b/third_party/blink/renderer/core/html/html_permission_icon_element.h
new file mode 100644
index 0000000..f7f392a
--- /dev/null
+++ b/third_party/blink/renderer/core/html/html_permission_icon_element.h
@@ -0,0 +1,29 @@
+// 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 THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ICON_ELEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ICON_ELEMENT_H_
+
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/renderer/core/html/html_span_element.h"
+
+namespace blink {
+// Internal element for the Permission element. This element holds the icon
+// of the permission element.
+class HTMLPermissionIconElement final : public HTMLSpanElement {
+ public:
+  explicit HTMLPermissionIconElement(Document&);
+
+  void SetIcon(mojom::blink::PermissionName permission_type,
+               bool is_precise_location);
+
+ private:
+  // Guard used to prevent re-setting the icon on the permission element. The
+  // state of the element can change, and the text changes with it, but the icon
+  // is always the same. There is no need to set it again.
+  bool is_icon_set_ = false;
+};
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_HTML_PERMISSION_ICON_ELEMENT_H_
diff --git a/third_party/blink/renderer/core/html/resources/images/permission_icon_camera.svg b/third_party/blink/renderer/core/html/resources/images/permission_icon_camera.svg
new file mode 100644
index 0000000..e0418a7
--- /dev/null
+++ b/third_party/blink/renderer/core/html/resources/images/permission_icon_camera.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 -960 960 960" width="100%">
+  <path d="M160-160q-33 0-56.5-23.5T80-240v-480q0-33 23.5-56.5T160-800h480q33 0 56.5 23.5T720-720v180l160-160v440L720-420v180q0 33-23.5 56.5T640-160H160Zm0-80h480v-480H160v480Zm0 0v-480 480Z"/>
+</svg>
diff --git a/third_party/blink/renderer/core/html/resources/images/permission_icon_location.svg b/third_party/blink/renderer/core/html/resources/images/permission_icon_location.svg
new file mode 100644
index 0000000..a43bb56
--- /dev/null
+++ b/third_party/blink/renderer/core/html/resources/images/permission_icon_location.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 -960 960 960" width="100%">
+  <path d="M480-480q33 0 56.5-23.5T560-560q0-33-23.5-56.5T480-640q-33 0-56.5 23.5T400-560q0 33 23.5 56.5T480-480Zm0 294q122-112 181-203.5T720-552q0-109-69.5-178.5T480-800q-101 0-170.5 69.5T240-552q0 71 59 162.5T480-186Zm0 106Q319-217 239.5-334.5T160-552q0-150 96.5-239T480-880q127 0 223.5 89T800-552q0 100-79.5 217.5T480-80Zm0-480Z"/>
+</svg>
diff --git a/third_party/blink/renderer/core/html/resources/images/permission_icon_location_precise.svg b/third_party/blink/renderer/core/html/resources/images/permission_icon_location_precise.svg
new file mode 100644
index 0000000..15123c9
--- /dev/null
+++ b/third_party/blink/renderer/core/html/resources/images/permission_icon_location_precise.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 -960 960 960" width="100%">
+  <path d="M440-42v-80q-125-14-214.5-103.5T122-440H42v-80h80q14-125 103.5-214.5T440-838v-80h80v80q125 14 214.5 103.5T838-520h80v80h-80q-14 125-103.5 214.5T520-122v80h-80Zm40-158q116 0 198-82t82-198q0-116-82-198t-198-82q-116 0-198 82t-82 198q0 116 82 198t198 82Zm0-120q-66 0-113-47t-47-113q0-66 47-113t113-47q66 0 113 47t47 113q0 66-47 113t-113 47Zm0-80q33 0 56.5-23.5T560-480q0-33-23.5-56.5T480-560q-33 0-56.5 23.5T400-480q0 33 23.5 56.5T480-400Zm0-80Z"/>
+</svg>
diff --git a/third_party/blink/renderer/core/html/resources/images/permission_icon_microphone.svg b/third_party/blink/renderer/core/html/resources/images/permission_icon_microphone.svg
new file mode 100644
index 0000000..1ff62b7f
--- /dev/null
+++ b/third_party/blink/renderer/core/html/resources/images/permission_icon_microphone.svg
@@ -0,0 +1,3 @@
+<svg xmlns="http://www.w3.org/2000/svg" height="100%" viewBox="0 -960 960 960" width="100%">
+  <path d="M480-400q-50 0-85-35t-35-85v-240q0-50 35-85t85-35q50 0 85 35t35 85v240q0 50-35 85t-85 35Zm0-240Zm-40 520v-123q-104-14-172-93t-68-184h80q0 83 58.5 141.5T480-320q83 0 141.5-58.5T680-520h80q0 105-68 184t-172 93v123h-80Zm40-360q17 0 28.5-11.5T520-520v-240q0-17-11.5-28.5T480-800q-17 0-28.5 11.5T440-760v240q0 17 11.5 28.5T480-480Z"/>
+</svg>
diff --git a/third_party/blink/renderer/core/html/resources/permission.css b/third_party/blink/renderer/core/html/resources/permission.css
index 0094d0e..40c9121 100644
--- a/third_party/blink/renderer/core/html/resources/permission.css
+++ b/third_party/blink/renderer/core/html/resources/permission.css
@@ -49,3 +49,11 @@
   word-wrap: normal;
   word-spacing: inherit;
 }
+
+::permission-icon {
+  display: flex;
+  width: 1.3em;
+  height: 1.3em;
+  margin: auto;
+  float: inline-start;
+}
diff --git a/third_party/blink/renderer/core/html/shadow/shadow_element_names.json5 b/third_party/blink/renderer/core/html/shadow/shadow_element_names.json5
index dcd6864..3b14b04 100644
--- a/third_party/blink/renderer/core/html/shadow/shadow_element_names.json5
+++ b/third_party/blink/renderer/core/html/shadow/shadow_element_names.json5
@@ -18,6 +18,10 @@
       Symbol: "kIdDetailsContent",
     },
     {
+      name: "permission-icon",
+      Symbol: "kIdPermissionIcon",
+    },
+    {
       name: "details-summary",
       Symbol: "kIdDetailsSummary",
     },
diff --git a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
index 1870bdb..7032dd6 100644
--- a/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
+++ b/third_party/blink/renderer/core/html/shadow/shadow_element_utils.cc
@@ -57,6 +57,8 @@
       return shadow_element_names::kPseudoFileUploadButton;
     case kPseudoIdDetailsContent:
       return shadow_element_names::kIdDetailsContent;
+    case kPseudoIdPermissionIcon:
+      return shadow_element_names::kIdPermissionIcon;
     case kPseudoIdPickerSelect:
       return shadow_element_names::kPickerSelect;
     default:
diff --git a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
index 5c0f702..3f696f2 100644
--- a/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
+++ b/third_party/blink/renderer/core/inspector/inspector_dom_agent.cc
@@ -270,6 +270,8 @@
       return protocol::DOM::PseudoTypeEnum::FileSelectorButton;
     case kPseudoIdDetailsContent:
       return protocol::DOM::PseudoTypeEnum::DetailsContent;
+    case kPseudoIdPermissionIcon:
+      return protocol::DOM::PseudoTypeEnum::PermissionIcon;
     case kPseudoIdPickerSelect:
       return protocol::DOM::PseudoTypeEnum::Picker;
     case kPseudoIdViewTransition:
@@ -393,6 +395,9 @@
   if (type == protocol::DOM::PseudoTypeEnum::DetailsContent) {
     return kPseudoIdDetailsContent;
   }
+  if (type == protocol::DOM::PseudoTypeEnum::PermissionIcon) {
+    return kPseudoIdPermissionIcon;
+  }
   if (type == protocol::DOM::PseudoTypeEnum::Picker) {
     return kPseudoIdPickerSelect;
   }
diff --git a/third_party/blink/renderer/core/style/computed_style_constants.h b/third_party/blink/renderer/core/style/computed_style_constants.h
index a496633..afabc9b 100644
--- a/third_party/blink/renderer/core/style/computed_style_constants.h
+++ b/third_party/blink/renderer/core/style/computed_style_constants.h
@@ -107,6 +107,7 @@
   kPseudoIdFileSelectorButton,
   kPseudoIdDetailsContent,
   kPseudoIdPickerSelect,
+  kPseudoIdPermissionIcon,
   // Special values follow:
   kAfterLastInternalPseudoId,
   kPseudoIdInvalid,
diff --git a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc
index a1124a53..3b54f1d 100644
--- a/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc
+++ b/third_party/blink/renderer/modules/accessibility/blink_ax_tree_source.cc
@@ -241,18 +241,15 @@
   // The child may be invalid due to issues in blink accessibility code.
   CHECK(child);
   if (child->IsDetached()) {
-    NOTREACHED(base::NotFatalUntil::M127)
-        << "Should not try to serialize an invalid child:" << "\nParent: "
-        << node->ToString().Utf8() << "\nChild: " << child->ToString().Utf8();
-    return nullptr;
+    NOTREACHED() << "Should not try to serialize an invalid child:"
+                 << "\nParent: " << node->ToString().Utf8()
+                 << "\nChild: " << child->ToString().Utf8();
   }
 
   if (!child->IsIncludedInTree()) {
-    NOTREACHED(base::NotFatalUntil::M127)
-        << "Should not receive unincluded child."
-        << "\nChild: " << child->ToString().Utf8()
-        << "\nParent: " << node->ToString().Utf8();
-    return nullptr;
+    NOTREACHED() << "Should not receive unincluded child."
+                 << "\nChild: " << child->ToString().Utf8()
+                 << "\nParent: " << node->ToString().Utf8();
   }
 
   // These should not be produced by Blink. They are only needed on Mac and
diff --git a/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc b/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
index 64409da..34ea6e9 100644
--- a/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
+++ b/third_party/blink/renderer/modules/canvas/offscreencanvas/offscreen_canvas_test.cc
@@ -225,7 +225,7 @@
   const bool context_alpha = GetParam().alpha;
 
   auto canvas_resource = CanvasResourceSharedImage::CreateSoftware(
-      offscreen_canvas().Size(), viz::SinglePlaneFormat::kRGBA_8888,
+      offscreen_canvas().Size(), viz::SinglePlaneFormat::kBGRA_8888,
       kPremul_SkAlphaType, gfx::ColorSpace::CreateSRGB(),
       /*provider=*/nullptr, shared_image_interface_provider());
   EXPECT_TRUE(!!canvas_resource);
@@ -251,7 +251,7 @@
   platform->RunUntilIdle();
 
   auto canvas_resource2 = CanvasResourceSharedImage::CreateSoftware(
-      offscreen_canvas().Size(), viz::SinglePlaneFormat::kRGBA_8888,
+      offscreen_canvas().Size(), viz::SinglePlaneFormat::kBGRA_8888,
       kPremul_SkAlphaType, gfx::ColorSpace::CreateSRGB(),
       /*provider=*/nullptr, shared_image_interface_provider());
   EXPECT_CALL(mock_embedded_frame_sink_provider.mock_compositor_frame_sink(),
diff --git a/third_party/blink/renderer/modules/credentialmanagement/identity_provider.cc b/third_party/blink/renderer/modules/credentialmanagement/identity_provider.cc
index 7b941ca6..fb34a32 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/identity_provider.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/identity_provider.cc
@@ -164,7 +164,13 @@
           "User declined the permission to register the identity provider."));
       return;
     }
-  };
+    case RegisterIdpStatus::kErrorInvalidConfig: {
+      resolver->Reject(MakeGarbageCollected<DOMException>(
+          DOMExceptionCode::kNotAllowedError,
+          "Invalid identity provider registration config."));
+      return;
+    }
+  }
 }
 
 ScriptPromise<IDLBoolean> IdentityProvider::registerIdentityProvider(
diff --git a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_webgpu.idl b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_webgpu.idl
index ac76ded..899056c 100644
--- a/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_webgpu.idl
+++ b/third_party/blink/renderer/modules/webgl/webgl2_rendering_context_webgpu.idl
@@ -8,6 +8,12 @@
     ActiveScriptWrappable,
     Exposed=(Window,Worker),
     RuntimeEnabled=WebGLOnWebGPU
-] interface WebGL2RenderingContextWebGPU { };
+] interface WebGL2RenderingContextWebGPU {
+    // TODO(https://issues.chromium.org/413078308): Asynchronous initialization
+    // is needed because it is not possible to synchronously wait for WebGPU
+    // requestAdapter/Device in the renderer process. Once this capability is
+    // added, the initAsync should be removed.
+    [CallWith=ScriptState] Promise<undefined> initAsync();
+};
 WebGL2RenderingContextWebGPU includes WebGLRenderingContextBase;
 WebGL2RenderingContextWebGPU includes WebGL2RenderingContextBase;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu.idl b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu.idl
index 2f4c23c..88fde368 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu.idl
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu.idl
@@ -12,5 +12,10 @@
 
     [RuntimeEnabled=WebGLDrawingBufferStorage] const GLenum RGB8   = 0x8051;
     [RuntimeEnabled=WebGLDrawingBufferStorage] const GLenum RGBA8  = 0x8058;
+    // TODO(https://issues.chromium.org/413078308): Asynchronous initialization
+    // is needed because it is not possible to synchronously wait for WebGPU
+    // requestAdapter/Device in the renderer process. Once this capability is
+    // added, the initAsync should be removed.
+    [CallWith=ScriptState] Promise<undefined> initAsync();
 };
 WebGLRenderingContextWebGPU includes WebGLRenderingContextBase;
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc
index 8d6c118..a323216 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.cc
@@ -1,10 +1,19 @@
-// Copyright 2025 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
+// 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 "third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.h"
 
 #include "base/notimplemented.h"
+#include "third_party/blink/public/platform/web_url.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context.h"
+#include "third_party/blink/renderer/core/frame/local_dom_window.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_callback.h"
+#include "third_party/blink/renderer/platform/graphics/skia/skia_utils.h"
+#include "third_party/blink/renderer/platform/graphics/web_graphics_context_3d_provider_util.h"
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
 
@@ -19,6 +28,122 @@
 
 WebGLRenderingContextWebGPUBase::~WebGLRenderingContextWebGPUBase() {}
 
+ScriptPromise<IDLUndefined> WebGLRenderingContextWebGPUBase::initAsync(
+    ScriptState* script_state) {
+  auto* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>(script_state);
+  auto promise = resolver->Promise();
+
+  // Synchronously connect to the GPU process to use WebGPU.
+  ExecutionContext* execution_context = ExecutionContext::From(script_state);
+  std::unique_ptr<WebGraphicsContext3DProvider> context_provider =
+      Platform::Current()->CreateWebGPUGraphicsContext3DProvider(
+          execution_context->Url());
+
+  if (context_provider == nullptr) {
+    resolver->RejectWithDOMException(
+        DOMExceptionCode::kOperationError,
+        "Failed to create a WebGPU context provider");
+    return promise;
+  }
+
+  // The context provider requires being bound on a single thread because it was
+  // initially designed only for GL.
+  context_provider->BindToCurrentSequence();
+  // Send the execution token to the GPU process, it won't return devices until
+  // it receives it.
+  context_provider->WebGPUInterface()->SetWebGPUExecutionContextToken(
+      To<LocalDOMWindow>(execution_context)->document()->Token());
+
+  // Create the wgpu::Instance (as part of the DawnControlClientHolder).
+  dawn_control_client_ = DawnControlClientHolder::Create(
+      std::move(context_provider),
+      execution_context->GetTaskRunner(TaskType::kWebGPU));
+
+  // Request the adapter, making it resolve the result promise when it is done.
+  auto* callback =
+      MakeWGPUOnceCallback(resolver->WrapCallbackInScriptScope(WTF::BindOnce(
+          &WebGLRenderingContextWebGPUBase::InitRequestAdapterCallback,
+          WrapPersistent(this), WrapPersistent(script_state))));
+
+  dawn_control_client_->GetWGPUInstance().RequestAdapter(
+      nullptr, wgpu::CallbackMode::AllowSpontaneous,
+      callback->UnboundCallback(), callback->AsUserdata());
+  dawn_control_client_->EnsureFlush(ToEventLoop(script_state));
+
+  return promise;
+}
+
+void WebGLRenderingContextWebGPUBase::InitRequestAdapterCallback(
+    ScriptState* script_state,
+    ScriptPromiseResolver<IDLUndefined>* resolver,
+    wgpu::RequestAdapterStatus status,
+    wgpu::Adapter adapter,
+    wgpu::StringView error_message) {
+  if (status != wgpu::RequestAdapterStatus::Success) {
+    resolver->RejectWithDOMException(
+        DOMExceptionCode::kOperationError,
+        WTF::String::FromUTF8WithLatin1Fallback(error_message));
+    return;
+  }
+
+  adapter_ = std::move(adapter);
+
+  // Request the device.
+  auto* callback = MakeWGPUOnceCallback(
+      WTF::BindOnce(&WebGLRenderingContextWebGPUBase::InitRequestDeviceCallback,
+                    WrapPersistent(this), WrapPersistent(script_state),
+                    WrapPersistent(resolver)));
+
+  adapter_.RequestDevice(nullptr, wgpu::CallbackMode::AllowSpontaneous,
+                         callback->UnboundCallback(), callback->AsUserdata());
+  dawn_control_client_->EnsureFlush(ToEventLoop(script_state));
+}
+
+void WebGLRenderingContextWebGPUBase::InitRequestDeviceCallback(
+    ScriptState* script_state,
+    ScriptPromiseResolver<IDLUndefined>* resolver,
+    wgpu::RequestDeviceStatus status,
+    wgpu::Device device,
+    wgpu::StringView error_message) {
+  if (status != wgpu::RequestDeviceStatus::Success) {
+    resolver->RejectWithDOMException(
+        DOMExceptionCode::kOperationError,
+        WTF::String::FromUTF8WithLatin1Fallback(error_message));
+    return;
+  }
+
+  device_ = std::move(device);
+
+  // TODO(413078308): Fill in with a GLES2Interface that will be used by WebGL
+  // objects.
+  WebGLContextObjectSupport::OnContextRestored(nullptr);
+
+  // Create the underlying WebGPUSwapBufferProvider.
+  constexpr wgpu::TextureUsage kDefaultFBOUsages =
+      wgpu::TextureUsage::RenderAttachment | wgpu::TextureUsage::CopySrc |
+      wgpu::TextureUsage::CopySrc;
+#if BUILDFLAG(IS_ANDROID)
+  constexpr wgpu::TextureFormat kDefaultFBON32Format =
+      wgpu::TextureFormat::RGBA8Unorm;
+#else
+  constexpr wgpu::TextureFormat kDefaultFBON32Format =
+      wgpu::TextureFormat::BGRA8Unorm;
+#endif
+
+  // TODO(413078308): Add support for non-SRGB color spaces and HDR metadata.
+  // TODO(413078308): Add support for RGBA16Float drawing buffer.
+  swap_buffers_ = base::AdoptRef(new WebGPUSwapBufferProvider(
+      this, dawn_control_client_, device_, kDefaultFBOUsages,
+      wgpu::TextureUsage::None, kDefaultFBON32Format,
+      PredefinedColorSpace::kSRGB, gfx::HDRMetadata{}));
+
+  // We are required to present to the compositor on context creation.
+  ShouldPresentToCompositor();
+
+  resolver->Resolve();
+}
+
 // ****************************************************************************
 // Start of WebGLRenderingContextBase's IDL methods
 // ****************************************************************************
@@ -2381,24 +2506,34 @@
 // Start of CanvasRenderingContext implementation
 // ****************************************************************************
 SkAlphaType WebGLRenderingContextWebGPUBase::GetAlphaType() const {
-  NOTIMPLEMENTED();
-  return SkAlphaType::kUnknown_SkAlphaType;
+  // WebGL spec section 2.2 The Drawing Buffer
+  //
+  //   If defined, the alpha channel is used by the HTML compositor to combine
+  //   the color buffer with the rest of the page.
+  return CreationAttributes().alpha ? kPremul_SkAlphaType : kOpaque_SkAlphaType;
 }
 
 viz::SharedImageFormat WebGLRenderingContextWebGPUBase::GetSharedImageFormat()
     const {
-  NOTIMPLEMENTED();
-  return {};
+  // TODO(413078308): Add support for RGBA16Float drawing buffer.
+  if (swap_buffers_) {
+    return swap_buffers_->Format();
+  }
+  return GetN32FormatForCanvas();
 }
 
 gfx::ColorSpace WebGLRenderingContextWebGPUBase::GetColorSpace() const {
-  NOTIMPLEMENTED();
-  return {};
+  // TODO(413078308): Add support for non-SRGB color spaces.
+  return gfx::ColorSpace::CreateSRGB();
+}
+
+int WebGLRenderingContextWebGPUBase::ExternallyAllocatedBufferCountPerPixel() {
+  // TODO(413078308): Add support configuring MSAA and depth-stencil.
+  return 2;
 }
 
 bool WebGLRenderingContextWebGPUBase::isContextLost() const {
-  NOTIMPLEMENTED();
-  return false;
+  return IsLost();
 }
 
 scoped_refptr<StaticBitmapImage> WebGLRenderingContextWebGPUBase::GetImage(
@@ -2413,18 +2548,11 @@
 }
 
 bool WebGLRenderingContextWebGPUBase::IsComposited() const {
-  NOTIMPLEMENTED();
-  return false;
+  return true;
 }
 
 bool WebGLRenderingContextWebGPUBase::IsPaintable() const {
-  NOTIMPLEMENTED();
-  return false;
-}
-
-bool WebGLRenderingContextWebGPUBase::UsingSwapChain() const {
-  NOTIMPLEMENTED();
-  return false;
+  return true;
 }
 
 void WebGLRenderingContextWebGPUBase::PageVisibilityChanged() {
@@ -2448,10 +2576,16 @@
 }
 
 cc::Layer* WebGLRenderingContextWebGPUBase::CcLayer() const {
-  NOTIMPLEMENTED();
+  if (swap_buffers_) {
+    return swap_buffers_->CcLayer();
+  }
   return nullptr;
 }
 
+void WebGLRenderingContextWebGPUBase::Reshape(int width, int height) {
+  NOTIMPLEMENTED();
+}
+
 void WebGLRenderingContextWebGPUBase::Stop() {
   NOTIMPLEMENTED();
 }
@@ -2469,8 +2603,47 @@
 // End of CanvasRenderingContext implementation
 // ****************************************************************************
 
+void WebGLRenderingContextWebGPUBase::OnTextureTransferred() {
+  current_swap_buffer_ = nullptr;
+}
+
+void WebGLRenderingContextWebGPUBase::InitializeLayer(cc::Layer* layer) {
+  if (Host()) {
+    Host()->InitializeLayerWithCSSProperties(layer);
+  }
+}
+
+void WebGLRenderingContextWebGPUBase::SetNeedsCompositingUpdate() {
+  if (Host()) {
+    Host()->SetNeedsCompositingUpdate();
+  }
+}
+
+bool WebGLRenderingContextWebGPUBase::IsGPUDeviceDestroyed() {
+  return IsLost();
+}
+
 void WebGLRenderingContextWebGPUBase::Trace(Visitor* visitor) const {
   WebGLContextObjectSupport::Trace(visitor);
   CanvasRenderingContext::Trace(visitor);
 }
+
+void WebGLRenderingContextWebGPUBase::ShouldPresentToCompositor() {
+  if (current_swap_buffer_) {
+    return;
+  }
+  wgpu::TextureDescriptor texDesc;
+  texDesc.size.width = std::max(1, Host()->Size().width());
+  texDesc.size.height = std::max(1, Host()->Size().height());
+  texDesc.usage = swap_buffers_->TextureUsage();
+  texDesc.format = swap_buffers_->TextureFormat();
+  texDesc.dimension = wgpu::TextureDimension::e2D;
+
+  scoped_refptr<WebGPUMailboxTexture> mailbox_texture =
+      swap_buffers_->GetNewTexture(texDesc, GetAlphaType());
+  mailbox_texture->SetNeedsPresent(true);
+
+  current_swap_buffer_ = mailbox_texture->GetTexture();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.h b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.h
index 42470446..e20a746 100644
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.h
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_webgpu_base.h
@@ -12,6 +12,7 @@
 #include "third_party/blink/renderer/core/html/canvas/canvas_rendering_context.h"
 #include "third_party/blink/renderer/modules/webgl/webgl_context_object_support.h"
 #include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
+#include "third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
 namespace blink {
@@ -42,7 +43,8 @@
 
 class MODULES_EXPORT WebGLRenderingContextWebGPUBase
     : public WebGLContextObjectSupport,
-      public CanvasRenderingContext {
+      public CanvasRenderingContext,
+      public WebGPUSwapBufferProvider::Client {
  public:
   WebGLRenderingContextWebGPUBase(
       CanvasRenderingContextHost* host,
@@ -55,6 +57,10 @@
   WebGLRenderingContextWebGPUBase& operator=(
       const WebGLRenderingContextWebGPUBase&) = delete;
 
+  // Extra Web-exposed initAsync while until Dawn operations can be made
+  // blocking in the renderer process.
+  ScriptPromise<IDLUndefined> initAsync(ScriptState* script_state);
+
   // **************************************************************************
   // Start of WebGLRenderingContextBase's IDL methods
   // **************************************************************************
@@ -1251,13 +1257,13 @@
   SkAlphaType GetAlphaType() const override;
   viz::SharedImageFormat GetSharedImageFormat() const override;
   gfx::ColorSpace GetColorSpace() const override;
+  int ExternallyAllocatedBufferCountPerPixel() override;
   bool isContextLost() const override;
   scoped_refptr<StaticBitmapImage> GetImage(FlushReason) override;
   void SetHdrMetadata(const gfx::HDRMetadata& hdr_metadata) override;
 
   bool IsComposited() const override;
   bool IsPaintable() const override;
-  bool UsingSwapChain() const override;
   void PageVisibilityChanged() override;
   CanvasResourceProvider* PaintRenderingResultsToCanvas(
       SourceDrawingBuffer) override;
@@ -1268,6 +1274,7 @@
       VideoFrameCopyCompletedCallback) override;
 
   cc::Layer* CcLayer() const override;
+  void Reshape(int width, int height) override;
   void Stop() override;
   void FinalizeFrame(FlushReason) override;
   bool PushFrame() override;
@@ -1276,9 +1283,37 @@
   // End of CanvasRenderingContext implementation
   // **************************************************************************
 
+  // WebGPUSwapBufferProvider::Client implementation
+  void OnTextureTransferred() override;
+  void InitializeLayer(cc::Layer* layer) override;
+  void SetNeedsCompositingUpdate() override;
+  bool IsGPUDeviceDestroyed() override;
+
   void Trace(Visitor*) const override;
 
  private:
+  void InitRequestAdapterCallback(ScriptState* script_state,
+                                  ScriptPromiseResolver<IDLUndefined>* resolver,
+                                  wgpu::RequestAdapterStatus status,
+                                  wgpu::Adapter adapter,
+                                  wgpu::StringView error_message);
+  void InitRequestDeviceCallback(ScriptState* script_state,
+                                 ScriptPromiseResolver<IDLUndefined>* resolver,
+                                 wgpu::RequestDeviceStatus status,
+                                 wgpu::Device device,
+                                 wgpu::StringView error_message);
+
+  // Must be called when an operation happens that should cause the drawing
+  // buffer to be present to the compositor. See WebGL spec Section 2.2 The
+  // Drawing Buffer.
+  void ShouldPresentToCompositor();
+
+  scoped_refptr<DawnControlClientHolder> dawn_control_client_;
+  wgpu::Adapter adapter_;
+  wgpu::Device device_;
+
+  scoped_refptr<WebGPUSwapBufferProvider> swap_buffers_;
+  wgpu::Texture current_swap_buffer_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc b/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
index 8117f15..6e2ebb0 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group.cc
@@ -7,7 +7,7 @@
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_descriptor.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_bind_group_entry.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_gpu_buffer_binding.h"
-#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_union_gpubuffer_gpubufferbinding_gpuexternaltexture_gpusampler_gputextureview.h"
 #include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h"
 #include "third_party/blink/renderer/modules/webgpu/gpu_bind_group_layout.h"
 #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h"
@@ -28,6 +28,11 @@
   };
 
   switch (webgpu_binding->resource()->GetContentType()) {
+    case V8GPUBindingResource::ContentType::kGPUBuffer: {
+      GPUBuffer* buffer = webgpu_binding->resource()->GetAsGPUBuffer();
+      dawn_binding.buffer = AsDawnType(buffer);
+      break;
+    }
     case V8GPUBindingResource::ContentType::kGPUBufferBinding: {
       GPUBufferBinding* buffer =
           webgpu_binding->resource()->GetAsGPUBufferBinding();
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
index 75392081..41754ea 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
+++ b/third_party/blink/renderer/modules/webgpu/gpu_bind_group_entry.idl
@@ -4,7 +4,7 @@
 
 // https://gpuweb.github.io/gpuweb/
 
-typedef (GPUSampler or GPUTextureView or GPUBufferBinding or GPUExternalTexture) GPUBindingResource;
+typedef (GPUSampler or GPUTextureView or GPUBuffer or GPUBufferBinding or GPUExternalTexture) GPUBindingResource;
 
 dictionary GPUBindGroupEntry {
     required GPUIndex32 binding;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
index 95d1929..081f55c 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -318,15 +318,14 @@
   DCHECK(release_callback);
 
   auto format = client_si->format();
+  auto size = client_si->size();
 
   return MakeGarbageCollected<ImageBitmap>(
       AcceleratedStaticBitmapImage::CreateFromCanvasSharedImage(
           std::move(client_si), sk_image_sync_token,
-          /* shared_image_texture_id = */ 0,
-          gfx::Size(texture_descriptor_.size.width,
-                    texture_descriptor_.size.height),
-          format, kPremul_SkAlphaType, gfx::ColorSpace::CreateSRGB(),
-          GetContextProviderWeakPtr(), base::PlatformThread::CurrentRef(),
+          /* shared_image_texture_id = */ 0, size, format, kPremul_SkAlphaType,
+          gfx::ColorSpace::CreateSRGB(), GetContextProviderWeakPtr(),
+          base::PlatformThread::CurrentRef(),
           ThreadScheduler::Current()->CleanupTaskRunner(),
           std::move(release_callback)));
 }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
index af900ba..3334442 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -79,7 +79,6 @@
   bool isContextLost() const override { return false; }
   bool IsComposited() const final { return true; }
   bool IsPaintable() const final { return true; }
-  int ExternallyAllocatedBufferCountPerPixel() final { return 1; }
   void Stop() final;
   cc::Layer* CcLayer() const final;
   void Reshape(int width, int height) override;
diff --git a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
index 3bd0098c..4b9776c 100644
--- a/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
+++ b/third_party/blink/renderer/modules/xr/xr_rigid_transform.cc
@@ -7,7 +7,6 @@
 #include <cmath>
 #include <utility>
 
-#include "base/not_fatal_until.h"
 #include "third_party/blink/renderer/bindings/core/v8/v8_dom_point_init.h"
 #include "third_party/blink/renderer/core/geometry/dom_point_read_only.h"
 #include "third_party/blink/renderer/modules/xr/xr_utils.h"
@@ -35,8 +34,7 @@
 void XRRigidTransform::DecomposeMatrix() {
   // decompose matrix to position and orientation
   std::optional<gfx::DecomposedTransform> decomp = matrix_->Decompose();
-  CHECK(decomp, base::NotFatalUntil::M129)
-      << "Matrix decompose failed for " << matrix_->ToString();
+  CHECK(decomp) << "Matrix decompose failed for " << matrix_->ToString();
 
   position_ = DOMPointReadOnly::Create(
       decomp->translate[0], decomp->translate[1], decomp->translate[2], 1.0);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.cc b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
index 08137b3..ba73b75 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.cc
@@ -58,16 +58,12 @@
 namespace blink {
 
 CanvasResource::CanvasResource(base::WeakPtr<CanvasResourceProvider> provider,
-                               gfx::Size size,
-                               viz::SharedImageFormat format,
                                SkAlphaType alpha_type,
                                const gfx::ColorSpace& color_space)
     : owning_thread_ref_(base::PlatformThread::CurrentRef()),
       owning_thread_task_runner_(
           ThreadScheduler::Current()->CleanupTaskRunner()),
       provider_(std::move(provider)),
-      size_(size),
-      format_(format),
       alpha_type_(alpha_type),
       color_space_(color_space) {}
 
@@ -202,8 +198,10 @@
 }
 
 SkImageInfo CanvasResource::CreateSkImageInfo() const {
-  return SkImageInfo::Make(SkISize::Make(size_.width(), size_.height()),
-                           viz::ToClosestSkColorType(format_), alpha_type_,
+  auto size = GetClientSharedImage()->size();
+  auto format = GetClientSharedImage()->format();
+  return SkImageInfo::Make(SkISize::Make(size.width(), size.height()),
+                           viz::ToClosestSkColorType(format), alpha_type_,
                            color_space_.ToSkColorSpace());
 }
 
@@ -219,8 +217,6 @@
     base::WeakPtr<WebGraphicsSharedImageInterfaceProvider>
         shared_image_interface_provider)
     : CanvasResource(std::move(provider),
-                     size,
-                     format,
                      alpha_type,
                      color_space),
       is_accelerated_(false),
@@ -236,8 +232,7 @@
 
   owning_thread_data().client_shared_image =
       shared_image_interface->CreateSharedImageForSoftwareCompositor(
-          {viz::SinglePlaneFormat::kBGRA_8888, size, color_space,
-           gpu::SHARED_IMAGE_USAGE_CPU_WRITE_ONLY,
+          {format, size, color_space, gpu::SHARED_IMAGE_USAGE_CPU_WRITE_ONLY,
            "CanvasResourceSharedImage"});
 
   // This class doesn't currently have a way of verifying the sync token for
@@ -274,8 +269,6 @@
     bool is_accelerated,
     gpu::SharedImageUsageSet shared_image_usage_flags)
     : CanvasResource(std::move(provider),
-                     size,
-                     format,
                      alpha_type,
                      color_space),
       context_provider_wrapper_(std::move(context_provider_wrapper)),
@@ -576,25 +569,20 @@
       has_read_ref_on_texture);
 
   scoped_refptr<StaticBitmapImage> image;
-  auto client_shared_image = GetClientSharedImage();
+  const auto& client_shared_image = GetClientSharedImage();
 
   // If its cross thread, then the sync token was already verified.
   image = AcceleratedStaticBitmapImage::CreateFromCanvasSharedImage(
-      std::move(client_shared_image), GetSyncToken(), texture_id_for_image,
-      Size(), GetFormat(), GetAlphaType(), GetColorSpace(),
-      context_provider_wrapper_, owning_thread_ref_, owning_thread_task_runner_,
+      client_shared_image, GetSyncToken(), texture_id_for_image,
+      client_shared_image->size(), client_shared_image->format(),
+      GetAlphaType(), GetColorSpace(), context_provider_wrapper_,
+      owning_thread_ref_, owning_thread_task_runner_,
       std::move(release_callback));
 
   DCHECK(image);
   return image;
 }
 
-scoped_refptr<gpu::ClientSharedImage>
-CanvasResourceSharedImage::GetClientSharedImage() {
-  CHECK(owning_thread_data_.client_shared_image);
-  return owning_thread_data_.client_shared_image;
-}
-
 const scoped_refptr<gpu::ClientSharedImage>&
 CanvasResourceSharedImage::GetClientSharedImage() const {
   CHECK(owning_thread_data_.client_shared_image);
@@ -789,9 +777,9 @@
       base::RetainedRef(this));
 
   return AcceleratedStaticBitmapImage::CreateFromCanvasSharedImage(
-      client_si_, GetSyncToken(), /*shared_image_texture_id=*/0u, Size(),
-      GetFormat(), GetAlphaType(), GetColorSpace(), context_provider_wrapper_,
-      owning_thread_ref_, owning_thread_task_runner_,
+      client_si_, GetSyncToken(), /*shared_image_texture_id=*/0u,
+      client_si_->size(), client_si_->format(), GetAlphaType(), GetColorSpace(),
+      context_provider_wrapper_, owning_thread_ref_, owning_thread_task_runner_,
       std::move(release_callback));
 }
 
@@ -835,8 +823,6 @@
     base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
     base::WeakPtr<CanvasResourceProvider> provider)
     : CanvasResource(std::move(provider),
-                     client_si->size(),
-                     client_si->format(),
                      kPremul_SkAlphaType,
                      client_si->color_space()),
       client_si_(std::move(client_si)),
@@ -922,14 +908,15 @@
       base::RetainedRef(this));
 
   return AcceleratedStaticBitmapImage::CreateFromCanvasSharedImage(
-      back_buffer_shared_image_, GetSyncToken(), shared_texture_id, Size(),
-      GetFormat(), GetAlphaType(), GetColorSpace(), context_provider_wrapper_,
+      back_buffer_shared_image_, GetSyncToken(), shared_texture_id,
+      back_buffer_shared_image_->size(), back_buffer_shared_image_->format(),
+      GetAlphaType(), GetColorSpace(), context_provider_wrapper_,
       owning_thread_ref_, owning_thread_task_runner_,
       std::move(release_callback));
 }
 
-scoped_refptr<gpu::ClientSharedImage>
-CanvasResourceSwapChain::GetClientSharedImage() {
+const scoped_refptr<gpu::ClientSharedImage>&
+CanvasResourceSwapChain::GetClientSharedImage() const {
   return front_buffer_shared_image_;
 }
 
@@ -998,8 +985,6 @@
     base::WeakPtr<WebGraphicsContext3DProviderWrapper> context_provider_wrapper,
     base::WeakPtr<CanvasResourceProvider> provider)
     : CanvasResource(std::move(provider),
-                     size,
-                     format,
                      alpha_type,
                      color_space),
       context_provider_wrapper_(std::move(context_provider_wrapper)),
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource.h b/third_party/blink/renderer/platform/graphics/canvas_resource.h
index b0c43775..8065e68 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource.h
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource.h
@@ -86,9 +86,7 @@
   virtual bool IsValid() const = 0;
 
   // The bounds for this resource.
-  gfx::Size Size() const { return size_; }
-
-  viz::SharedImageFormat GetFormat() const { return format_; }
+  gfx::Size Size() const { return GetClientSharedImage()->size(); }
 
   const gfx::ColorSpace& GetColorSpace() const { return color_space_; }
 
@@ -96,7 +94,8 @@
 
   // The ClientSharedImage containing information on the SharedImage
   // attached to the resource.
-  virtual scoped_refptr<gpu::ClientSharedImage> GetClientSharedImage() = 0;
+  virtual const scoped_refptr<gpu::ClientSharedImage>& GetClientSharedImage()
+      const = 0;
 
   // A CanvasResource is not thread-safe and does not allow concurrent usage
   // from multiple threads. But it maybe used from any thread. It remains bound
@@ -146,8 +145,6 @@
 
  protected:
   CanvasResource(base::WeakPtr<CanvasResourceProvider>,
-                 gfx::Size size,
-                 viz::SharedImageFormat format,
                  SkAlphaType alpha_type,
                  const gfx::ColorSpace& color_space);
 
@@ -188,8 +185,6 @@
   }
 
   base::WeakPtr<CanvasResourceProvider> provider_;
-  gfx::Size size_;
-  viz::SharedImageFormat format_;
   SkAlphaType alpha_type_;
   gfx::ColorSpace color_space_;
   bool is_origin_clean_ = true;
@@ -240,8 +235,8 @@
   void WillDraw();
   bool IsLost() const { return owning_thread_data().is_lost; }
 
-  scoped_refptr<gpu::ClientSharedImage> GetClientSharedImage() override;
-  const scoped_refptr<gpu::ClientSharedImage>& GetClientSharedImage() const;
+  const scoped_refptr<gpu::ClientSharedImage>& GetClientSharedImage()
+      const override;
   void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
                     const std::string& parent_path) const;
 
@@ -351,7 +346,8 @@
   bool IsValid() const override;
   bool CreatesAcceleratedTransferableResources() const override { return true; }
   void NotifyResourceLost() override { resource_is_lost_ = true; }
-  scoped_refptr<gpu::ClientSharedImage> GetClientSharedImage() final {
+  const scoped_refptr<gpu::ClientSharedImage>& GetClientSharedImage()
+      const final {
     return client_si_;
   }
 
@@ -414,7 +410,8 @@
     return back_buffer_shared_image_;
   }
   void PresentSwapChain();
-  scoped_refptr<gpu::ClientSharedImage> GetClientSharedImage() override;
+  const scoped_refptr<gpu::ClientSharedImage>& GetClientSharedImage()
+      const override;
 
  private:
   bool UsesAcceleratedRaster() const final { return true; }
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
index 8977325..8532ba3 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_dispatcher_test.cc
@@ -383,7 +383,7 @@
   platform->RunUntilIdle();
 
   auto canvas_resource = CanvasResourceSharedImage::CreateSoftware(
-      GetSize(), viz::SinglePlaneFormat::kRGBA_8888, kPremul_SkAlphaType,
+      GetSize(), viz::SinglePlaneFormat::kBGRA_8888, kPremul_SkAlphaType,
       gfx::ColorSpace::CreateSRGB(),
       /*provider=*/nullptr, shared_image_interface_provider());
   EXPECT_TRUE(!!canvas_resource);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
index 5ae28c1..a49d161f 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_provider.cc
@@ -414,16 +414,9 @@
     TRACE_EVENT0("blink", "CanvasResourceProviderSharedImage::CreateResource");
 
     if (is_software_) {
-      auto format = GetSharedImageFormat();
-      if (!format.IsBitmapFormatSupported()) {
-        // If the rendering format is not supported, downgrade to 8-bits.
-        // TODO(junov): Should we try 12-12-12-12 and 10-10-10-2?
-        format = GetN32FormatForCanvas();
-      }
-
       return CanvasResourceSharedImage::CreateSoftware(
-          Size(), format, GetAlphaType(), GetColorSpace(), CreateWeakPtr(),
-          shared_image_interface_provider_);
+          Size(), viz::SinglePlaneFormat::kBGRA_8888, GetAlphaType(),
+          GetColorSpace(), CreateWeakPtr(), shared_image_interface_provider_);
     }
 
     if (IsGpuContextLost())
@@ -1276,6 +1269,9 @@
     return nullptr;
   }
 
+  CHECK(format == viz::SharedImageFormat::N32Format() ||
+        format == viz::SinglePlaneFormat::kRGBA_F16);
+
   auto provider = std::make_unique<CanvasResourceProviderSharedImage>(
       size, format, alpha_type, color_space, shared_image_interface_provider,
       resource_host);
diff --git a/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc b/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
index ef1d85cc..163e19eb 100644
--- a/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
+++ b/third_party/blink/renderer/platform/graphics/canvas_resource_test.cc
@@ -45,7 +45,7 @@
 
   scoped_refptr<CanvasResource> canvas_resource =
       CanvasResourceSharedImage::CreateSoftware(
-          gfx::Size(10, 10), viz::SinglePlaneFormat::kRGBA_8888,
+          gfx::Size(10, 10), viz::SinglePlaneFormat::kBGRA_8888,
           kPremul_SkAlphaType, gfx::ColorSpace::CreateSRGB(),
           /*CanvasResourceProvider=*/nullptr, shared_image_interface_provider);
   EXPECT_TRUE(!!canvas_resource);
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
index 3c050d2..1ba4d14 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.h
@@ -64,6 +64,7 @@
 
   viz::SharedImageFormat Format() const;
   wgpu::TextureFormat TextureFormat() const { return format_; }
+  wgpu::TextureUsage TextureUsage() const { return usage_; }
   gfx::Size Size() const;
   cc::Layer* CcLayer();
   void Neuter();
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 7044f4e0..a1ed4e1c 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -3607,6 +3607,8 @@
       // The flag will enable us to land the feature over multiple CLs, and will
       // be enabled after the feature has been fully implemented.
       name: "PermissionElementIcon",
+      status: "test",
+      depends_on: ["PermissionElement"],
     },
     {
       name: "Permissions",
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
index a8e195e..010beb4 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.cc
@@ -17,6 +17,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
+#include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/platform/platform.h"
 
 namespace blink {
@@ -88,7 +89,9 @@
   if (CanPurge()) {
     if (called_from == base::MemoryReductionTaskContext::kProactive) {
       PerformMemoryPurge();
-    } else {
+    } else if (!did_purge_with_page_frozen_since_backgrounded_ ||
+               !base::FeatureList::IsEnabled(
+                   features::kMemoryPurgeOnFreezeLimit)) {
       RequestMemoryPurgeWithDelay(kFreezePurgeDelay);
     }
   }
@@ -143,6 +146,7 @@
 
 void MemoryPurgeManager::OnRendererForegrounded() {
   backgrounded_purge_pending_ = false;
+  did_purge_with_page_frozen_since_backgrounded_ = false;
   purge_timer_.Stop();
 }
 
@@ -171,6 +175,11 @@
     base::android::PreFreezeBackgroundMemoryTrimmer::OnRunningCompact();
 #endif
   }
+
+  if (frozen_page_count_ > 0) {
+    did_purge_with_page_frozen_since_backgrounded_ = true;
+  }
+
   backgrounded_purge_pending_ = false;
 }
 
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
index 4d9c657..228aa683 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h
@@ -137,6 +137,10 @@
   int total_page_count_ = 0;
   int frozen_page_count_ = 0;
 
+  // Whether a memory purge was performed with at least one page frozen since
+  // the renderer was backgrounded. Reset when the renderer is foregrounded.
+  bool did_purge_with_page_frozen_since_backgrounded_ = false;
+
   base::OneShotTimer purge_timer_;
 
 #if BUILDFLAG(IS_ANDROID)
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
index a5ce0aec..3e3f1a9 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager_unittest.cc
@@ -5,6 +5,7 @@
 #include "third_party/blink/renderer/platform/scheduler/main_thread/memory_purge_manager.h"
 
 #include "base/memory/memory_pressure_listener.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
@@ -253,6 +254,34 @@
   EXPECT_EQ(0U, MemoryPressureCount());
 }
 
+TEST_F(MemoryPurgeManagerTest, MemoryPurgeOnFreezeLimitEnabled) {
+  base::test::ScopedFeatureList feature_list{
+      features::kMemoryPurgeOnFreezeLimit};
+
+  memory_purge_manager_.SetPurgeDisabledForTesting(true);
+  memory_purge_manager_.SetRendererBackgrounded(true);
+
+  // The initial freeze should trigger a memory purge.
+  memory_purge_manager_.OnPageCreated();
+  memory_purge_manager_.OnPageFrozen();
+  FastForwardBy(base::Seconds(1));
+  EXPECT_EQ(1U, MemoryPressureCount());
+
+  // The second freeze should not trigger a memory purge.
+  memory_purge_manager_.OnPageResumed();
+  memory_purge_manager_.OnPageFrozen();
+  FastForwardBy(base::Seconds(1));
+  EXPECT_EQ(1U, MemoryPressureCount());
+
+  // Another freeze after foregrounding the renderer triggers a memory purge.
+  memory_purge_manager_.SetRendererBackgrounded(false);
+  memory_purge_manager_.OnPageResumed();
+  memory_purge_manager_.SetRendererBackgrounded(true);
+  memory_purge_manager_.OnPageFrozen();
+  FastForwardBy(base::Seconds(1));
+  EXPECT_EQ(2U, MemoryPressureCount());
+}
+
 }  // namespace
 
 }  // namespace blink
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index e403adf..b6c7737 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -9418,3 +9418,6 @@
 crbug.com/418345234 [ Win ] external/wpt/fetch/fetch-later/quota/max-payload.tentative.https.window.html [ Failure ]
 crbug.com/418572857 external/wpt/background-fetch/fetch.https.window.html [ Failure Pass Timeout ]
 crbug.com/418362694 [ Linux ] external/wpt/geolocation/enabled-by-permission-policy-attribute-redirect-on-load.https.sub.html [ Crash Timeout ]
+
+# Skipped due to feature implementation in progress
+crbug.com/420393952 external/wpt/html/semantics/permission-element/quirks-mode-no-height-is-still-bounded.tentative.html [ Failure Skip ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 2cef160..54911f1 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -4416,7 +4416,8 @@
     "owners": ["moonira@google.com"],
     "platforms": ["Linux"],
     "bases": [
-      "external/wpt/css/css-conditional/container-queries/"
+      "external/wpt/css/css-conditional/container-queries/",
+      "external/wpt/css/css-values/if-conditionals.html"
     ],
     "args": [
       "--disable-features=CSSContainerStyleQueriesRange"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html b/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
index caead78..f6d9817 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/if-conditionals.html
@@ -37,6 +37,21 @@
       inherits: true;
       initial-value: 3;
     }
+    @property --angle {
+      syntax: "<angle>";
+      inherits: true;
+      initial-value: 3deg;
+    }
+    @property --time {
+      syntax: "<time>";
+      inherits: true;
+      initial-value: 3s;
+    }
+    @property --resolution {
+      syntax: "<resolution>";
+      inherits: true;
+      initial-value: 3dpi;
+    }
     div {
       font-size: 30px;
     }
@@ -511,6 +526,122 @@
         [['--length', 'attr(data-foo type(<length>))']],
         'false_value');
 
+  // style() queries with range syntax in the condition, literals on both sides of equation
+  test_if_with_custom_properties('if(style(10em > 3px): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(1em > 1px): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(7px > 3px): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(3px > 3px): true_value; else: false_value)', [], 'false_value');
+  test_if_with_custom_properties('if(style(3turn > 3deg): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(3turn <= 3deg): true_value; else: false_value)', [], 'false_value');
+  test_if_with_custom_properties('if(style(3% >= 3%): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(3s > 3ms): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(3dppx > 96dpi): true_value; else: false_value)', [], 'true_value');
+
+  // style() queries with range syntax in the condition, simple custom properties in the condition
+  test_if_with_custom_properties('if(style(--x <= 3): true_value; else: false_value)',
+                                  [['--x', '3']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x >= --y): true_value; else: false_value)',
+                                  [['--x', '3'], ['--y', '3']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--length > 3px): true_value; else: false_value)',
+                                  [['--length', '11px']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x > 3px): true_value; else: false_value)',
+                                  [['--x', '11px']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--number >= 3): true_value; else: false_value)',
+                                  [['--number', '3']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x >= 3): true_value; else: false_value)',
+                                  [['--x', '3']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--percentage > 3%): true_value; else: false_value)',
+                                  [['--percentage', '5%']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x > 3%): true_value; else: false_value)',
+                                  [['--x', '5%']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--angle < 1turn): true_value; else: false_value)',
+                                  [['--angle', '1deg']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x < 1turn): true_value; else: false_value)',
+                                  [['--x', '1deg']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--time <= 1000ms): true_value; else: false_value)',
+                                  [['--time', '1s']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x <= 1000ms): true_value; else: false_value)',
+                                  [['--x', '1s']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(3dppx > --resolution): true_value; else: false_value)',
+                                  [['--resolution', '96dpi']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(3dppx > --x): true_value; else: false_value)',
+                                  [['--x', '96dpi']],
+                                  'true_value');
+
+  // style() queries with range syntax in the condition, invalid custom properties in the condition
+  test_if_with_custom_properties('if(style(--x + 1 >= --y): true_value; else: false_value)',
+                                  [['--x', '5'], ['--y', '3']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--x >= --y + 1): true_value; else: false_value)',
+                                  [['--x', '5'], ['--y', '3']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(calc(--x + 1) >= --y): true_value; else: false_value)',
+                                  [['--x', '5'], ['--y', '3']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--x >= calc(--y + 1)): true_value; else: false_value)',
+                                  [['--x', '5'], ['--y', '3']],
+                                  'false_value');
+
+  // style() queries with range syntax in the condition, custom properties with functions in the condition
+  test_if_with_custom_properties('if(style(--x >= calc(3px + 3px)): true_value; else: false_value)',
+                                  [['--x', '7px']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(calc(var(--x) + 1) >= var(--y)): true_value; else: false_value)',
+                                  [['--x', '5'], ['--y', '3']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(var(--x) >= --x): true_value; else: false_value)',
+                                  [['--x', '3']],
+                                  'true_value');
+
+  // style() queries with range syntax in the condition, incompatible types in the range.
+  test_if_with_custom_properties('if(style(3px > 3): true_value; else: false_value)',
+                                  [],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(3em > 3deg): true_value; else: false_value)',
+                                  [],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(1px >= 1%) or style(1px <= 1%): true_value; else: false_value)',
+                                  [],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--length > 3): true_value; else: false_value)',
+                                  [['--length', '11em']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--number > 3px): true_value; else: false_value)',
+                                  [['--number', '11']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--x >= 3): true_value; else: false_value)',
+                                  [['--x', '3px']],
+                                  'false_value');
+  test_if_with_custom_properties(`if(style(--length >= 30px): true_value;
+                                    else: false_value)`,
+                                  [['--length', 'attr(data-foo type(<length>))']],
+                                  'true_value');
+
+  // style() queries with range syntax in the condition, double range
+  test_if_with_custom_properties('if(style(10px <= 10px < 11px): true_value; else: false_value)', [], 'true_value');
+  test_if_with_custom_properties('if(style(3 < --x <= 5): true_value; else: false_value)',
+                                  [['--x', '5']],
+                                  'true_value');
+  test_if_with_custom_properties('if(style(--x >= --y > --z): true_value; else: false_value)',
+                                  [['--x', '3'], ['--y', '3'], ['--z', '3']],
+                                  'false_value');
+  test_if_with_custom_properties('if(style(--x >= --y > --z): true_value; else: false_value)',
+                                  [['--x', '3'], ['--y', '3'], ['--z', '1']],
+                                  'true_value');
+
   // media() queries in the condition
   test_if(`if(media(max-width: 1px): true_value;
           else: false_value)`,
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-hidden-reftest.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-hidden-reftest.html
new file mode 100644
index 0000000..79055da
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-hidden-reftest.html
@@ -0,0 +1,11 @@
+<!doctype html>
+<title>The icon of the location permission element should not be visibe if it is set to display:none</title>
+<!-- TODO: Update the link to the permission icon spec -->
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md">
+<link rel="mismatch" href="standard-location-permission-element-ref.html">
+<style>
+  ::permission-icon {
+    display: none;
+  }
+</style>
+<permission id="geolocation" type="geolocation"/>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-unique-per-type-reftest.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-unique-per-type-reftest.html
new file mode 100644
index 0000000..d51b1c4
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/icon-unique-per-type-reftest.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title>The camera permission element icon should be different to the location permission element</title>
+<!-- TODO: Update the link to the permission icon spec -->
+<link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md">
+<link rel="mismatch" href="standard-location-permission-element-ref.html">
+<permission id="camera" type="camera"/>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/standard-location-permission-element-ref.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/standard-location-permission-element-ref.html
new file mode 100644
index 0000000..15ffe75
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/permission-icon/standard-location-permission-element-ref.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>A standard permission element of type location, without any non-default styling</title>
+<permission id="geolocation" type="geolocation"/>
diff --git a/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt
new file mode 100644
index 0000000..80bbd08
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/container-style-queries-range/external/wpt/css/css-values/if-conditionals-expected.txt
@@ -0,0 +1,62 @@
+This is a testharness.js-based test.
+Found 29 FAIL, 0 TIMEOUT, 0 NOTRUN.
+[FAIL] CSS Values and Units Test: CSS inline if() function 112
+  assert_equals: "if(style(10em > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 113
+  assert_equals: "if(style(1em > 1px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 114
+  assert_equals: "if(style(7px > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 116
+  assert_equals: "if(style(3turn > 3deg): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 118
+  assert_equals: "if(style(3% >= 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 119
+  assert_equals: "if(style(3s > 3ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 120
+  assert_equals: "if(style(3dppx > 96dpi): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 121
+  assert_equals: "if(style(--x <= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 122
+  assert_equals: "if(style(--x >= --y): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 123
+  assert_equals: "if(style(--length > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 124
+  assert_equals: "if(style(--x > 3px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 125
+  assert_equals: "if(style(--number >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 126
+  assert_equals: "if(style(--x >= 3): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 127
+  assert_equals: "if(style(--percentage > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 128
+  assert_equals: "if(style(--x > 3%): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 129
+  assert_equals: "if(style(--angle < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 130
+  assert_equals: "if(style(--x < 1turn): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 131
+  assert_equals: "if(style(--time <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 132
+  assert_equals: "if(style(--x <= 1000ms): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 133
+  assert_equals: "if(style(3dppx > --resolution): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 134
+  assert_equals: "if(style(3dppx > --x): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 137
+  assert_equals: "if(style(calc(--x + 1) >= --y): true_value; else: false_value)" should be substituted to "false_value". expected "false_value" but got ""
+[FAIL] CSS Values and Units Test: CSS inline if() function 139
+  assert_equals: "if(style(--x >= calc(3px + 3px)): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 140
+  assert_equals: "if(style(calc(var(--x) + 1) >= var(--y)): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
+[FAIL] CSS Values and Units Test: CSS inline if() function 141
+  assert_equals: "if(style(var(--x) >= --x): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got ""
+[FAIL] CSS Values and Units Test: CSS inline if() function 148
+  assert_equals: "if(style(--length >= 30px): true_value;\n                                    else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 149
+  assert_equals: "if(style(10px <= 10px < 11px): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 150
+  assert_equals: "if(style(3 < --x <= 5): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+[FAIL] CSS Values and Units Test: CSS inline if() function 152
+  assert_equals: "if(style(--x >= --y > --z): true_value; else: false_value)" should be substituted to "true_value". expected "true_value" but got "false_value"
+Harness: the test ran to completion.
+
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src
index 9c6d38a..57196dd 160000
--- a/third_party/compiler-rt/src
+++ b/third_party/compiler-rt/src
@@ -1 +1 @@
-Subproject commit 9c6d38aa28100761bc2d6dcd2a590a37f8519adf
+Subproject commit 57196dd146582915c955f6d388e31aea93220c51
diff --git a/third_party/dawn b/third_party/dawn
index 156136e..45b5634 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 156136ebb43d383a3833545598023dd366085166
+Subproject commit 45b5634e70a3a6d61f3704f308d7a419e7db532d
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 5515443..acd68d2 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 55154436a9c71fc62179638710b405c99e80ef54
+Subproject commit acd68d2f092a2e674894c9d389c96e39beec1aa2
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index 9b791fd..705f487 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-13-3-225-g57a873045
-Revision: 57a873045016c7866a298f5e9faa830e6ec24cf9
+Version: VER-2-13-3-230-ge07e56c7f
+Revision: e07e56c7f106b600262ab653d696b7b57f320127
 CPEPrefix: cpe:/a:freetype:freetype:2.13.3
 License: FTL
 License File: src/docs/FTL.TXT
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 57a8730..e07e56c 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 57a873045016c7866a298f5e9faa830e6ec24cf9
+Subproject commit e07e56c7f106b600262ab653d696b7b57f320127
diff --git a/third_party/skia b/third_party/skia
index 1e07a4b..3ba7657 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 1e07a4b16973cf716cb40b72dd969e961f4dd950
+Subproject commit 3ba7657e8745bffd1c6263d5555be935afbc0df9
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index bf02428..5912cbd 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit bf024288c340597e8421df8db06c2de12c25bf31
+Subproject commit 5912cbdd295c2bacb5798432a7b1cac9d20c0725
diff --git a/third_party/vulkan-utility-libraries/src b/third_party/vulkan-utility-libraries/src
index ae56bd6..49ac289 160000
--- a/third_party/vulkan-utility-libraries/src
+++ b/third_party/vulkan-utility-libraries/src
@@ -1 +1 @@
-Subproject commit ae56bd6e65d9faa731150e931cb35f0d895223bc
+Subproject commit 49ac28931f28bffaa3cd73dc4ad997284d574962
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 84b023a..f7ceb1d0 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 84b023ac42601ff51ea6094dc2c18ca62960b25d
+Subproject commit f7ceb1d01a292846db77ec87786be84d6fd568d9
diff --git a/third_party/webrtc b/third_party/webrtc
index 2fe2d51..9909b30 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 2fe2d5190bd3d8766759e3a7de2b648d5ce96aee
+Subproject commit 9909b30d5e3c104d4dce7d066fc8422eef1dcc59
diff --git a/tools/binary_size/libsupersize/native.py b/tools/binary_size/libsupersize/native.py
index ada8cc4..e6bcec6 100644
--- a/tools/binary_size/libsupersize/native.py
+++ b/tools/binary_size/libsupersize/native.py
@@ -670,7 +670,7 @@
   args = [path_util.GetReadElfPath(), '-r', elf_path]
   stdout = subprocess.check_output(args).decode('ascii')
   relocations = re.findall(
-      'Relocation section .* at offset .* contains (\d+) entries', stdout)
+      r'Relocation section .* at offset .* contains (\d+) entries', stdout)
   return sum([int(i) for i in relocations])
 
 
diff --git a/tools/binary_size/libsupersize/readelf.py b/tools/binary_size/libsupersize/readelf.py
index f3d7cc5..b78362e6 100644
--- a/tools/binary_size/libsupersize/readelf.py
+++ b/tools/binary_size/libsupersize/readelf.py
@@ -22,7 +22,7 @@
   """Returns the GN architecture for the given binary."""
   args = [path_util.GetReadElfPath(), '-h', elf_path]
   stdout = subprocess.check_output(args, encoding='ascii')
-  machine = re.search('Machine:\s*(.+)', stdout).group(1)
+  machine = re.search(r'Machine:\s*(.+)', stdout).group(1)
   if machine == 'Intel 80386':
     return 'x86'
   if machine == 'Advanced Micro Devices X86-64':
diff --git a/tools/binary_size/libsupersize/viewer/caspian/BUILD.gn b/tools/binary_size/libsupersize/viewer/caspian/BUILD.gn
index 90dc22c..9f2d40a 100644
--- a/tools/binary_size/libsupersize/viewer/caspian/BUILD.gn
+++ b/tools/binary_size/libsupersize/viewer/caspian/BUILD.gn
@@ -4,11 +4,9 @@
 
 import("//testing/test.gni")
 
-# Enable wasm target that depends on foo.patch being applied.
-if (!defined(is_wasm)) {
-  is_wasm = current_os == "wasm"
+declare_args() {
+  enable_caspian = false
 }
-
 assert(is_linux || is_chromeos || is_wasm)
 
 source_set("caspian-lib") {
@@ -61,18 +59,26 @@
   cflags = [ "-Wall" ]
 }
 
-if (is_wasm) {
-  executable("caspian_web") {
-    sources = [ "caspian_web.cc" ]
-    deps = [
-      ":caspian-lib",
-      "//third_party/re2:re2",
-    ]
-    ldflags = [
-      "-s",
-      "EXPORTED_FUNCTIONS=['_BuildTree','_GetMetadata','_LoadBeforeSizeFile','_LoadSizeFile','_Open','_QueryAncestryById','_QueryProperty','_free','_malloc']",
-      "-s",
-      "EXPORTED_RUNTIME_METHODS=['ccall','cwrap','UTF8ToString']",
-    ]
+if (enable_caspian) {
+  if (is_wasm) {
+    executable("caspian_web") {
+      sources = [ "caspian_web.cc" ]
+      deps = [
+        ":caspian-lib",
+        "//third_party/re2:re2",
+      ]
+      ldflags = [
+        "-s",
+        "EXPORTED_FUNCTIONS=['_BuildTree','_GetMetadata','_LoadBeforeSizeFile','_LoadSizeFile','_Open','_QueryAncestryById','_QueryProperty','_free','_malloc']",
+        "-s",
+        "EXPORTED_RUNTIME_METHODS=['HEAPU8','ccall','cwrap','UTF8ToString']",
+        "-s",
+        "MAXIMUM_MEMORY=4GB",
+      ]
+    }
+  } else {
+    group("caspian_web") {
+      public_deps = [ ":caspian_web(//build/toolchain/wasm)" ]
+    }
   }
 }
diff --git a/tools/binary_size/libsupersize/viewer/caspian/README.md b/tools/binary_size/libsupersize/viewer/caspian/README.md
index f4f4756..a350b68e 100644
--- a/tools/binary_size/libsupersize/viewer/caspian/README.md
+++ b/tools/binary_size/libsupersize/viewer/caspian/README.md
@@ -9,42 +9,24 @@
 
 ## Building the WASM Module
 
-### 1. Install Emscripten
+### Install Emscripten
 
-This step needs to be only once.
-
-1. `git clone` emscripten:
-https://emscripten.org/docs/getting_started/downloads.html
-2. Install the known working version:
-   ```sh
-   cd $EMSDK; ./emsdk install 3.1.9 && ./emsdk activate 3.1.9
-   ```
-3. Activate it via environment variables:
-   ```sh
-   cd $EMSDK; source emsdk_env.sh
-   ```
-
-### 2. Apply Local Patches
-
-Caspian needs some minor edits that we don't want to commit:
+This step needs to be only once. Docs: https://emscripten.org/docs/getting_started/downloads.html
 
 ```sh
-git apply -3 tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
+cd /usr/local/google/code
+git clone https://github.com/emscripten-core/emsdk.git
+cd emsdk
+./emsdk install 4.0.9
+./emsdk activate 4.0.9
+source emsdk_env.sh
 ```
 
-To re-create .patch file:
-```sh
-git add ...files to include in patch...
-git diff --staged > tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
-# Double check that only expected files are included in the patch:
-grep +++ tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
-```
-
-### 3. Build
+### Build
 
 ```sh
 # Omit is_official_build=true if developing locally.
-gn gen out/caspian --args='is_official_build=true treat_warnings_as_errors=false fatal_linker_warnings=false chrome_pgo_phase=0 enable_rust=false'
+gn gen out/caspian --args='enable_caspian=true is_official_build=true treat_warnings_as_errors=false fatal_linker_warnings=false emscripten_path="/usr/local/google/code/emsdk/upstream/emscripten"'
 # Build and copy into static/ directory:
 ( cd out/caspian; autoninja caspian_web && cp wasm/caspian_web.* ../../tools/binary_size/libsupersize/viewer/static/ )
 ```
@@ -90,6 +72,9 @@
    ```
    cd $PATH_TO_EMSDK
    git pull origin main --tags
+   ./emsdk install latest
+   ./emsdk activate latest
+   source ./emsdk_env.sh
    ```
 2.  Update this README's Emscripten version above, then follow its steps.
 
diff --git a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch b/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
deleted file mode 100644
index 1d24e9e..0000000
--- a/tools/binary_size/libsupersize/viewer/caspian/wasmbuild.patch
+++ /dev/null
@@ -1,129 +0,0 @@
-diff --git a/build/config/BUILDCONFIG.gn b/build/config/BUILDCONFIG.gn
-index cc7e92ddb67cd..f9212d2e81c63 100644
---- a/build/config/BUILDCONFIG.gn
-+++ b/build/config/BUILDCONFIG.gn
-@@ -305,10 +305,11 @@ is_ios = current_os == "ios"
- is_linux = current_os == "linux"
- is_mac = current_os == "mac"
- is_nacl = current_os == "nacl"
-+is_wasm = current_os == "wasm"
- is_win = current_os == "win" || current_os == "winuwp"
- 
- is_apple = is_ios || is_mac
--is_posix = !is_win && !is_fuchsia
-+is_posix = !is_win && !is_fuchsia && !is_wasm
- 
- # =============================================================================
- # TARGET DEFAULTS
-diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
-index 6119aa066a982..a77ca7e4a2ab8 100644
---- a/build/config/compiler/BUILD.gn
-+++ b/build/config/compiler/BUILD.gn
-@@ -647,6 +647,20 @@ config("compiler") {
-     ldflags += [ "-fexperimental-relative-c++-abi-vtables" ]
-   }
- 
-+  if (is_wasm) {
-+    ldflags += [
-+      "-s",
-+      "ALLOW_MEMORY_GROWTH=1",
-+      "-s",
-+      "LLD_REPORT_UNDEFINED=1",
-+    ]
-+
-+    if (is_official_build) {
-+      cflags += ["-flto=full"]
-+      ldflags += ["-flto=full"]
-+    }
-+  }
-+
-   # Add flags for link-time optimization. These flags enable
-   # optimizations/transformations that require whole-program visibility at link
-   # time, so they need to be applied to all translation units, and we may end up
-@@ -766,7 +780,7 @@ config("compiler") {
- 
-   # TODO(crbug.com/40242425): Cleanup undefined symbol errors caught by
-   # --no-undefined-version.
--  if (use_lld && !is_win && !is_mac && !is_ios) {
-+  if (use_lld && !is_win && !is_mac && !is_ios && !is_wasm) {
-     ldflags += [ "-Wl,--undefined-version" ]
-   }
- 
-@@ -777,7 +791,7 @@ config("compiler") {
-   if (use_lld && !enable_call_graph_profile_sort) {
-     if (is_win) {
-       ldflags += [ "/call-graph-profile-sort:no" ]
--    } else {
-+    } else if (!is_wasm) {
-       ldflags += [ "-Wl,--no-call-graph-profile-sort" ]
-     }
-   }
-@@ -1615,7 +1629,7 @@ config("default_warnings") {
-         "-Wno-ignored-pragma-optimize",
-       ]
- 
--      if (!is_nacl) {
-+      if (!is_nacl && !is_wasm) {
-         cflags += [
-           # TODO(crbug.com/40231599) Evaluate and possibly enable.
-           "-Wno-deprecated-builtins",
-@@ -2380,6 +2394,9 @@ config("symbols") {
- 
-     # All configs using /DEBUG should include this:
-     configs = [ ":win_pdbaltpath" ]
-+  } else if (is_wasm) {
-+    cflags = [ "-gseparate-dwarf" ]
-+    ldflags = [ "-gseparate-dwarf" ]
-   } else {
-     cflags = []
-     if (is_mac && enable_dsyms) {
-diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
-index 844bc8e540bcc..93e6e0c437fab 100644
---- a/build/toolchain/toolchain.gni
-+++ b/build/toolchain/toolchain.gni
-@@ -47,6 +47,9 @@ if (is_apple) {
-   shlib_extension = ".so"
- } else if (is_win) {
-   shlib_extension = ".dll"
-+} else if (is_wasm) {
-+  # WebAssembly does not stably support shared libraries. (as of Oct 2019)
-+  shlib_extension = ".wasm"
- } else {
-   assert(false, "Platform not supported")
- }
-diff --git a/build/toolchain/wasm/BUILD.gn b/build/toolchain/wasm/BUILD.gn
-new file mode 100644
-index 0000000000000..4aed5264eae15
---- /dev/null
-+++ b/build/toolchain/wasm/BUILD.gn
-@@ -0,0 +1,30 @@
-+# Copyright 2019 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/toolchain/gcc_toolchain.gni")
-+
-+gcc_toolchain("wasm") {
-+  cc = "emcc"
-+  cxx = "em++"
-+  nm = "emcc"
-+  ar = "emar"
-+  ld = cxx
-+
-+  toolchain_args = {
-+    current_cpu = "wasm"
-+    current_os = "wasm"
-+
-+    is_clang = true
-+    use_remoteexec = false
-+    use_debug_fission = false
-+    clang_use_chrome_plugins = false
-+    use_allocator_shim = false
-+    is_component_build = false
-+  }
-+  executable_extension = ".js"
-+  link_outputs = [
-+    "{{output_dir}}/{{target_output_name}}.wasm",
-+    "{{output_dir}}/{{target_output_name}}.wasm.debug.wasm",
-+  ]
-+}
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 1c05f9b6..7a9d74e 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -13098,6 +13098,7 @@
   <int value="-300817167" label="CrosSwitcher:enabled"/>
   <int value="-300018686" label="disable-cloud-import"/>
   <int value="-299841473" label="top-document-isolation:enabled"/>
+  <int value="-299332162" label="PageActionsMigration:enabled"/>
   <int value="-299116652" label="CCTResizable90MaximumHeight:enabled"/>
   <int value="-298647219"
       label="OmniboxContextualSearchOnFocusSuggestions:enabled"/>
@@ -13384,6 +13385,7 @@
   <int value="-190449995" label="CommerceLocalPDPDetection:enabled"/>
   <int value="-189740492"
       label="PolicyIndicationForManagedDefaultSearch:disabled"/>
+  <int value="-189543840" label="PageActionsMigration:disabled"/>
   <int value="-189478545" label="ArcCustomTabsExperiment:enabled"/>
   <int value="-188439713" label="disable-video-capture-use-gpu-memory-buffer"/>
   <int value="-187536302" label="TabstripComboButton:enabled"/>
@@ -13800,6 +13802,7 @@
   <int value="-35256214" label="InterestFeedNoticeCardAutoDismiss:enabled"/>
   <int value="-35002051" label="DefaultBucketUsesRelaxedDurability:enabled"/>
   <int value="-34898620" label="RendererSideContentDecoding:disabled"/>
+  <int value="-33771076" label="MemoryPurgeOnFreezeLimit:disabled"/>
   <int value="-33240310" label="AppShimNotificationAttribution:enabled"/>
   <int value="-32712825" label="CrOSEnforceSystemAec:disabled"/>
   <int value="-31484570"
@@ -14672,6 +14675,7 @@
   <int value="296066418" label="CCTResizableForThirdParties:disabled"/>
   <int value="296215399" label="WindowsMixedReality:disabled"/>
   <int value="296296761" label="MediaFoundationVideoCapture:disabled"/>
+  <int value="296729972" label="MvcUpdateViewWhenModelChanged:enabled"/>
   <int value="297095559" label="ShowBluetoothDebugLogToggle:disabled"/>
   <int value="297750703" label="DesktopPWAsAppIconShortcutsMenu:enabled"/>
   <int value="299270348" label="EnablePixPaymentsInLandscapeMode:disabled"/>
@@ -15122,6 +15126,7 @@
   <int value="455698038"
       label="disable-gesture-requirement-for-media-playback"/>
   <int value="455754036" label="MirroringService:disabled"/>
+  <int value="456095041" label="MvcUpdateViewWhenModelChanged:disabled"/>
   <int value="456908798" label="WebViewSupervisedUserSiteBlock:enabled"/>
   <int value="457265823" label="NtpWideModules:enabled"/>
   <int value="457301531" label="SiteIsolationForGuests:disabled"/>
@@ -15214,6 +15219,7 @@
   <int value="494939785" label="InsecureFormSubmissionInterstitial:disabled"/>
   <int value="495177253" label="CastStreamingWinHardwareH264:enabled"/>
   <int value="495435958" label="PageInfoAboutThisSiteMoreInfo:enabled"/>
+  <int value="495620535" label="MemoryPurgeOnFreezeLimit:enabled"/>
   <int value="496491728" label="SiteSearchSettingsPolicy:enabled"/>
   <int value="496667708" label="ArcInputOverlay:disabled"/>
   <int value="497039057" label="AdaptiveChargingForTesting:disabled"/>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index 192d436a..1b95fb1 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -544,7 +544,7 @@
 </histogram>
 
 <histogram name="Enterprise.CloudExtensionRequestUpdated"
-    enum="EnterpriseCloudExtensionRequestListUpdate" expires_after="2025-10-01">
+    enum="EnterpriseCloudExtensionRequestListUpdate" expires_after="2025-12-01">
   <owner>zmin@chromium.org</owner>
   <owner>src/chrome/browser/enterprise/reporting/OWNERS</owner>
   <summary>
@@ -1835,7 +1835,7 @@
     name="Enterprise.DMServerCloudPolicyRequestStatus{EnterpriseDMServerCloudPolicyRequest}"
     enum="EnterpriseDeviceManagementStatus" expires_after="2025-12-01">
   <owner>vincb@google.com</owner>
-  <owner>zmin@google.com</owner>
+  <owner>zmin@chromium.com</owner>
   <summary>
     Records the returned status of fetching cloud policies from the dmserver.
 
@@ -3661,7 +3661,7 @@
 </histogram>
 
 <histogram name="Enterprise.UserInfoFetch.HttpErrorCode"
-    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2025-10-19">
+    enum="CombinedHttpResponseAndNetErrorCode" expires_after="2025-12-19">
   <owner>vincb@google.com</owner>
   <owner>zmin@chromium.org</owner>
   <summary>
@@ -3674,7 +3674,7 @@
 </histogram>
 
 <histogram name="Enterprise.UserInfoFetch.Status"
-    enum="EnterpriseUserInfoFetchStatus" expires_after="2025-10-26">
+    enum="EnterpriseUserInfoFetchStatus" expires_after="2025-12-26">
   <owner>vincb@google.com</owner>
   <owner>zmin@chromium.org</owner>
   <summary>
@@ -3850,7 +3850,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.AzureADJoinStatusCheckTime" units="ms"
-    expires_after="2025-07-01">
+    expires_after="2025-12-01">
   <owner>igorruvinov@chromium.org</owner>
   <owner>ydago@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
@@ -3862,7 +3862,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.InDomain" enum="BooleanEnabled"
-    expires_after="2025-07-01">
+    expires_after="2025-12-01">
   <owner>ydago@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -3909,7 +3909,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.IsDomainJoined" enum="BooleanEnabled"
-    expires_after="2025-06-08">
+    expires_after="2025-12-10">
   <owner>pastarmovj@chromium.org</owner>
   <owner>zmin@chromium.org</owner>
   <summary>
@@ -3919,7 +3919,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.IsEnterpriseUser" enum="BooleanEnabled"
-    expires_after="2025-10-26">
+    expires_after="2025-12-01">
   <owner>pastarmovj@chromium.org</owner>
   <owner>zmin@chromium.org</owner>
   <summary>
@@ -3930,7 +3930,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.IsFullyManaged2" enum="IsFullyManagedBoolean"
-    expires_after="2025-10-19">
+    expires_after="2025-12-01">
   <owner>twellington@google.com</owner>
   <owner>tedchcoc@chromium.org</owner>
   <summary>
@@ -3941,7 +3941,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.IsJoinedToAzureAD" enum="BooleanEnabled"
-    expires_after="2025-07-01">
+    expires_after="2025-12-01">
   <owner>igorruvinov@chromium.org</owner>
   <owner>ydago@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
@@ -4030,7 +4030,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.OSType" enum="OsSuite"
-    expires_after="2025-07-01">
+    expires_after="2025-12-01">
   <owner>ydago@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -4040,7 +4040,7 @@
 </histogram>
 
 <histogram name="EnterpriseCheck.WindowsProfileType" enum="WindowsProfileType"
-    expires_after="2025-11-02">
+    expires_after="2025-12-01">
   <owner>wfh@chromium.org</owner>
   <owner>chrome-platform-security-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/glic/histograms.xml b/tools/metrics/histograms/metadata/glic/histograms.xml
index e8f8a53..e3aa62d 100644
--- a/tools/metrics/histograms/metadata/glic/histograms.xml
+++ b/tools/metrics/histograms/metadata/glic/histograms.xml
@@ -84,8 +84,10 @@
     <variant name="OnUserInputSubmitted"/>
     <variant name="OpenGlicSettingsPage"/>
     <variant name="OpenOsPermissionSettingsMenu"/>
+    <variant name="PauseActorTask"/>
     <variant name="RefreshSignInCookies"/>
     <variant name="ResizeWindow"/>
+    <variant name="ResumeActorTask"/>
     <variant name="ScrollTo"/>
     <variant name="SetAudioDucking"/>
     <variant name="SetClosedCaptioningState"/>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index 3ea80b0d9..a28f697 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -857,6 +857,19 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.Capture.Win.GetAudioClientTimedOut" enum="Boolean"
+    expires_after="2026-05-30">
+  <owner>henrika@chromium.org</owner>
+  <owner>olka@chromium.org</owner>
+  <owner>webrtc-audio-uma@google.com</owner>
+  <summary>
+    Logs whether the attempt to acquire an input audio client asynchronously
+    timed out or not. A timeout corresponds to a waiting time which exceeds 10
+    seconds. Logged once when an input audio stream is opened and the specified
+    device ID is a process loopback device. Only supported on Windows.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.Capture.Win.Glitches2" units="glitches"
     expires_after="2026-05-11">
   <owner>olka@chromium.org</owner>
@@ -909,6 +922,21 @@
   </summary>
 </histogram>
 
+<histogram name="Media.Audio.Capture.Win.TimeToGetAudioClient" units="ms"
+    expires_after="2026-05-30">
+  <owner>henrika@chromium.org</owner>
+  <owner>olka@chromium.org</owner>
+  <owner>webrtc-audio-uma@google.com</owner>
+  <summary>
+    This histogram records the time it takes to activate an audio client
+    asynchronously, which occurs on the audio.CrUtilityMain thread in the
+    AudioService process. Logged once when an input audio stream is successfully
+    opened and the specified device ID is a process loopback device. Only
+    supported on Windows and when Media.Audio.Capture.Win.GetAudioClientTimedOut
+    is false.
+  </summary>
+</histogram>
+
 <histogram name="Media.Audio.Capture.Win.VoiceProcessingEffects"
     enum="AudioEffectType" expires_after="2025-12-30">
   <owner>henrika@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/web_rtc/enums.xml b/tools/metrics/histograms/metadata/web_rtc/enums.xml
index 5a05346..5665576 100644
--- a/tools/metrics/histograms/metadata/web_rtc/enums.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/enums.xml
@@ -219,8 +219,6 @@
   <int value="2" label="WithoutCreateAnswer"/>
   <int value="3" label="WithoutCreateOffer"/>
   <int value="4" label="NumberOfContents"/>
-  <int value="5" label="NumberOfTransports"/>
-  <int value="6" label="OrderOfContents"/>
   <int value="20" label="IceOptions"/>
   <int value="21" label="IcePwd"/>
   <int value="22" label="IceUfrag"/>
@@ -230,6 +228,7 @@
   <int value="26" label="PayloadTypes"/>
   <int value="27" label="Ssrcs"/>
   <int value="28" label="IceOptionsRenomination"/>
+  <int value="29" label="Direction"/>
   <int value="40" label="RtpHeaderExtensionsRemoved"/>
   <int value="41" label="RtpHeaderExtensionsAdded"/>
   <int value="42" label="RtpHeaderExtensionsModified"/>
@@ -253,6 +252,8 @@
   <int value="84" label="VideoCodecsFmtpH264SpsPpsIdrInKeyframe"/>
   <int value="85" label="VideoCodecsFmtp"/>
   <int value="86" label="VideoCodecsRtcpFb"/>
+  <int value="87" label="VideoCodecsAddedWithRawPacketization"/>
+  <int value="88" label="VideoCodecsModifiedWithRawPacketization"/>
 </enum>
 
 <enum name="SrtpErrorCode">
diff --git a/tools/metrics/structured/sync/structured.xml b/tools/metrics/structured/sync/structured.xml
index a7a86dc..3b8b451 100644
--- a/tools/metrics/structured/sync/structured.xml
+++ b/tools/metrics/structured/sync/structured.xml
@@ -3466,6 +3466,33 @@
       </summary>
     </metric>
   </event>
+
+  <event name="FunctionCall">
+    <summary>
+      Recorded when an instrumented function is called.
+    </summary>
+    <metric name="Name" type="int">
+      <summary>
+        Hash of the function name
+      </summary>
+    </metric>
+    <metric name="Context" type="int">
+      <summary>
+        Hash of the function's context.
+      </summary>
+    </metric>
+    <metric name="TimeSinceSessionStart" type="int">
+      <summary>
+        Time in milliseconds since DevTools sessions start.
+      </summary>
+    </metric>
+    <metric name="SessionId" type="int">
+      <summary>
+        Unique ID of this debugging session. If DevTools is opened on multiple tabs,
+        each instance would have a unique ID.
+      </summary>
+    </metric>
+  </event>
 </project>
 
 <project name="TestProjectOne">
diff --git a/ui/base/models/dialog_model.cc b/ui/base/models/dialog_model.cc
index c11dc4f..5a6b01a 100644
--- a/ui/base/models/dialog_model.cc
+++ b/ui/base/models/dialog_model.cc
@@ -24,23 +24,23 @@
 
 DialogModel::Button::Params& DialogModel::Button::Params::SetId(
     ElementIdentifier id) {
-  CHECK(!id_, base::NotFatalUntil::M123);
-  CHECK(id, base::NotFatalUntil::M123);
+  CHECK(!id_);
+  CHECK(id);
   id_ = id;
   return *this;
 }
 
 DialogModel::Button::Params& DialogModel::Button::Params::SetLabel(
     std::u16string label) {
-  CHECK(label_.empty(), base::NotFatalUntil::M123);
-  CHECK(!label.empty(), base::NotFatalUntil::M123);
+  CHECK(label_.empty());
+  CHECK(!label.empty());
   label_ = label;
   return *this;
 }
 
 DialogModel::Button::Params& DialogModel::Button::Params::SetStyle(
     std::optional<ButtonStyle> style) {
-  CHECK(style_ != style, base::NotFatalUntil::M123);
+  CHECK(style_ != style);
   style_ = style;
   return *this;
 }
@@ -65,7 +65,7 @@
       style_(params.style_),
       is_enabled_(params.is_enabled_),
       callback_(std::move(callback)) {
-  CHECK(callback_, base::NotFatalUntil::M123);
+  CHECK(callback_);
 }
 
 DialogModel::Button::~Button() = default;
@@ -82,11 +82,11 @@
 DialogModel::Builder::Builder() : Builder(nullptr) {}
 
 DialogModel::Builder::~Builder() {
-  CHECK(!model_, base::NotFatalUntil::M123) << "Model should've been built.";
+  CHECK(!model_) << "Model should've been built.";
 }
 
 std::unique_ptr<DialogModel> DialogModel::Builder::Build() {
-  CHECK(model_, base::NotFatalUntil::M123);
+  CHECK(model_);
   return std::move(model_);
 }
 
@@ -133,18 +133,18 @@
     base::RepeatingCallback<void(const Event&)> callback,
     const DialogModel::Button::Params& params) {
   CHECK(params.is_visible_);
-  CHECK(!model_->extra_button_, base::NotFatalUntil::M123);
-  CHECK(!model_->extra_link_, base::NotFatalUntil::M123);
+  CHECK(!model_->extra_button_);
+  CHECK(!model_->extra_link_);
   // Extra buttons are required to have labels.
-  CHECK(!params.label_.empty(), base::NotFatalUntil::M123);
+  CHECK(!params.label_.empty());
   model_->extra_button_.emplace(std::move(callback), params);
   return *this;
 }
 
 DialogModel::Builder& DialogModel::Builder::AddExtraLink(
     DialogModelLabel::TextReplacement link) {
-  CHECK(!model_->extra_button_, base::NotFatalUntil::M123);
-  CHECK(!model_->extra_link_, base::NotFatalUntil::M123);
+  CHECK(!model_->extra_button_);
+  CHECK(!model_->extra_link_);
   model_->extra_link_.emplace(std::move(link));
   return *this;
 }
@@ -152,16 +152,16 @@
 DialogModel::Builder& DialogModel::Builder::OverrideDefaultButton(
     mojom::DialogButton button) {
   // This can only be called once.
-  CHECK(!model_->override_default_button_, base::NotFatalUntil::M123);
+  CHECK(!model_->override_default_button_);
   // Confirm the button exists.
   switch (button) {
     case mojom::DialogButton::kNone:
       break;
     case mojom::DialogButton::kOk:
-      CHECK(model_->ok_button_, base::NotFatalUntil::M123);
+      CHECK(model_->ok_button_);
       break;
     case mojom::DialogButton::kCancel:
-      CHECK(model_->cancel_button_, base::NotFatalUntil::M123);
+      CHECK(model_->cancel_button_);
       break;
   }
   model_->override_default_button_ = button;
@@ -171,9 +171,9 @@
 DialogModel::Builder& DialogModel::Builder::SetInitiallyFocusedField(
     ElementIdentifier id) {
   // This must be called with a non-null id
-  CHECK(id, base::NotFatalUntil::M123);
+  CHECK(id);
   // This can only be called once.
-  CHECK(!model_->initially_focused_field_, base::NotFatalUntil::M123);
+  CHECK(!model_->initially_focused_field_);
   model_->initially_focused_field_ = id;
   return *this;
 }
diff --git a/ui/base/models/dialog_model_field.cc b/ui/base/models/dialog_model_field.cc
index 0aa11de..4375fc7 100644
--- a/ui/base/models/dialog_model_field.cc
+++ b/ui/base/models/dialog_model_field.cc
@@ -45,7 +45,7 @@
     : message_id_(-1), string_(std::move(fixed_string)) {}
 
 const std::u16string& DialogModelLabel::GetString() const {
-  CHECK(replacements_.empty(), base::NotFatalUntil::M123);
+  CHECK(replacements_.empty());
   return string_;
 }
 
@@ -116,17 +116,17 @@
 }
 
 DialogModelParagraph* DialogModelField::AsParagraph() {
-  CHECK_EQ(type_, kParagraph, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kParagraph);
   return static_cast<DialogModelParagraph*>(this);
 }
 
 DialogModelCheckbox* DialogModelField::AsCheckbox() {
-  CHECK_EQ(type_, kCheckbox, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kCheckbox);
   return static_cast<DialogModelCheckbox*>(this);
 }
 
 DialogModelCombobox* DialogModelField::AsCombobox() {
-  CHECK_EQ(type_, kCombobox, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kCombobox);
   return static_cast<DialogModelCombobox*>(this);
 }
 
@@ -135,17 +135,17 @@
 }
 
 const DialogModelMenuItem* DialogModelField::AsMenuItem() const {
-  CHECK_EQ(type_, kMenuItem, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kMenuItem);
   return static_cast<const DialogModelMenuItem*>(this);
 }
 
 const DialogModelTitleItem* DialogModelField::AsTitleItem() const {
-  CHECK_EQ(type_, kTitleItem, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kTitleItem);
   return static_cast<const DialogModelTitleItem*>(this);
 }
 
 DialogModelTextfield* DialogModelField::AsTextfield() {
-  CHECK_EQ(type_, kTextfield, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kTextfield);
   return static_cast<DialogModelTextfield*>(this);
 }
 
@@ -155,7 +155,7 @@
 }
 
 DialogModelCustomField* DialogModelField::AsCustomField() {
-  CHECK_EQ(type_, kCustom, base::NotFatalUntil::M123);
+  CHECK_EQ(type_, kCustom);
   return static_cast<DialogModelCustomField*>(this);
 }
 
@@ -238,8 +238,8 @@
 
 DialogModelMenuItem::Params& DialogModelMenuItem::Params::SetId(
     ElementIdentifier id) {
-  CHECK(!id_, base::NotFatalUntil::M123);
-  CHECK(id, base::NotFatalUntil::M123);
+  CHECK(!id_);
+  CHECK(id);
   id_ = id;
   return *this;
 }
@@ -259,7 +259,7 @@
 
 void DialogModelMenuItem::OnActivated(base::PassKey<DialogModelFieldHost>,
                                       int event_flags) {
-  CHECK(callback_, base::NotFatalUntil::M123);
+  CHECK(callback_);
   callback_.Run(event_flags);
 }
 
@@ -298,8 +298,7 @@
       text_(std::move(text)) {
   // Textfields need either an accessible name or label or the screenreader will
   // not be able to announce anything sensible.
-  CHECK(!label_.empty() || !accessible_name_.empty(),
-        base::NotFatalUntil::M123);
+  CHECK(!label_.empty() || !accessible_name_.empty());
 }
 
 DialogModelTextfield::~DialogModelTextfield() = default;
diff --git a/ui/base/models/dialog_model_menu_model_adapter.cc b/ui/base/models/dialog_model_menu_model_adapter.cc
index 5f5440cc..a33ce2d9 100644
--- a/ui/base/models/dialog_model_menu_model_adapter.cc
+++ b/ui/base/models/dialog_model_menu_model_adapter.cc
@@ -44,8 +44,7 @@
 
 MenuSeparatorType DialogModelMenuModelAdapter::GetSeparatorTypeAt(
     size_t index) const {
-  CHECK_EQ(GetField(index)->type(), DialogModelField::kSeparator,
-           base::NotFatalUntil::M123);
+  CHECK_EQ(GetField(index)->type(), DialogModelField::kSeparator);
   return MenuSeparatorType::NORMAL_SEPARATOR;
 }
 
@@ -101,7 +100,7 @@
 }
 
 bool DialogModelMenuModelAdapter::IsEnabledAt(size_t index) const {
-  CHECK_LT(index, GetItemCount(), base::NotFatalUntil::M123);
+  CHECK_LT(index, GetItemCount());
 
   const DialogModelField* const field = GetField(index);
   // Non-interactive title should be disabled.
@@ -114,7 +113,7 @@
 
 ui::ElementIdentifier DialogModelMenuModelAdapter::GetElementIdentifierAt(
     size_t index) const {
-  CHECK_LT(index, GetItemCount(), base::NotFatalUntil::M123);
+  CHECK_LT(index, GetItemCount());
 
   const DialogModelField* const field = GetField(index);
   if (field->type() == DialogModelField::kTitleItem) {
@@ -140,7 +139,7 @@
 
 const DialogModelField* DialogModelMenuModelAdapter::GetField(
     size_t index) const {
-  CHECK_LT(index, GetItemCount(), base::NotFatalUntil::M123);
+  CHECK_LT(index, GetItemCount());
   return model_->fields(DialogModelHost::GetPassKey())[index].get();
 }
 
diff --git a/ui/base/resource/resource_bundle_android.cc b/ui/base/resource/resource_bundle_android.cc
index 7d9b624..8a1580e0 100644
--- a/ui/base/resource/resource_bundle_android.cc
+++ b/ui/base/resource/resource_bundle_android.cc
@@ -28,14 +28,16 @@
 
 namespace {
 
+using FileDescriptor = int;
+
 bool g_locale_paks_in_apk = false;
 bool g_load_secondary_locale_paks = false;
 // It is okay to cache and share these file descriptors since the
 // ResourceBundle singleton never closes the handles.
-int g_chrome_100_percent_fd = -1;
-int g_resources_pack_fd = -1;
-int g_locale_pack_fd = -1;
-int g_secondary_locale_pack_fd = -1;
+FileDescriptor g_chrome_100_percent_fd = -1;
+FileDescriptor g_resources_pack_fd = -1;
+FileDescriptor g_locale_pack_fd = -1;
+FileDescriptor g_secondary_locale_pack_fd = -1;
 base::MemoryMappedFile::Region g_chrome_100_percent_region;
 base::MemoryMappedFile::Region g_resources_pack_region;
 base::MemoryMappedFile::Region g_locale_pack_region;
@@ -43,7 +45,7 @@
 
 bool LoadFromApkOrFile(const char* apk_path,
                        const base::FilePath* disk_path,
-                       int* out_fd,
+                       FileDescriptor* out_fd,
                        base::MemoryMappedFile::Region* out_region) {
   DCHECK_EQ(*out_fd, -1) << "Attempt to load " << apk_path << " twice.";
   if (apk_path != nullptr) {
@@ -64,9 +66,31 @@
   return success;
 }
 
-int LoadLocalePakFromApk(const std::string& app_locale,
-                         bool in_split,
-                         base::MemoryMappedFile::Region* out_region) {
+// Returns the path within the apk for the given locale's .pak file, or an
+// empty string if it doesn't exist.
+// Only locale paks for the active Android language can be retrieved.
+// If |in_split| is true, look into bundle split-specific location (e.g.
+// 'assets/locales#lang_<lang>/<locale>.pak', otherwise use the default
+// WebView-related location, i.e. 'assets/stored-locales/<locale>.pak'.
+// If |log_error|, logs the path to logcat, but does not abort.
+std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale,
+                                                bool in_bundle,
+                                                bool log_error) {
+  JNIEnv* env = base::android::AttachCurrentThread();
+  base::android::ScopedJavaLocalRef<jstring> ret =
+      Java_ResourceBundle_getLocalePakResourcePath(
+          env, base::android::ConvertUTF8ToJavaString(env, locale), in_bundle,
+          log_error);
+  if (ret.obj() == nullptr) {
+    return std::string();
+  }
+  return base::android::ConvertJavaStringToUTF8(env, ret.obj());
+}
+
+FileDescriptor LoadLocalePakFromApk(
+    const std::string& app_locale,
+    bool in_split,
+    base::MemoryMappedFile::Region* out_region) {
   bool log_error = true;
   std::string locale_path_within_apk =
       GetPathForAndroidLocalePakWithinApk(app_locale, in_split, log_error);
@@ -77,7 +101,7 @@
 }
 
 std::unique_ptr<DataPack> LoadDataPackFromLocalePak(
-    int locale_pack_fd,
+    FileDescriptor locale_pack_fd,
     const base::MemoryMappedFile::Region& region) {
   auto data_pack = std::make_unique<DataPack>(k100Percent);
   CHECK(data_pack->LoadFromFileRegion(base::File(locale_pack_fd), region))
@@ -85,6 +109,13 @@
   return data_pack;
 }
 
+bool LocaleDataPakExists(const std::string& locale,
+                         bool in_split,
+                         bool log_error) {
+  return !GetPathForAndroidLocalePakWithinApk(locale, in_split, log_error)
+              .empty();
+}
+
 }  // namespace
 
 void ResourceBundle::LoadCommonResources() {
@@ -102,14 +133,12 @@
 
 // static
 bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
-  bool log_error = false;
-  bool in_split = !g_locale_paks_in_apk;
-  if (!in_split) {
-    return !GetPathForAndroidLocalePakWithinApk(locale, in_split, log_error)
-                .empty();
+  const bool in_split = !g_locale_paks_in_apk;
+  const bool exists =
+      ::ui::LocaleDataPakExists(locale, in_split, false /* log_error */);
+  if (exists || !in_split) {
+    return exists;
   }
-  if (!GetPathForAndroidLocalePakWithinApk(locale, in_split, log_error).empty())
-    return true;
 
   // Fall back to checking on disk, which is necessary only for tests.
   const auto path = GetLocaleFilePath(locale);
@@ -120,7 +149,7 @@
                                                 bool crash_on_failure) {
   DCHECK(!locale_resources_data_.get() &&
          !secondary_locale_resources_data_.get())
-             << "locale.pak already loaded";
+      << "locale.pak already loaded";
   std::string app_locale = l10n_util::GetApplicationLocale(pref_locale);
 
   // Some Chromium apps have two sets of .pak files for their UI strings, i.e.:
@@ -153,9 +182,9 @@
   //    as the secondary locale pak file. Otherwise don't load a secondary
   //    locale at all.
   //
-  //    This is set by SetLoadSecondaryLocalePaks() which is called
-  //    during ChromeMainDelegate::PostEarlyInitialization() with a value
-  //    that is true iff there are stored-locale/ .pak files.
+  //    This is set by DetectAndSetLoadSecondaryLocalePaks() which is called
+  //    during ChromeMainDelegate::PostEarlyInitialization(). It will set the
+  //    value to true iff there are stored-locale/ .pak files.
   //
   // In other words, if both |g_locale_paks_in_apk| and
   // |g_load_secondary_locale_paks| are true, the stored-locales file will be
@@ -194,11 +223,12 @@
     }
   }
 
-  locale_resources_data_ = LoadDataPackFromLocalePak(
-      g_locale_pack_fd, g_locale_pack_region);
+  locale_resources_data_ =
+      LoadDataPackFromLocalePak(g_locale_pack_fd, g_locale_pack_region);
 
-  if (!locale_resources_data_.get())
+  if (!locale_resources_data_.get()) {
     return std::string();
+  }
 
   // Load secondary locale .pak file if it exists. For debug build monochrome,
   // a secondary locale pak will always be loaded; however, it should be
@@ -211,8 +241,9 @@
     secondary_locale_resources_data_ = LoadDataPackFromLocalePak(
         g_secondary_locale_pack_fd, g_secondary_locale_pack_region);
 
-    if (!secondary_locale_resources_data_.get())
+    if (!secondary_locale_resources_data_.get()) {
       return std::string();
+    }
   }
 
   return app_locale;
@@ -226,8 +257,10 @@
   g_locale_paks_in_apk = value;
 }
 
-void SetLoadSecondaryLocalePaks(bool value) {
-  g_load_secondary_locale_paks = value;
+void DetectAndSetLoadSecondaryLocalePaks() {
+  // Auto-detect based on en-US whether secondary locale .pak files exist.
+  g_load_secondary_locale_paks =
+      LocaleDataPakExists("en-US", false /* in_split */, false /* log_error */);
 }
 
 void LoadMainAndroidPackFile(const char* path_within_apk,
@@ -245,49 +278,38 @@
 void LoadPackFileFromApk(const std::string& path,
                          const std::string& split_name) {
   base::MemoryMappedFile::Region region;
-  int fd = base::android::OpenApkAsset(path, split_name, &region);
+  FileDescriptor fd = base::android::OpenApkAsset(path, split_name, &region);
   CHECK_GE(fd, 0) << "Could not find " << path << " in APK.";
   ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
       base::File(fd), region, ui::kScaleFactorNone);
 }
 
-int GetMainAndroidPackFd(base::MemoryMappedFile::Region* out_region) {
+FileDescriptor GetMainAndroidPackFd(
+    base::MemoryMappedFile::Region* out_region) {
   DCHECK_GE(g_resources_pack_fd, 0);
   *out_region = g_resources_pack_region;
   return g_resources_pack_fd;
 }
 
-int GetCommonResourcesPackFd(base::MemoryMappedFile::Region* out_region) {
+FileDescriptor GetCommonResourcesPackFd(
+    base::MemoryMappedFile::Region* out_region) {
   DCHECK_GE(g_chrome_100_percent_fd, 0);
   *out_region = g_chrome_100_percent_region;
   return g_chrome_100_percent_fd;
 }
 
-int GetLocalePackFd(base::MemoryMappedFile::Region* out_region) {
+FileDescriptor GetLocalePackFd(base::MemoryMappedFile::Region* out_region) {
   DCHECK_GE(g_locale_pack_fd, 0);
   *out_region = g_locale_pack_region;
   return g_locale_pack_fd;
 }
 
-int GetSecondaryLocalePackFd(base::MemoryMappedFile::Region* out_region) {
+FileDescriptor GetSecondaryLocalePackFd(
+    base::MemoryMappedFile::Region* out_region) {
   *out_region = g_secondary_locale_pack_region;
   return g_secondary_locale_pack_fd;
 }
 
-std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale,
-                                                bool in_bundle,
-                                                bool log_error) {
-  JNIEnv* env = base::android::AttachCurrentThread();
-  base::android::ScopedJavaLocalRef<jstring> ret =
-      Java_ResourceBundle_getLocalePakResourcePath(
-          env, base::android::ConvertUTF8ToJavaString(env, locale), in_bundle,
-          log_error);
-  if (ret.obj() == nullptr) {
-    return std::string();
-  }
-  return base::android::ConvertJavaStringToUTF8(env, ret.obj());
-}
-
 void SetNoAvailableLocalePaksForTest() {
   Java_ResourceBundle_setNoAvailableLocalePaks(
       base::android::AttachCurrentThread());
diff --git a/ui/base/resource/resource_bundle_android.h b/ui/base/resource/resource_bundle_android.h
index ba8610e8..06ca565b 100644
--- a/ui/base/resource/resource_bundle_android.h
+++ b/ui/base/resource/resource_bundle_android.h
@@ -44,20 +44,9 @@
 // GetPathForAndroidLocalePakWithinApk rather than looking for them on disk.
 COMPONENT_EXPORT(UI_BASE) void SetLocalePaksStoredInApk(bool value);
 
-// Tell ResourceBundle to load secondary locale .pak files.
-COMPONENT_EXPORT(UI_BASE) void SetLoadSecondaryLocalePaks(bool value);
-
-// Returns the path within the apk for the given locale's .pak file, or an
-// empty string if it doesn't exist.
-// Only locale paks for the active Android language can be retrieved.
-// If |in_split| is true, look into bundle split-specific location (e.g.
-// 'assets/locales#lang_<lang>/<locale>.pak', otherwise use the default
-// WebView-related location, i.e. 'assets/stored-locales/<locale>.pak'.
-// If |log_error|, logs the path to logcat, but does not abort.
-COMPONENT_EXPORT(UI_BASE)
-std::string GetPathForAndroidLocalePakWithinApk(const std::string& locale,
-                                                bool in_split,
-                                                bool log_error);
+// Tell ResourceBundle to determine whether load secondary locale .pak files
+// based on whether secondary locale .pak files exist.
+COMPONENT_EXPORT(UI_BASE) void DetectAndSetLoadSecondaryLocalePaks();
 
 // Called in test when there are no locale pak files available.
 COMPONENT_EXPORT(UI_BASE) void SetNoAvailableLocalePaksForTest();
diff --git a/ui/base/ui_features.gni b/ui/base/ui_features.gni
index 6e7ff9e..da4746e1c 100644
--- a/ui/base/ui_features.gni
+++ b/ui/base/ui_features.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/features.gni")
 import("//build/config/ui.gni")
 
 declare_args() {
diff --git a/ui/events/ozone/chromeos/cursor_controller.cc b/ui/events/ozone/chromeos/cursor_controller.cc
index b2f8007..6409c50 100644
--- a/ui/events/ozone/chromeos/cursor_controller.cc
+++ b/ui/events/ozone/chromeos/cursor_controller.cc
@@ -49,8 +49,7 @@
 
 void CursorController::AddCursorObserver(CursorObserver* observer) {
   base::AutoLock lock(cursor_observers_lock_);
-  CHECK(!base::Contains(cursor_observers_, observer),
-        base::NotFatalUntil::M126);
+  CHECK(!base::Contains(cursor_observers_, observer));
   cursor_observers_.push_back(observer);
 }
 
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
index 3da4914..544c948c 100644
--- a/ui/gl/gl_switches.cc
+++ b/ui/gl/gl_switches.cc
@@ -349,9 +349,17 @@
     return false;
 
 #if BUILDFLAG(IS_ANDROID)
+  // Samsung GPUs already use ANGLE as the GLES driver.  Always choose
+  // ANGLE/Vulkan on these GPUs to avoid the inefficiencies of translating
+  // over ANGLE twice.
+  if (active_gpu.driverId == VK_DRIVER_ID_SAMSUNG_PROPRIETARY) {
+    return true;
+  }
+
   // Exclude SwiftShader-based Android emulators for now.
-  if (active_gpu.driverId == VK_DRIVER_ID_GOOGLE_SWIFTSHADER)
+  if (active_gpu.driverId == VK_DRIVER_ID_GOOGLE_SWIFTSHADER) {
     return false;
+  }
 
   // Encountered bugs with older Imagination drivers.  New drivers seem fixed,
   // but disabled for the sake of experiment for now. crbug.com/371512561
diff --git a/ui/ozone/platform/wayland/wayland.gni b/ui/ozone/platform/wayland/wayland.gni
index a966dea6..01e5517 100644
--- a/ui/ozone/platform/wayland/wayland.gni
+++ b/ui/ozone/platform/wayland/wayland.gni
@@ -2,6 +2,7 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/config/gclient_args.gni")
 import("//build/config/ozone.gni")
 import("//build/config/ui.gni")
 
diff --git a/ui/views/background.cc b/ui/views/background.cc
index b63e5df..8714d51d 100644
--- a/ui/views/background.cc
+++ b/ui/views/background.cc
@@ -54,8 +54,8 @@
  public:
   RoundedRectBackground(ui::ColorVariant color,
                         const gfx::RoundedCornersF& radii,
-                        int for_border_thickness)
-      : radii_(radii), half_thickness_(for_border_thickness / 2.0f) {
+                        const gfx::Insets& insets)
+      : radii_(radii), insets_(insets) {
     SetColor(color);
   }
 
@@ -64,7 +64,7 @@
 
   void Paint(gfx::Canvas* canvas, View* view) const override {
     gfx::Rect rect(view->GetLocalBounds());
-    rect.Inset(half_thickness_);
+    rect.Inset(insets_);
     SkPath path;
     SkScalar radii[8] = {radii_.upper_left(),  radii_.upper_left(),
                          radii_.upper_right(), radii_.upper_right(),
@@ -91,7 +91,7 @@
 
  private:
   const gfx::RoundedCornersF radii_;
-  const float half_thickness_;
+  const gfx::Insets insets_;
 };
 
 // ThemedVectorIconBackground is an image drawn on the view's background using
@@ -188,14 +188,20 @@
     ui::ColorVariant color,
     const gfx::RoundedCornersF& radii,
     int for_border_thickness) {
+  return CreateRoundedRectBackground(color, radii,
+                                     gfx::Insets(for_border_thickness / 2.0f));
+}
+
+std::unique_ptr<Background> CreateRoundedRectBackground(
+    ui::ColorVariant color,
+    const gfx::RoundedCornersF& radii,
+    const gfx::Insets& insets) {
   // If the radii is not set, fallback to SolidBackground since it results in
   // more efficient tiling by cc. See crbug.com/1464128.
-  if (radii.IsEmpty() && for_border_thickness == 0) {
+  if (radii.IsEmpty() && insets.IsEmpty()) {
     return CreateSolidBackground(color);
   }
-
-  return std::make_unique<RoundedRectBackground>(color, radii,
-                                                 for_border_thickness);
+  return std::make_unique<RoundedRectBackground>(color, radii, insets);
 }
 
 std::unique_ptr<Background> CreateThemedVectorIconBackground(
diff --git a/ui/views/background.h b/ui/views/background.h
index 52cf4793..0beb41c 100644
--- a/ui/views/background.h
+++ b/ui/views/background.h
@@ -16,6 +16,7 @@
 #include "ui/color/color_id.h"
 #include "ui/color/color_variant.h"
 #include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/insets.h"
 #include "ui/gfx/geometry/rounded_corners_f.h"
 #include "ui/views/views_export.h"
 
@@ -101,6 +102,12 @@
     const gfx::RoundedCornersF& radii,
     int for_border_thickness = 0);
 
+// Same as above except the background is inset by the specified insets.
+VIEWS_EXPORT std::unique_ptr<Background> CreateRoundedRectBackground(
+    ui::ColorVariant color,
+    const gfx::RoundedCornersF& radii,
+    const gfx::Insets& insets);
+
 // Creates a background from the specified Painter.
 VIEWS_EXPORT std::unique_ptr<Background> CreateBackgroundFromPainter(
     std::unique_ptr<Painter> painter);