diff --git a/DEPS b/DEPS
index 063c174a..7a8b6a0 100644
--- a/DEPS
+++ b/DEPS
@@ -300,19 +300,19 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '3f05162719c305d3e7dcf93800c67fa5b4a295ee',
+  'src_internal_revision': '03be48c96a22a496b50d3709c2749424c56c4300',
   # 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': '245d2b8fb04212b4b7f122f02438a1f0ac62141e',
+  'skia_revision': '515eb6238867bf965b4f28e2348bae1b4e25e380',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'bd4ded6cee0c3cbd1106937be7a43116671692b2',
+  'v8_revision': '35721b006fd74c1d7a316f9dff47376c0a4d0dab',
   # 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': '6e992fa20b4bbcc5c7892ce085d95b0549c9cfa8',
+  'angle_revision': '48b7d12ee04af9fae02eb756f94d1974f1c4bd45',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -396,7 +396,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': 'e8b639c4812cbc6276f37fb393da8537422844f8',
+  'devtools_frontend_revision': 'c1bd58ca07fe70f4b425597ee5e345d2fb57bc44',
   # 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.
@@ -420,7 +420,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': '4cfedf0f36940477134b3eff352cf396b74e8e3b',
+  'dawn_revision': '33862a3ffc8a511d320fbf938c3e956c27e5c6a0',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -536,7 +536,7 @@
 
   # If you change this, also update the libc++ revision in
   # //buildtools/deps_revisions.gni.
-  'libcxx_revision':       '4e8b01e3c1c22a50f8eb5290f6a65859d5886205',
+  'libcxx_revision':       'c79b6718f6f27bd3576c719ee2989767e8fac5ad',
 
   # GN CIPD package version.
   'gn_version': 'git_revision:6e8e0d6d4a151ab2ed9b4a35366e630c55888444',
@@ -1158,7 +1158,7 @@
   },
 
   'src/chrome/release_scripts': {
-      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + 'a8b04e95dc407615a7d2bdc70903376809093548',
+      'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '96fcca5edf9bb94f04fb2fc487aaf332ae1eff0d',
       'condition': 'checkout_chrome_release_scripts',
   },
 
@@ -1490,7 +1490,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/variations/cipd',
-        'version': '5o1aqhP1KwO_yLbWQrePDjIOPYWmsLtIihEL4tFjJqIC',
+        'version': '3VXXseF-F64ZUWlmuk--AZUzoJLO4uE8odnBzSR8SoAC',
       },
     ],
     'dep_type': 'cipd',
@@ -1501,12 +1501,12 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '599d7806ce1185408289232b25620f00947b7c6a',
+    '6ff60127a2e8b147f1b62098202caf2b6110928f',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
   'src/docs/website': {
-    'url': Var('chromium_git') + '/website.git' + '@' + '911ac9ba06c70163c0feff9dfe9d5829dda94b83',
+    'url': Var('chromium_git') + '/website.git' + '@' + 'dc80f907bac0c93c587629f0a8d56b20a9575f4d',
   },
 
   'src/ios/third_party/earl_grey2/src': {
@@ -1530,7 +1530,7 @@
   },
 
   'src/ios/third_party/material_components_ios/src': {
-      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'a33768e63142497497c73383accc8d7254aa4dc9',
+      'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'f93b1dcc0fd51e78a968e6823f02746f2938e1ec',
       'condition': 'checkout_ios',
   },
 
@@ -1660,7 +1660,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'MxOklR3uqOTkCS4tAVAfhzBjAdmVbT0N1LtrxIouxD4C',
+          'version': 'ssCLYB_Hh0LF7Aa9S8GvxR8b0QwsjNxQMQd_Q0q_4NwC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -1731,7 +1731,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/error_prone',
-               'version': 'muHOjW6H-gb8j6gY4sUylWC1paxyWPRMAeYZ1Ok8KkwC',
+               'version': 'ZK9e0tqXwlyM9VSS1O09u8kkCtk-SfKOTtSXyAq22-UC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1764,7 +1764,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/manifest_merger',
-               'version': 'vHfVYpJ8u72iZgoN6s-BvRweZgVkKP-j_QbT8eSgc3gC',
+               'version': 'MBIQRTQ6FavhzrjRrKgZHXpedUncW5cLxVQjYvkSnHgC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2855,7 +2855,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@ddb9ba0fdcc3193af3c60f811fa4524d54943890',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d04dafb08ac68d0ed86ef37455bcea22e77eca5a',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@4a038eafdf9e9f3e0ac2e200127df969f3a51ddb',
   '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@8e82b7cfeca98baae9a01a53511483da7194f854',
@@ -2864,7 +2864,7 @@
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@7b6539f24633096c25631bab9fd572bd1ad9b27b',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@59dc56aa3023434317a5197d77be51855b5fd2fb',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@abc2498bde8d65841f463431a6220701fad44c64',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@5cf5ba49fd12c048e4192b150eb7528253a887ba',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@6ebe2666e8d9ec374657066d0834560ed8551acc',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21',
@@ -2903,13 +2903,13 @@
     Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + 'c01b768bce4a143e152c1870b6ba99ea6267d2b0',
 
   'src/third_party/webgpu-cts/src':
-    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '75af759c3c6bc4cb77a0df7c735a8a2061acaa37',
+    Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'd3ac5784fb25afe1a9605af57112b854bb8206c7',
 
   'src/third_party/webpagereplay':
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + '74b51006acd2bd9f533c3c309a73cdf2479057c4',
+    Var('webrtc_git') + '/src.git' + '@' + '7bb84253eab7c6c607fe7141815fbd7d4fa326b7',
 
   # 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.
@@ -3020,7 +3020,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/eche_app/app',
-        'version': 'xNq9WwmHSfKs5EeHx8lOA-fM772owYHnZmue2MNQWqUC',
+        'version': 'ySpsvm5BaDi-mSxkTdIlTXUYREw21tq1odNWKOlEW58C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3031,7 +3031,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/boca_app/app',
-        'version': 'FxuES9vKxPPnFlhpnL20lBplbs-EoRdwcUWLcBXn53sC',
+        'version': 'kLp-1VsGHWAcnZ2L3vvuwoaG7xjSPmK5va6ksFAzRisC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3086,7 +3086,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'dRGB9OAnRbFszJVcOYRUPiAHxhen5vCtXmk87H3GOEAC',
+        'version': 'EfEDfVaBVVUs2WQy7jb8MAl--7vsXZO3TXaSKNybscoC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4701,7 +4701,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '04489da71ef10228a79347ccfd484cfed4f613d3',
+        'd107d1bf097cecf3dc2979e13d92a3361bcdf5f8',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
index 59951a7..765cb1b 100644
--- a/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
+++ b/android_webview/java/src/org/chromium/android_webview/AwContentsClient.java
@@ -30,6 +30,7 @@
 import org.chromium.base.Callback;
 import org.chromium.base.ContextUtils;
 import org.chromium.base.Log;
+import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.ScopedSysTraceEvent;
 import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.embedder_support.util.WebResourceResponseInfo;
@@ -44,14 +45,32 @@
 import java.util.regex.Pattern;
 
 /**
- * Base-class that an AwContents embedder derives from to receive callbacks.
- * For any other callbacks we need to make transformations of (e.g. adapt parameters
- * or perform filtering) we can provide final overrides for methods here, and then introduce
- * new abstract methods that the our own client must implement.
- * i.e.: all methods in this class should either be final, or abstract.
+ * Base-class that an AwContents embedder derives from to receive callbacks. For any other callbacks
+ * we need to make transformations of (e.g. adapt parameters or perform filtering) we can provide
+ * final overrides for methods here, and then introduce new abstract methods that the our own client
+ * must implement. i.e.: all methods in this class should either be final, or abstract.
  */
 @Lifetime.WebView
 public abstract class AwContentsClient {
+
+    // LINT.IfChange(SendIntentState)
+    @IntDef({
+        SendIntentState.SKIPPED,
+        SendIntentState.INVOKED,
+        SendIntentState.ACTIVITY_STARTED,
+        SendIntentState.MAX_VALUE
+    })
+    private @interface SendIntentState {
+        // These values are persisted to logs. Entries should not be renumbered and
+        // numeric values should never be reused.
+        int SKIPPED = 0;
+        int INVOKED = 1;
+        int ACTIVITY_STARTED = 2;
+        int MAX_VALUE = ACTIVITY_STARTED;
+    }
+
+    // LINT.ThenChange(//tools/metrics/histograms/metadata/android/enums.xml:WebViewSendIntentState)
+
     private static final String TAG = "AwContentsClient";
     private final AwContentsClientCallbackHelper mCallbackHelper;
 
@@ -175,6 +194,7 @@
         if (poller != null && poller.shouldCancelAllCallbacks()) return false;
 
         if (hasWebViewClient()) {
+            recordSendBrowsingIntentState(SendIntentState.SKIPPED);
             // Note: only GET requests can be overridden, so we hardcode the method.
             AwWebResourceRequest request =
                     new AwWebResourceRequest(
@@ -192,6 +212,7 @@
 
     private static boolean sendBrowsingIntent(
             Context context, String url, boolean hasUserGesture, boolean isRedirect) {
+        recordSendBrowsingIntentState(SendIntentState.INVOKED);
         if (!hasUserGesture && !isRedirect) {
             Log.w(TAG, "Denied starting an intent without a user gesture, URI %s", url);
             return true;
@@ -236,6 +257,7 @@
         }
 
         try {
+            recordSendBrowsingIntentState(SendIntentState.ACTIVITY_STARTED);
             context.startActivity(intent);
             return true;
         } catch (ActivityNotFoundException ex) {
@@ -251,6 +273,11 @@
         return false;
     }
 
+    private static void recordSendBrowsingIntentState(@SendIntentState int activityStarted) {
+        RecordHistogram.recordEnumeratedHistogram(
+                "Android.WebView.SendBrowsingIntent", activityStarted, SendIntentState.MAX_VALUE);
+    }
+
     public static Uri[] parseFileChooserResult(int resultCode, Intent intent) {
         if (resultCode == Activity.RESULT_CANCELED) {
             return null;
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
index 4feb465..7eb6697 100644
--- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
+++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -218,9 +218,6 @@
                 BlinkFeatures.PRELOAD_LINK_REL_DATA_URLS,
                 "Allow preloading data: URLs with link rel=preload"),
         Flag.baseFeature(
-                BlinkFeatures.BYPASS_CSP_FOR_PRELOADS,
-                "Enables bypassing CSP checks when we consume a preload"),
-        Flag.baseFeature(
                 BlinkFeatures.DOCUMENT_POLICY_EXPECT_NO_LINKED_RESOURCES,
                 "Enables the ability to use Document Policy header to control feature"
                         + " ExpectNoLinkedResources."),
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/AwParameterizedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/AwParameterizedTest.java
index af315af..c786b837 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/AwParameterizedTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/AwParameterizedTest.java
@@ -52,6 +52,7 @@
                         settings.setDefaultFontSize(42);
                         settings.setTextZoom(200);
                         settings.setUserAgentString("foobar");
+                        settings.setPaymentRequestEnabled(true);
                     },
                     "allMutations..true")
         };
diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/WebExposedTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/WebExposedTest.java
index 4521a78..36db7e82 100644
--- a/android_webview/javatests/src/org/chromium/android_webview/test/WebExposedTest.java
+++ b/android_webview/javatests/src/org/chromium/android_webview/test/WebExposedTest.java
@@ -143,6 +143,8 @@
 
                     // Exposes window.openDatabase
                     settings.setDatabaseEnabled(true);
+                    // Exposes Payment APIs
+                    settings.setPaymentRequestEnabled(true);
 
                     class SynchronousConsole {
                         @JavascriptInterface
diff --git a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
index d3af95e..110e9bf 100644
--- a/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/android_webview/test/data/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4113,6 +4113,7 @@
     getter align
     getter allow
     getter allowFullscreen
+    getter allowPaymentRequest
     getter contentDocument
     getter contentWindow
     getter credentialless
@@ -4140,6 +4141,7 @@
     setter align
     setter allow
     setter allowFullscreen
+    setter allowPaymentRequest
     setter credentialless
     setter csp
     setter frameBorder
@@ -6853,6 +6855,63 @@
     method quadraticCurveTo
     method rect
     method roundRect
+interface PaymentAddress
+    attribute @@toStringTag
+    getter addressLine
+    getter city
+    getter country
+    getter dependentLocality
+    getter organization
+    getter phone
+    getter postalCode
+    getter recipient
+    getter region
+    getter sortingCode
+    method constructor
+    method toJSON
+interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent
+    attribute @@toStringTag
+    getter methodDetails
+    getter methodName
+    method constructor
+interface PaymentRequest : EventTarget
+    static method isSecurePaymentConfirmationAvailable
+    attribute @@toStringTag
+    getter id
+    getter onpaymentmethodchange
+    getter onshippingaddresschange
+    getter onshippingoptionchange
+    getter shippingAddress
+    getter shippingOption
+    getter shippingType
+    method abort
+    method canMakePayment
+    method constructor
+    method hasEnrolledInstrument
+    method show
+    setter onpaymentmethodchange
+    setter onshippingaddresschange
+    setter onshippingoptionchange
+interface PaymentRequestUpdateEvent : Event
+    attribute @@toStringTag
+    method constructor
+    method updateWith
+interface PaymentResponse : EventTarget
+    attribute @@toStringTag
+    getter details
+    getter methodName
+    getter onpayerdetailchange
+    getter payerEmail
+    getter payerName
+    getter payerPhone
+    getter requestId
+    getter shippingAddress
+    getter shippingOption
+    method complete
+    method constructor
+    method retry
+    method toJSON
+    setter onpayerdetailchange
 interface Performance : EventTarget
     attribute @@toStringTag
     getter eventCounts
diff --git a/ash/wm/desks/desk.cc b/ash/wm/desks/desk.cc
index 932ae0a..bb37ad7 100644
--- a/ash/wm/desks/desk.cc
+++ b/ash/wm/desks/desk.cc
@@ -296,7 +296,7 @@
 
   // No windows should be added to the desk container on |root| prior to
   // tracking it by the desk.
-  aura::Window* desk_container = root->GetChildById(container_id_);
+  aura::Window* desk_container = GetDeskContainerForRoot(root);
   DCHECK(desk_container->children().empty());
   auto container_observer =
       std::make_unique<DeskContainerObserver>(this, desk_container);
@@ -495,7 +495,7 @@
   }
 
   for (aura::Window* root : Shell::GetAllRootWindows()) {
-    auto* container = root->GetChildById(container_id_);
+    auto* container = GetDeskContainerForRoot(root);
     container->layer()->SetOpacity(0);
     container->Show();
   }
@@ -510,8 +510,9 @@
   };
 
   if (!MaybeResetContainersOpacities()) {
-    for (aura::Window* root : Shell::GetAllRootWindows())
-      root->GetChildById(container_id_)->Show();
+    for (aura::Window* root : Shell::GetAllRootWindows()) {
+      GetDeskContainerForRoot(root)->Show();
+    }
   }
 
   is_active_ = true;
@@ -589,8 +590,9 @@
   auto* active_window = window_util::GetActiveWindow();
 
   // Hide the associated containers on all roots.
-  for (aura::Window* root : Shell::GetAllRootWindows())
-    root->GetChildById(container_id_)->Hide();
+  for (aura::Window* root : Shell::GetAllRootWindows()) {
+    GetDeskContainerForRoot(root)->Hide();
+  }
 
   is_active_ = false;
   last_day_visited_ = desks_restore_util::GetDaysFromLocalEpoch();
@@ -739,7 +741,6 @@
 
 aura::Window* Desk::GetDeskContainerForRoot(aura::Window* root) const {
   DCHECK(root);
-
   return root->GetChildById(container_id_);
 }
 
@@ -1043,7 +1044,7 @@
     return false;
 
   for (aura::Window* root : Shell::GetAllRootWindows()) {
-    auto* container = root->GetChildById(container_id_);
+    auto* container = GetDeskContainerForRoot(root);
     container->layer()->SetOpacity(1);
   }
   started_activation_animation_ = false;
diff --git a/ash/wm/desks/desk_animation_base.cc b/ash/wm/desks/desk_animation_base.cc
index 98c6550..37aaec3b 100644
--- a/ash/wm/desks/desk_animation_base.cc
+++ b/ash/wm/desks/desk_animation_base.cc
@@ -28,9 +28,6 @@
 DeskAnimationBase::~DeskAnimationBase() {
   for (auto& observer : controller_->observers_)
     observer.OnDeskSwitchAnimationFinished();
-
-  if (finished_callback_)
-    std::move(finished_callback_).Run();
 }
 
 void DeskAnimationBase::Launch() {
diff --git a/ash/wm/desks/desk_animation_base.h b/ash/wm/desks/desk_animation_base.h
index d351275..8f4555a5 100644
--- a/ash/wm/desks/desk_animation_base.h
+++ b/ash/wm/desks/desk_animation_base.h
@@ -65,11 +65,6 @@
   void OnEndingDeskScreenshotTaken() override;
   void OnDeskSwitchAnimationFinished() override;
 
-  void set_finished_callback(base::OnceClosure finished_callback) {
-    DCHECK(finished_callback_.is_null());
-    finished_callback_ = std::move(finished_callback);
-  }
-
   void set_skip_notify_controller_on_animation_finished_for_testing(bool val) {
     skip_notify_controller_on_animation_finished_for_testing_ = val;
   }
@@ -160,9 +155,6 @@
   // DeskController are tied together in production code, but may not be in a
   // test scenario.
   bool skip_notify_controller_on_animation_finished_for_testing_ = false;
-
-  // Callback for when the animation is finished.
-  base::OnceClosure finished_callback_;
 };
 
 }  // namespace ash
diff --git a/ash/wm/desks/desk_button/desk_button.cc b/ash/wm/desks/desk_button/desk_button.cc
index 9b913e60..e30788a 100644
--- a/ash/wm/desks/desk_button/desk_button.cc
+++ b/ash/wm/desks/desk_button/desk_button.cc
@@ -85,15 +85,8 @@
       desk_name_label_
           ->GetPreferredSize(views::SizeBounds(desk_name_label_->width(), {}))
           .width();
-  if (desk_button_container_->ShouldShowDeskProfilesUi()) {
-    width += kDeskButtonAvatarSize.width() +
-             kDeskButtonChildSpacingHorizontalExpanded;
-    width = std::clamp(width, kDeskButtonWidthHorizontalZeroWithAvatar,
-                       kDeskButtonWidthHorizontalExpandedWithAvatar);
-  } else {
     width = std::clamp(width, kDeskButtonWidthHorizontalZeroNoAvatar,
                        kDeskButtonWidthHorizontalExpandedNoAvatar);
-  }
 
   return {width, height};
 }
@@ -199,16 +192,6 @@
       this, gfx::Insets(kDeskButtonFocusRingHaloInset),
       kDeskButtonCornerRadius);
 
-  if (chromeos::features::IsDeskProfilesEnabled()) {
-    AddChildView(views::Builder<views::ImageView>()
-                     .CopyAddressTo(&desk_avatar_view_)
-                     .SetPaintToLayer()
-                     .Build());
-    desk_avatar_view_->layer()->SetFillsBoundsOpaquely(false);
-    desk_avatar_view_->layer()->SetRoundedCornerRadius(
-        gfx::RoundedCornersF(kDeskButtonAvatarSize.width()));
-  }
-
   AddChildView(
       views::Builder<views::Label>()
           .CopyAddressTo(&desk_name_label_)
@@ -273,27 +256,6 @@
     return;
   }
 
-  if (!desk_button_container_->zero_state() &&
-      desk_button_container_->ShouldShowDeskProfilesUi()) {
-    if (auto* desk_profiles_delegate =
-            Shell::Get()->GetDeskProfilesDelegate()) {
-      if (auto* summary =
-              desk_profiles_delegate->GetProfilesSnapshotByProfileId(
-                  active_desk->lacros_profile_id())) {
-        profile_ = *summary;
-        desk_avatar_image_ = gfx::ImageSkiaOperations::CreateResizedImage(
-            summary->icon, skia::ImageOperations::RESIZE_BEST,
-            kDeskButtonAvatarSize);
-
-        desk_avatar_view_->SetImage(
-            ui::ImageModel::FromImageSkia(desk_avatar_image_));
-        desk_avatar_view_->SetImageSize(kDeskButtonAvatarSize);
-        desk_avatar_view_->SetVisible(true);
-        return;
-      }
-    }
-  }
-
   desk_avatar_view_->SetVisible(false);
 }
 
diff --git a/ash/wm/desks/desk_button/desk_button_container.cc b/ash/wm/desks/desk_button/desk_button_container.cc
index e020bf2..29ce8ea 100644
--- a/ash/wm/desks/desk_button/desk_button_container.cc
+++ b/ash/wm/desks/desk_button/desk_button_container.cc
@@ -34,26 +34,10 @@
 DeskButtonContainer::~DeskButtonContainer() = default;
 
 // static
-bool DeskButtonContainer::ShouldShowDeskProfilesUi() {
-  if (!chromeos::features::IsDeskProfilesEnabled()) {
-    return false;
-  }
-  auto* desk_profiles_delegate = Shell::Get()->GetDeskProfilesDelegate();
-  if (!desk_profiles_delegate ||
-      desk_profiles_delegate->GetProfilesSnapshot().size() < 2u) {
-    return false;
-  }
-  return true;
-}
-
-// static
 int DeskButtonContainer::GetMaxLength(bool zero_state) {
   if (zero_state) {
     return kDeskButtonContainerHeightVertical;
   }
-  if (ShouldShowDeskProfilesUi()) {
-    return kDeskButtonContainerWidthHorizontalExpandedWithAvatar;
-  }
   return kDeskButtonContainerWidthHorizontalExpandedNoAvatar;
 }
 
diff --git a/ash/wm/desks/desk_button/desk_button_container.h b/ash/wm/desks/desk_button/desk_button_container.h
index 056f332..dc08e1e 100644
--- a/ash/wm/desks/desk_button/desk_button_container.h
+++ b/ash/wm/desks/desk_button/desk_button_container.h
@@ -39,8 +39,6 @@
   DeskButtonContainer& operator=(const DeskButtonContainer&) = delete;
   ~DeskButtonContainer() override;
 
-  static bool ShouldShowDeskProfilesUi();
-
   static int GetMaxLength(bool zero_state);
 
   bool zero_state() const { return zero_state_; }
diff --git a/ash/wm/desks/desk_mini_view.cc b/ash/wm/desks/desk_mini_view.cc
index 3e623cb3..4cabc9c 100644
--- a/ash/wm/desks/desk_mini_view.cc
+++ b/ash/wm/desks/desk_mini_view.cc
@@ -201,16 +201,6 @@
       },
       base::Unretained(this)));
 
-  // Only show profile avatar button when there is more than one profile logged
-  // in.
-  auto* desk_profile_delegate = Shell::Get()->GetDeskProfilesDelegate();
-  if (chromeos::features::IsDeskProfilesEnabled() &&
-      ((desk_profile_delegate &&
-        desk_profile_delegate->GetProfilesSnapshot().size() > 1))) {
-    desk_profile_button_ =
-        AddChildView(std::make_unique<DeskProfilesButton>(desk, this));
-  }
-
   desk_action_view_ = AddChildView(std::make_unique<DeskActionView>(
       /*combine_desks_target_name=*/
       DesksController::Get()->GetCombineDesksTargetName(desk_),
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc
index d22a585f..7ba7387 100644
--- a/ash/wm/desks/desks_controller.cc
+++ b/ash/wm/desks/desks_controller.cc
@@ -800,9 +800,10 @@
 
   UMA_HISTOGRAM_ENUMERATION(kDeskSwitchHistogramName, source);
 
-  const int target_desk_index = GetDeskIndex(desk);
-  if (source != DesksSwitchSource::kDeskRemoved &&
-      source != DesksSwitchSource::kDeskButtonDeskRemoved) {
+  const bool is_removal = source == DesksSwitchSource::kDeskRemoved ||
+                          source == DesksSwitchSource::kDeskButtonDeskRemoved;
+
+  if (!is_removal) {
     // Desk removal has its own a11y alert.
     Shell::Get()
         ->accessibility_controller()
@@ -810,8 +811,7 @@
             IDS_ASH_VIRTUAL_DESKS_ALERT_DESK_ACTIVATED, desk->name()));
   }
 
-  if (source == DesksSwitchSource::kDeskRemoved ||
-      source == DesksSwitchSource::kDeskButtonDeskRemoved ||
+  if (is_removal ||
       (source == DesksSwitchSource::kRemovalUndone && in_overview) ||
       is_user_switch) {
     // Desk switches due to desks removal, undoing the removal of an active desk
@@ -829,6 +829,11 @@
     return;
   }
 
+  // Desk activation will be done during the animation.
+
+  const int starting_desk_index = GetDeskIndex(active_desk());
+  const int target_desk_index = GetDeskIndex(desk);
+
   // When switching desks we want to update window activation when leaving
   // overview or if nothing was active prior to switching desks. This will
   // ensure that after switching desks, we will try to focus a candidate window.
@@ -844,7 +849,6 @@
       IsParentSwitchableContainer(active_window) ||
       IsApplistActiveInTabletMode(active_window);
 
-  const int starting_desk_index = GetDeskIndex(active_desk());
   animation_ = std::make_unique<DeskActivationAnimation>(
       this, starting_desk_index, target_desk_index, source,
       update_window_activation);
diff --git a/ash/wm/desks/desks_unittests.cc b/ash/wm/desks/desks_unittests.cc
index 7e85bc53..e7d5d5f6f 100644
--- a/ash/wm/desks/desks_unittests.cc
+++ b/ash/wm/desks/desks_unittests.cc
@@ -304,32 +304,6 @@
   event_generator->MoveMouseBy(0, 50);
 }
 
-TestDeskProfilesDelegate& GetDeskProfilesTestDelegate() {
-  CHECK(chromeos::features::IsDeskProfilesEnabled());
-  return *static_cast<TestDeskProfilesDelegate*>(
-      Shell::Get()->GetDeskProfilesDelegate());
-}
-
-uint64_t GetDummyLacrosDeskProfileId(size_t index) {
-  static constexpr uint64_t kLacrosProfileIdBase = 1001;
-  return kLacrosProfileIdBase + index * 2;
-}
-
-// Adds `count` dummy lacros profiles to the test delegate.
-void AddDummyLacrosDeskProfiles(size_t count) {
-  for (size_t i = 0; i != count; ++i) {
-    LacrosProfileSummary summary;
-    summary.profile_id = GetDummyLacrosDeskProfileId(i);
-    summary.name =
-        base::UTF8ToUTF16(base::StringPrintf("Lacros user %lu", i + 1));
-    summary.email =
-        base::UTF8ToUTF16(base::StringPrintf("email%lu@gmail.com", i + 1));
-    summary.icon = gfx::test::CreateImageSkia(32, 32);
-
-    GetDeskProfilesTestDelegate().UpdateTestProfile(std::move(summary));
-  }
-}
-
 // Sends tab keys (or shift+tab) until the passed predicate becomes true, or a
 // fixed max is hit.
 template <class Predicate>
@@ -9164,10 +9138,9 @@
   EXPECT_TRUE(OverviewController::Get()->InOverviewSession());
 }
 
-class DeskBarTest
-    : public AshTestBase,
-      public ::testing::WithParamInterface<
-          testing::tuple<bool, bool, bool, DeskBarViewBase::Type>> {
+class DeskBarTest : public AshTestBase,
+                    public ::testing::WithParamInterface<
+                        testing::tuple<bool, bool, DeskBarViewBase::Type>> {
  public:
   DeskBarTest()
       : test_close_all_window_close_timeout_(
@@ -9178,12 +9151,10 @@
   ~DeskBarTest() override = default;
 
   void SetUp() override {
-    std::tie(use_touch_gestures_, use_16_desks_, use_desk_profiles_,
-             bar_type_) = GetParam();
+    std::tie(use_touch_gestures_, use_16_desks_, bar_type_) = GetParam();
 
     scoped_feature_list_.InitWithFeatureStates(
-        {{features::kFeatureManagement16Desks, use_16_desks_},
-         {chromeos::features::kDeskProfiles, use_desk_profiles_}});
+        {{features::kFeatureManagement16Desks, use_16_desks_}});
 
     AshTestBase::SetUp();
 
@@ -9192,12 +9163,6 @@
     ash_test_helper()->saved_desk_test_helper()->WaitForDeskModels();
 
     SetShowDeskButtonInShelfPref(GetPrimaryUserPrefService(), true);
-
-    if (use_desk_profiles_) {
-      // Add two lacros profiles so that the desk profile avatar shows up in
-      // desk mini views.
-      AddDummyLacrosDeskProfiles(2);
-    }
   }
 
   void TearDown() override {
@@ -9405,7 +9370,6 @@
 
   bool use_touch_gestures_;
   bool use_16_desks_;
-  bool use_desk_profiles_;
   DeskBarViewBase::Type bar_type_;
 
  private:
@@ -10211,11 +10175,6 @@
     EXPECT_EQ(DesksTestApi::IsDeskShortcutViewVisible(mini_view),
               expected_visibility);
 
-    if (use_desk_profiles_) {
-      PressAndReleaseKey(ui::VKEY_TAB);
-      ASSERT_TRUE(mini_view->desk_profiles_button()->HasFocus());
-    }
-
     if (i == 0) {
       PressAndReleaseKey(ui::VKEY_TAB);
 
@@ -10316,11 +10275,6 @@
       }
     }
 
-    if (use_desk_profiles_) {
-      PressAndReleaseKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
-      ASSERT_TRUE(mini_view->desk_profiles_button()->HasFocus());
-    }
-
     // The shortcut view only appears on the first 8 desks in the desk button
     // desk bar.
     const bool expected_visibility =
@@ -10785,12 +10739,6 @@
       PressAndReleaseKey(ui::VKEY_TAB);
       PressAndReleaseKey(ui::VKEY_TAB);
 
-      // If desk profiles are enabled then we need to tab past the profile
-      // avatar button.
-      if (use_desk_profiles_) {
-        PressAndReleaseKey(ui::VKEY_TAB);
-      }
-
       PressAndReleaseKey(ui::VKEY_TAB);
       ASSERT_TRUE(mini_views[1]->desk_preview()->HasFocus());
 
@@ -11714,111 +11662,6 @@
                                      true, 2);
 }
 
-class DeskProfilesTest : public AshTestBase {
- public:
-  DeskProfilesTest() = default;
-  ~DeskProfilesTest() override = default;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_{
-      chromeos::features::kDeskProfiles};
-};
-
-TEST_F(DeskProfilesTest, RemoveProfile) {
-  // This test creates three dummy lacros profiles and sets up three desks with
-  // each associated with a different user. The last user is then removed and we
-  // verify that the desk has reverted to the default lacros profile.
-  AddDummyLacrosDeskProfiles(3);
-
-  const uint64_t lacros_profile_id1 = GetDummyLacrosDeskProfileId(0);
-  const uint64_t lacros_profile_id2 = GetDummyLacrosDeskProfileId(1);
-  const uint64_t lacros_profile_id3 = GetDummyLacrosDeskProfileId(2);
-
-  GetDeskProfilesTestDelegate().SetPrimaryProfileByProfileId(
-      lacros_profile_id1);
-
-  NewDesk();
-  NewDesk();
-
-  // Assign different lacros profiles to all three desks.
-  auto* controller = DesksController::Get();
-  auto* desk1 = controller->GetDeskAtIndex(0);
-  auto* desk2 = controller->GetDeskAtIndex(1);
-  auto* desk3 = controller->GetDeskAtIndex(2);
-  desk1->SetLacrosProfileId(lacros_profile_id1);
-  desk2->SetLacrosProfileId(lacros_profile_id2);
-  desk3->SetLacrosProfileId(lacros_profile_id3);
-
-  EXPECT_EQ(desk1->lacros_profile_id(), lacros_profile_id1);
-  EXPECT_EQ(desk2->lacros_profile_id(), lacros_profile_id2);
-  EXPECT_EQ(desk3->lacros_profile_id(), lacros_profile_id3);
-
-  // Remove the last profile. We now expect the desk to be updated to the
-  // default profile (lacros_profile_id1).
-  GetDeskProfilesTestDelegate().RemoveTestProfile(lacros_profile_id3);
-
-  EXPECT_EQ(desk1->lacros_profile_id(), lacros_profile_id1);
-  EXPECT_EQ(desk2->lacros_profile_id(), lacros_profile_id2);
-  EXPECT_EQ(desk3->lacros_profile_id(), lacros_profile_id1);
-}
-
-TEST_F(DeskProfilesTest, SelectProfile) {
-  AddDummyLacrosDeskProfiles(2);
-
-  base::HistogramTester histogram_tester;
-  auto* desk_bar_controller = DesksController::Get()->desk_bar_controller();
-
-  NewDesk();
-  auto* desk1 = DesksController::Get()->GetDeskAtIndex(0);
-  auto* desk2 = DesksController::Get()->GetDeskAtIndex(1);
-
-  // By default, neither desk has a lacros profile ID assigned.
-  EXPECT_EQ(0u, desk1->lacros_profile_id());
-  EXPECT_EQ(0u, desk2->lacros_profile_id());
-
-  desk_bar_controller->OpenDeskBar(Shell::Get()->GetPrimaryRootWindow());
-  auto* desk_bar_view =
-      desk_bar_controller->GetDeskBarView(Shell::Get()->GetPrimaryRootWindow());
-  views::test::RunScheduledLayout(desk_bar_view);
-  ASSERT_EQ(2u, desk_bar_view->mini_views().size());
-
-  // Assign a profile to the second desk using the desk profile button.
-  {
-    DeskProfilesButton* desk_profile_button =
-        DesksTestApi::GetDeskProfileButton(desk_bar_view->mini_views()[1]);
-    ASSERT_TRUE(desk_profile_button);
-
-    LeftClickOn(desk_profile_button);
-    DeskActionContextMenu* menu = desk_profile_button->menu();
-    ASSERT_TRUE(menu);
-
-    // Get the menu item for the seecond profile and click it.
-    views::MenuItemView* menu_item = DesksTestApi::GetDeskActionContextMenuItem(
-        menu, DeskActionContextMenu::kDynamicProfileStart + 1);
-    ASSERT_TRUE(menu_item);
-    LeftClickOn(menu_item);
-
-    // Verify that the profile has indeed been set on desk 2.
-    EXPECT_EQ(desk2->lacros_profile_id(), GetDummyLacrosDeskProfileId(1));
-  }
-
-  // Assign a profile to the second desk using the desk action context menu.
-  {
-    DeskActionContextMenu* menu = DesksTestApi::GetContextMenuForDesk(
-        DeskBarViewBase::Type::kDeskButton, 1);
-    ASSERT_TRUE(menu);
-
-    // Get the menu item for the first profile and click it.
-    views::MenuItemView* menu_item = DesksTestApi::GetDeskActionContextMenuItem(
-        menu, DeskActionContextMenu::kDynamicProfileStart);
-    ASSERT_TRUE(menu_item);
-    LeftClickOn(menu_item);
-
-    // Verify that the profile has been updated on desk 2.
-    EXPECT_EQ(desk2->lacros_profile_id(), GetDummyLacrosDeskProfileId(0));
-  }
-}
-
 // TODO(afakhry): Add more tests:
 // - Always on top windows are not tracked by any desk.
 // - Reusing containers when desks are removed and created.
@@ -11906,15 +11749,13 @@
     DeskBarTest,
     testing::Combine(testing::Bool(),  // use touch gestures
                      testing::Bool(),  // use 16 desks
-                     testing::Bool(),  // use desk profiles
                      testing::Values(DeskBarViewBase::Type::kDeskButton,
                                      DeskBarViewBase::Type::kOverview)),
     [](const testing::TestParamInfo<DeskBarTest::ParamType>& info) {
       DesksTestParams params;
-      bool use_desk_profiles;
       DeskBarViewBase::Type bar_type;
-      std::tie(params.use_touch_gestures, params.use_16_desks,
-               use_desk_profiles, bar_type) = info.param;
+      std::tie(params.use_touch_gestures, params.use_16_desks, bar_type) =
+          info.param;
       std::string result = GetTestSuffix(params);
       std::string bar_type_str;
       switch (bar_type) {
@@ -11926,11 +11767,7 @@
           break;
       }
 
-      std::string desk_profiles_str =
-          use_desk_profiles ? "DeskProfiles" : "NoDeskProfiles";
-      return base::StringPrintf("%s_%s_%s", result.c_str(),
-                                bar_type_str.c_str(),
-                                desk_profiles_str.c_str());
+      return base::StringPrintf("%s_%s", result.c_str(), bar_type_str.c_str());
     });
 
 INSTANTIATE_TEST_SUITE_P(
diff --git a/ash/wm/desks/desks_util.cc b/ash/wm/desks/desks_util.cc
index afa453b5..42b99667 100644
--- a/ash/wm/desks/desks_util.cc
+++ b/ash/wm/desks/desks_util.cc
@@ -157,15 +157,6 @@
   return desk_container && desk_container->GetId() == desk->container_id();
 }
 
-std::optional<uint64_t> GetActiveDeskLacrosProfileId() {
-  std::optional<uint64_t> id;
-  if (auto* desk_controller = DesksController::Get();
-      desk_controller && chromeos::features::IsDeskProfilesEnabled()) {
-    id = desk_controller->active_desk()->lacros_profile_id();
-  }
-  return id;
-}
-
 aura::Window* GetDeskContainerForContext(aura::Window* context) {
   DCHECK(context);
 
diff --git a/ash/wm/desks/desks_util.h b/ash/wm/desks/desks_util.h
index 2724a7f..d0f10c8a 100644
--- a/ash/wm/desks/desks_util.h
+++ b/ash/wm/desks/desks_util.h
@@ -61,10 +61,6 @@
 
 ASH_EXPORT bool BelongsToDesk(aura::Window* window, const Desk* desk);
 
-// Returns active desk's associated lacros profile ID when Desk Profiles feature
-// is enabled; returns null otherwise.
-ASH_EXPORT std::optional<uint64_t> GetActiveDeskLacrosProfileId();
-
 // If `context` is a descendent window of a desk container, return that desk
 // container, otherwise return nullptr. Note that this will return nullptr if
 // `context` is a descendent of the float container, even if it is associated
diff --git a/ash/wm/overview/overview_grid.cc b/ash/wm/overview/overview_grid.cc
index 3b44f97..1a1a13f0 100644
--- a/ash/wm/overview/overview_grid.cc
+++ b/ash/wm/overview/overview_grid.cc
@@ -1917,17 +1917,6 @@
 
   auto* target_desk = desks_controller->desks().back().get();
 
-  // When creating a new desk by by dragging and dropping a lacros browser
-  // window to new desk button, set the desk's default profile based on the
-  // profile lacros window is logged into.
-  const auto windows = dragged_item->GetWindows();
-  if (chromeos::features::IsDeskProfilesEnabled() && windows.size() == 1) {
-    if (auto lacros_profile_id = windows[0]->GetProperty(kLacrosProfileId);
-        lacros_profile_id != 0) {
-      target_desk->SetLacrosProfileId(lacros_profile_id);
-    }
-  }
-
   return desks_controller->MoveWindowFromActiveDeskTo(
       dragged_item->GetWindow(), target_desk, root_window_,
       DesksMoveWindowFromActiveDeskSource::kDragAndDrop);
diff --git a/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc b/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc
index 6c0ea0c8..c9162e4 100644
--- a/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc
+++ b/base/allocator/partition_allocator/src/partition_alloc/address_pool_manager.cc
@@ -48,7 +48,7 @@
   // Callers rely on the pages being zero-initialized when recommitting them.
   // |DecommitSystemPages| doesn't guarantee this on all operating systems, in
   // particular on macOS, but |DecommitAndZeroSystemPages| does.
-  DecommitAndZeroSystemPages(address, size, kPageTag);
+  PA_CHECK(DecommitAndZeroSystemPages(address, size, kPageTag));
 }
 
 }  // namespace
diff --git a/base/files/drive_info_unittest.cc b/base/files/drive_info_unittest.cc
index b3b092c..574932f 100644
--- a/base/files/drive_info_unittest.cc
+++ b/base/files/drive_info_unittest.cc
@@ -13,6 +13,8 @@
 
 namespace {
 
+using ::testing::Optional;
+
 void TestForReasonableDriveInfo(const std::optional<DriveInfo>& info) {
   ASSERT_TRUE(info.has_value());
 
@@ -25,7 +27,7 @@
   EXPECT_TRUE(info->is_removable.has_value());
 
   // Expect more than 10MB for the media size.
-  EXPECT_GE(info->size_bytes.value(), 10'000'000);
+  EXPECT_THAT(info->size_bytes, Optional(testing::Ge(10'000'000)));
 #endif
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC)
@@ -35,15 +37,15 @@
 
 #if BUILDFLAG(IS_MAC)
   // Nothing should be CoreStorage any more on the Mac.
-  EXPECT_FALSE(info->is_core_storage.value());
+  EXPECT_THAT(info->is_core_storage, Optional(false));
 
   // Everything should be APFS nowadays.
-  EXPECT_TRUE(info->is_apfs.value());
+  EXPECT_THAT(info->is_apfs, Optional(true));
 
   // This test should not encounter a read-only drive.
-  EXPECT_TRUE(info->is_writable.value());
+  EXPECT_THAT(info->is_writable, Optional(true));
 
-  EXPECT_THAT(info->bsd_name.value(), testing::StartsWith("disk"));
+  EXPECT_THAT(info->bsd_name, Optional(testing::StartsWith("disk")));
 #endif
 }
 
diff --git a/build/config/siso/android.star b/build/config/siso/android.star
index 5e7df809..240b6ed5 100644
--- a/build/config/siso/android.star
+++ b/build/config/siso/android.star
@@ -49,6 +49,9 @@
         gn_args = gn.args(ctx)
         if gn_args.get("android_static_analysis") == '"build_server"':
             remote_run_static_analysis = False
+        if gn_args.get("enable_kythe_annotations") == "true":
+            # Remote Kythe annotations isn't supported.
+            remote_run = False
 
     step_config["rules"].extend([
         # See also https://chromium.googlesource.com/chromium/src/build/+/HEAD/android/docs/java_toolchain.md
diff --git a/build/fuchsia/gen_build_defs.py b/build/fuchsia/gen_build_defs.py
index b67cbc1..02eaef7f 100755
--- a/build/fuchsia/gen_build_defs.py
+++ b/build/fuchsia/gen_build_defs.py
@@ -12,6 +12,7 @@
 import json
 import logging
 import os
+import subprocess
 import sys
 
 sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__),
@@ -82,6 +83,36 @@
   return [os.path.relpath(path, meta_root) for path in sdk_relative_paths]
 
 
+def _FindReadelfPath() -> str:
+  """Define the path of the readelf tool."""
+  if os.environ.get('FUCHSIA_READELF'):
+    return os.environ['FUCHSIA_READELF']
+  return os.path.join(DIR_SRC_ROOT, 'third_party', 'llvm-build',
+                      'Release+Asserts', 'bin', 'llvm-readelf')
+
+
+def GetGnuBuildId(elf_file: str, readelf_path: str) -> str:
+  """Extracts the GNU build ID from an ELF64 file.
+
+    Args:
+        elf_file: Path to input file.
+    Returns:
+        The build-id value has an hexadecimal string, or
+        an empty string on failure (e.g. not an ELF file,
+        or no .note.gnu.build-id section in it).
+    """
+  ret = subprocess.run([readelf_path, "-n", elf_file],
+                       text=True,
+                       capture_output=True)
+  if ret.returncode == 0:
+    for line in ret.stdout.splitlines():
+      _, prefix, build_id = line.partition("Build ID:")
+      if prefix:
+        return build_id.strip()
+
+  return ""
+
+
 def ConvertCommonFields(json):
   """Extracts fields from JSON manifest data which are used across all
   target types. Note that FIDL packages do their own processing."""
@@ -342,6 +373,113 @@
         buildfile.write(FormatGNTarget(target) + '\n\n')
 
 
+def PopulateBuildIdDirectory(toplevel_meta):
+  """Populate the SDK_ROOT/.build-id directory with symlinks.
+
+  Future versions of the IDK will no longer place debug symbols
+  in the top-level .build-id/ directory directly. Instead their
+  location is available by parsing the meta.json files of various
+  prebuilt atom types.
+
+  This function supports both the existing and future layout,
+  by only creating entries under SDK_ROOT/.build_id for
+  GNU build ID values that are not already listed here.
+
+  Note that this script is run as a DEPS hook and has no knowledge
+  of the current target_cpu value or Fuchsia API level, so symlinks
+  for all possible debug symbols will be created.
+  """
+  readelf_path = _FindReadelfPath()
+
+  # First, collect all debug symbols location from the manifest
+  # that are not already in the top-level .build-id directory.
+
+  # Map a Build ID hex value to the corresponding debug symbol file
+  # path, relative to the SDK root.
+  build_ids_map = {}
+
+  def probe_path(debug):
+    if debug and not debug.startswith(".build-id/"):
+      debug_path = os.path.join(SDK_ROOT, debug)
+      build_id = GetGnuBuildId(debug_path, readelf_path)
+      assert build_id, (
+          f"Could not extract GNU Build ID from debug symbol path: {debug_path}"
+      )
+      build_ids_map[build_id] = debug
+
+  def parse_sysroot(meta_json):
+    # Debug symbols for the HEAD API level, if available, are in
+    # binaries.$ARCH.debug_libs
+    for arch, values in meta_json.get("binaries", {}).items():
+      for debug in values.get("debug_libs", []):
+        probe_path(debug)
+
+    # Debug symbols for specific (ARCH, API_LEVEL) are in
+    # variants[$INDEX].values.debug_libs, where
+    # variants[$INDEX].constraints.{arch, api_level} match
+    # (ARCH, API_LEVEL).
+    for variant in meta_json.get("variants", []):
+      for debug in variant["values"].get("debug_libs", []):
+        probe_path(debug)
+
+  def parse_cc_prebuilt_library(meta_json):
+    # Only prebuilt shared libraries have Build ID values.
+    if meta_json["format"] != "shared":
+      return
+
+    # Debug symbols for HEAD API level  are in binaries.$ARCH.debug
+    for arch, values in meta_json.get("binaries", {}).items():
+      probe_path(values.get("debug"))
+
+    # Debug symbols for specific (ARCH, API_LEVEL) are in
+    # variants[$INDEX].values.debug, where
+    # variants[$INDEX].constraints.{arch, api_leve} match
+    # (ARCH, API_LEVEL)
+    for variant in meta_json.get("variants", []):
+      debug = variant["values"].get("debug")
+      probe_path(debug)
+
+  def parse_loadable_module(meta_json):
+    # https://issues.fuchsia.dev/407488427: There are currently
+    # no debug symbols for loadable_module atoms. Implement
+    # the function properly once this bug is fixed.
+    pass
+
+  type_to_parser = {
+      "sysroot": parse_sysroot,
+      "cc_prebuilt_library": parse_cc_prebuilt_library,
+      "loadable_module": parse_loadable_module,
+  }
+
+  for part in toplevel_meta["parts"]:
+    meta_path = os.path.join(SDK_ROOT, part["meta"])
+    parser = type_to_parser.get(part["type"])
+    if parser:
+      with open(meta_path, "rb") as f:
+        meta_json = json.load(f)
+      parser(meta_json)
+
+  # Populate the FUCHSIA_SDK_ROOT/.build-id/ directory with hard-links to the
+  # corresponding debug symbols
+  build_id_dir = os.path.join(SDK_ROOT, ".build-id")
+  for build_id, debug_file in build_ids_map.items():
+    link_path = os.path.join(build_id_dir, build_id[0:2],
+                             f"{build_id[2:]}.debug")
+
+    # https://issues.chromium.org/issues/407890258
+    # Remove symlinks in favor of hard-links to avoid incremental flakiness.
+    if os.path.islink(link_path):
+      os.remove(link_path)
+
+    if os.path.exists(link_path):
+      continue  # File already exists, ignore.
+
+    link_target = os.path.join(SDK_ROOT, debug_file)
+    link_dir = os.path.dirname(link_path)
+    os.makedirs(link_dir, exist_ok=True)
+    os.link(link_target, link_path)
+
+
 def ProcessSdkManifest():
   toplevel_meta = json.load(
       open(os.path.join(SDK_ROOT, 'meta', 'manifest.json')))
@@ -350,9 +488,10 @@
     meta_path = os.path.join(SDK_ROOT, part['meta'])
     ConvertMeta(meta_path)
 
+  PopulateBuildIdDirectory(toplevel_meta)
+
 
 def main():
-
   # Exit if there's no Fuchsia support for this platform.
   try:
     get_host_os()
diff --git a/buildtools/deps_revisions.gni b/buildtools/deps_revisions.gni
index 55d6b9f..43b36ef 100644
--- a/buildtools/deps_revisions.gni
+++ b/buildtools/deps_revisions.gni
@@ -5,5 +5,5 @@
 declare_args() {
   # Used to cause full rebuilds on libc++ rolls. This should be kept in sync
   # with the libcxx_revision var in //DEPS.
-  libcxx_revision = "4e8b01e3c1c22a50f8eb5290f6a65859d5886205"
+  libcxx_revision = "c79b6718f6f27bd3576c719ee2989767e8fac5ad"
 }
diff --git a/cc/layers/picture_layer_impl.cc b/cc/layers/picture_layer_impl.cc
index 72e21983..10c9fec 100644
--- a/cc/layers/picture_layer_impl.cc
+++ b/cc/layers/picture_layer_impl.cc
@@ -496,8 +496,7 @@
               shared_quad_state, offset_geometry_rect,
               offset_visible_geometry_rect, needs_blending,
               draw_info.resource_id_for_export(), texture_rect,
-              draw_info.resource_size(), /*is_premultiplied=*/true,
-              nearest_neighbor_,
+              draw_info.resource_size(), nearest_neighbor_,
               !layer_tree_impl()->settings().enable_edge_anti_aliasing);
           ValidateQuadResources(quad);
           has_draw_quad = true;
diff --git a/cc/layers/render_surface_unittest.cc b/cc/layers/render_surface_unittest.cc
index ddf1f36..d10cd8d9 100644
--- a/cc/layers/render_surface_unittest.cc
+++ b/cc/layers/render_surface_unittest.cc
@@ -71,7 +71,7 @@
       auto* quad = render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
       quad->SetNew(shared_quad_state, rect, rect, needs_blending,
                    viz::kInvalidResourceId, gfx::RectF(rect), bounds(), false,
-                   false, false);
+                   false);
     }
   }
 
diff --git a/cc/layers/tile_display_layer_impl.cc b/cc/layers/tile_display_layer_impl.cc
index 73038ad..b6e96b2 100644
--- a/cc/layers/tile_display_layer_impl.cc
+++ b/cc/layers/tile_display_layer_impl.cc
@@ -36,10 +36,8 @@
 
 TileDisplayLayerImpl::TileResource::TileResource(
     const viz::TransferableResource& resource,
-    bool is_premultiplied,
     bool is_checkered)
     : resource(resource),
-      is_premultiplied(is_premultiplied),
       is_checkered(is_checkered) {}
 
 TileDisplayLayerImpl::TileResource::TileResource(const TileResource&) = default;
@@ -275,7 +273,7 @@
                      offset_visible_geometry_rect, needs_blending,
                      resource->resource.id, texture_rect,
                      iter.CurrentTiling()->tile_size(),
-                     resource->is_premultiplied, /*nearest_neighbor=*/false,
+                     /*nearest_neighbor=*/false,
                      /*enable_edge_aa=*/false);
         used_resources.push_back(resource->resource);
         has_draw_quad = true;
@@ -306,8 +304,6 @@
   shared_quad_state->quad_to_target_transform.Translate(-quad_offset);
   shared_quad_state->quad_layer_rect.Offset(quad_offset);
   shared_quad_state->visible_quad_layer_rect.Offset(quad_offset);
-
-  client_->DidAppendQuadsWithResources(used_resources);
 }
 
 void TileDisplayLayerImpl::GetContentsResourceId(
@@ -337,7 +333,6 @@
 
   std::vector<viz::TransferableResource> used_resources;
   used_resources.push_back(iter->resource()->resource);
-  client_->DidAppendQuadsWithResources(used_resources);
 }
 
 gfx::Rect TileDisplayLayerImpl::GetDamageRect() const {
diff --git a/cc/layers/tile_display_layer_impl.h b/cc/layers/tile_display_layer_impl.h
index 833ae2f6..938eef8 100644
--- a/cc/layers/tile_display_layer_impl.h
+++ b/cc/layers/tile_display_layer_impl.h
@@ -34,8 +34,6 @@
   class CC_EXPORT Client {
    public:
     virtual ~Client() = default;
-    virtual void DidAppendQuadsWithResources(
-        const std::vector<viz::TransferableResource>& resource) = 0;
 
     // To notify client to Import or Discard a TransferableResource.
     virtual void ImportResource(viz::TransferableResource resource) = 0;
@@ -46,14 +44,12 @@
 
   struct CC_EXPORT TileResource {
     TileResource(const viz::TransferableResource& resource,
-                 bool is_premultiplied,
                  bool is_checkered);
     TileResource(const TileResource&);
     TileResource& operator=(const TileResource&);
     ~TileResource();
 
     viz::TransferableResource resource;
-    bool is_premultiplied;
     bool is_checkered;
   };
 
diff --git a/cc/mojo_embedder/viz_layer_context.cc b/cc/mojo_embedder/viz_layer_context.cc
index 4321a5f..18bab5f 100644
--- a/cc/mojo_embedder/viz_layer_context.cc
+++ b/cc/mojo_embedder/viz_layer_context.cc
@@ -401,8 +401,6 @@
   auto wire = viz::mojom::TileResource::New();
   wire->resource = resources[0];
 
-  // Tile resources are always premultiplied.
-  wire->is_premultiplied = true;
   wire->is_checkered = draw_info.is_checker_imaged();
   return wire;
 }
diff --git a/cc/test/render_pass_test_utils.cc b/cc/test/render_pass_test_utils.cc
index b7984ff5..53d8bfe 100644
--- a/cc/test/render_pass_test_utils.cc
+++ b/cc/test/render_pass_test_utils.cc
@@ -275,7 +275,7 @@
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   scaled_tile_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
                            resource2, gfx::RectF(0, 0, 50, 50),
-                           gfx::Size(50, 50), false, false, false);
+                           gfx::Size(50, 50), false, false);
 
   viz::SharedQuadState* transformed_state =
       to_pass->CreateAndAppendSharedQuadState();
@@ -288,7 +288,7 @@
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   transformed_tile_quad->SetNew(
       transformed_state, rect, visible_rect, needs_blending, resource3,
-      gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false, false);
+      gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false);
 
   viz::SharedQuadState* shared_state2 =
       to_pass->CreateAndAppendSharedQuadState();
@@ -301,7 +301,7 @@
   auto* tile_quad = to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   tile_quad->SetNew(shared_state2, rect, visible_rect, needs_blending,
                     resource4, gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100),
-                    false, false, false);
+                    false, false);
 
   return {resource1, resource2, resource3, resource4,
           resource5, resource6, resource8};
@@ -437,7 +437,7 @@
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   scaled_tile_quad->SetNew(shared_state, rect, visible_rect, needs_blending,
                            mapped_resource2, gfx::RectF(0, 0, 50, 50),
-                           gfx::Size(50, 50), false, false, false);
+                           gfx::Size(50, 50), false, false);
 
   viz::SharedQuadState* transformed_state =
       to_pass->CreateAndAppendSharedQuadState();
@@ -450,7 +450,7 @@
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   transformed_tile_quad->SetNew(
       transformed_state, rect, visible_rect, needs_blending, mapped_resource3,
-      gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false, false);
+      gfx::RectF(0, 0, 100, 100), gfx::Size(100, 100), false, false);
 
   viz::SharedQuadState* shared_state2 =
       to_pass->CreateAndAppendSharedQuadState();
@@ -464,7 +464,7 @@
       to_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
   tile_quad->SetNew(shared_state2, rect, visible_rect, needs_blending,
                     mapped_resource4, gfx::RectF(0, 0, 100, 100),
-                    gfx::Size(100, 100), false, false, false);
+                    gfx::Size(100, 100), false, false);
 }
 
 std::unique_ptr<viz::AggregatedRenderPass> CopyToAggregatedRenderPass(
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc
index 7e6008b..661c197d 100644
--- a/cc/trees/layer_tree_host_impl_unittest.cc
+++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -10714,10 +10714,9 @@
 
     auto* test_blending_draw_quad =
         render_pass->CreateAndAppendDrawQuad<viz::TileDrawQuad>();
-    test_blending_draw_quad->SetNew(shared_quad_state, quad_rect_,
-                                    visible_quad_rect, needs_blending,
-                                    resource_id_, gfx::RectF(0, 0, 1, 1),
-                                    gfx::Size(1, 1), false, false, false);
+    test_blending_draw_quad->SetNew(
+        shared_quad_state, quad_rect_, visible_quad_rect, needs_blending,
+        resource_id_, gfx::RectF(0, 0, 1, 1), gfx::Size(1, 1), false, false);
 
     EXPECT_EQ(blend_, test_blending_draw_quad->ShouldDrawWithBlending());
     EXPECT_EQ(has_render_surface_,
diff --git a/chrome/VERSION b/chrome/VERSION
index 1ba4ec9..3fdb7e3 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=137
 MINOR=0
-BUILD=7115
+BUILD=7116
 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 295790ef..2f9e6d0b 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -3099,6 +3099,7 @@
     "java/src/org/chromium/chrome/browser/customtabs/CustomTabAuthUrlHeuristics.java",
     "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java",
     "java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java",
+    "java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java",
     "java/src/org/chromium/chrome/browser/customtabs/features/TabInteractionRecorder.java",
     "java/src/org/chromium/chrome/browser/datareduction/DataSaverOSSetting.java",
     "java/src/org/chromium/chrome/browser/device_dialog/ChromeBluetoothChooserAndroidDelegate.java",
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabThumbnailViewRenderTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabThumbnailViewRenderTest.java
index 13bca0c..a0398ed 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabThumbnailViewRenderTest.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabThumbnailViewRenderTest.java
@@ -62,7 +62,7 @@
     public final ChromeRenderTestRule mRenderTestRule =
             ChromeRenderTestRule.Builder.withPublicCorpus()
                     .setBugComponent(RenderTestRule.Component.UI_BROWSER_MOBILE_TAB_SWITCHER_GRID)
-                    .setRevision(6)
+                    .setRevision(7)
                     .build();
 
     @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
index a062b7ca..1152bbd0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/DefaultCustomTabIntentHandlingStrategy.java
@@ -6,8 +6,6 @@
 
 import android.text.TextUtils;
 
-import androidx.browser.trusted.LaunchHandlerClientMode;
-
 import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider;
 import org.chromium.chrome.browser.customtabs.CustomTabAuthUrlHeuristics;
 import org.chromium.chrome.browser.customtabs.CustomTabObserver;
@@ -50,6 +48,10 @@
 
         CustomTabAuthUrlHeuristics.recordUrlParamsHistogram(intentDataProvider.getUrlToLoad());
         CustomTabAuthUrlHeuristics.recordRedirectUriSchemeHistogram(intentDataProvider);
+
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_WEB_APP_LAUNCH_HANDLER)) {
+            handleLaunch(intentDataProvider, true);
+        }
     }
 
     // The hidden tab case needs a bit of special treatment.
@@ -82,23 +84,22 @@
         mNavigationController.navigate(params, intentDataProvider.getIntent());
     }
 
-    private WebAppLaunchParams handleLaunch(BrowserServicesIntentDataProvider intentDataProvider) {
-        String packageName = intentDataProvider.getClientPackageName();
-        return WebAppLaunchHandler.getLaunchParams(
-                LaunchHandlerClientMode.NAVIGATE_EXISTING,
-                intentDataProvider.getUrlToLoad(),
-                packageName);
-    }
+    private void handleLaunch(
+            BrowserServicesIntentDataProvider intentDataProvider, boolean isInitialIntent) {
+        WebAppLaunchHandler launchHandler =
+                new WebAppLaunchHandler(
+                        intentDataProvider.getLaunchHandlerClientMode(),
+                        intentDataProvider.getUrlToLoad(),
+                        intentDataProvider.getClientPackageName());
 
-    @Override
-    public void handleNewIntent(BrowserServicesIntentDataProvider intentDataProvider) {
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_WEB_APP_LAUNCH_HANDLER)) {
-            WebAppLaunchParams launchParams = handleLaunch(intentDataProvider);
-            if (!launchParams.startNewNavigation) {
-                return;
-            }
+        if (launchHandler.getStartNewNavigation() && !isInitialIntent) {
+            loadUrl(intentDataProvider);
         }
 
+        launchHandler.notifyLaunchQueue(mTabProvider.getTab().getWebContents());
+    }
+
+    private void loadUrl(BrowserServicesIntentDataProvider intentDataProvider) {
         String url = intentDataProvider.getUrlToLoad();
         if (TextUtils.isEmpty(url)) return;
         LoadUrlParams params = new LoadUrlParams(url);
@@ -113,4 +114,13 @@
 
         mNavigationController.navigate(params, intentDataProvider.getIntent());
     }
+
+    @Override
+    public void handleNewIntent(BrowserServicesIntentDataProvider intentDataProvider) {
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_WEB_APP_LAUNCH_HANDLER)) {
+            handleLaunch(intentDataProvider, false);
+        } else {
+            loadUrl(intentDataProvider);
+        }
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
index 49b5b45c..546b5750 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandler.java
@@ -10,16 +10,26 @@
 
 import androidx.browser.trusted.LaunchHandlerClientMode.ClientMode;
 
+import org.jni_zero.JNINamespace;
+import org.jni_zero.JniType;
+import org.jni_zero.NativeMethods;
+
+import org.chromium.content_public.browser.WebContents;
+
 import java.util.Arrays;
 
 /**
  * Manages web application launch configurations based on client mode. Provides methods to process
- * client mode and generate launch parameters.
+ * client mode and work with launch queue.
  */
+@JNINamespace("webapps")
 public class WebAppLaunchHandler {
 
     public static final @ClientMode int DEFAULT_CLIENT_MODE = NAVIGATE_EXISTING;
 
+    /** The LaunchParams value to be sent to a web app launch queue on app launch. */
+    private final WebAppLaunchParams mLaunchParams;
+
     /**
      * Retrieves the ClientMode enum value from a given AndroidX enum. Defaults to
      * DEFAULT_CLIENT_MODE if the value is invalid or AUTO.
@@ -35,6 +45,29 @@
         }
     }
 
+    public WebAppLaunchHandler(@ClientMode int clientMode, String targetUrl, String packageName) {
+        mLaunchParams = getLaunchParams(clientMode, targetUrl, packageName);
+    }
+
+    /** Returns whether this launch triggers a navigation */
+    public boolean getStartNewNavigation() {
+        return mLaunchParams.startNewNavigation;
+    }
+
+    /**
+     * Initiates the launch process for a web application tab notifying a launch queue.
+     *
+     * @param webContents Web contents object of the tab is being launched.
+     */
+    public void notifyLaunchQueue(WebContents webContents) {
+        WebAppLaunchHandlerJni.get()
+                .notifyLaunchQueue(
+                        webContents,
+                        mLaunchParams.startNewNavigation,
+                        mLaunchParams.targetUrl,
+                        mLaunchParams.packageName);
+    }
+
     /**
      * Generates WebAppLaunchParams based on the AndroidX representation of the client mode.
      *
@@ -43,7 +76,7 @@
      * @param packageName Android package name of the web app is being launched.
      * @return The generated WebAppLaunchParams object.
      */
-    public static WebAppLaunchParams getLaunchParams(
+    private static WebAppLaunchParams getLaunchParams(
             @ClientMode int clientModeParam, String targetUrl, String packageName) {
         @ClientMode int clientMode = getClientMode(clientModeParam);
 
@@ -51,5 +84,16 @@
         return new WebAppLaunchParams(startedNewNavigation, targetUrl, packageName);
     }
 
-    private WebAppLaunchHandler() {}
+    /**
+     * Takes the WebContents object of the tab that is being launched and notifies the launch queue
+     * with this object and associated launch parameters.
+     */
+    @NativeMethods
+    public interface Natives {
+        void notifyLaunchQueue(
+                @JniType("content::WebContents*") WebContents webContents,
+                @JniType("bool") boolean startNewNavigation,
+                @JniType("std::string") String startUrl,
+                @JniType("std::string") String packageName);
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
index b5f164e..bac8d72 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityUrlLoadingTest.java
@@ -21,6 +21,8 @@
 import android.content.Intent;
 import android.net.Uri;
 
+import androidx.browser.trusted.LaunchHandlerClientMode;
+
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -89,12 +91,15 @@
     @Mock WebContentsFactory.Natives mWebContentsFactoryJni;
     @Mock PreloadingDataBridge.Natives mPreloadingDataBridgeMock;
 
+    @Mock WebAppLaunchHandler.Natives mWebAppLaunchHandlerJniMock;
+
     @Before
     public void setUp() {
         UrlUtilitiesJni.setInstanceForTesting(mUrlUtilitiesJniMock);
         CustomTabAuthUrlHeuristicsJni.setInstanceForTesting(mCustomTabAuthUrlHeuristicsJniMock);
         WebContentsFactoryJni.setInstanceForTesting(mWebContentsFactoryJni);
         PreloadingDataBridgeJni.setInstanceForTesting(mPreloadingDataBridgeMock);
+        WebAppLaunchHandlerJni.setInstanceForTesting(mWebAppLaunchHandlerJniMock);
 
         when(env.profileProvider.getOriginalProfile()).thenReturn(mProfile);
         when(env.profileProvider.getOffTheRecordProfile(eq(true))).thenReturn(mIncognitoProfile);
@@ -202,13 +207,106 @@
         verify(env.tabFromFactory).loadUrl(argThat(params -> OTHER_URL.equals(params.getUrl())));
     }
 
-    private CustomTabIntentDataProvider createDataProviderForNewIntent(String url) {
+    private void checkLaunchHandler(
+            CustomTabIntentDataProvider intentDataProvider,
+            int expectedLoadUrlNumber,
+            boolean expectedStartNewNavigation) {
+        mIntentHandler.onNewIntent(intentDataProvider);
+        verify(env.tabFromFactory, times(expectedLoadUrlNumber))
+                .loadUrl(argThat(params -> OTHER_URL.equals(params.getUrl())));
+        verify(mWebAppLaunchHandlerJniMock, times(1))
+                .notifyLaunchQueue(any(), eq(true), eq(INITIAL_URL), eq(null));
+        verify(mWebAppLaunchHandlerJniMock, times(1))
+                .notifyLaunchQueue(any(), eq(expectedStartNewNavigation), eq(OTHER_URL), eq(null));
+    }
+
+    @Test
+    public void navigateExistingClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider =
+                createDataProviderForNewIntent(
+                        OTHER_URL, LaunchHandlerClientMode.NAVIGATE_EXISTING);
+
+        checkLaunchHandler(intentDataProvider, 1, true);
+    }
+
+    @Test
+    public void focusExistingClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider =
+                createDataProviderForNewIntent(OTHER_URL, LaunchHandlerClientMode.FOCUS_EXISTING);
+
+        checkLaunchHandler(intentDataProvider, 0, false);
+    }
+
+    @Test
+    public void autoClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider =
+                createDataProviderForNewIntent(OTHER_URL, LaunchHandlerClientMode.AUTO);
+
+        // The user agent(browser) decides what works best for the platform. Currently it's
+        // navigate-existing.
+        checkLaunchHandler(intentDataProvider, 1, true);
+    }
+
+    @Test
+    public void wrongClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider =
+                createDataProviderForNewIntent(OTHER_URL, 98);
+
+        // Fallback to auto mode as described in the specification.
+        checkLaunchHandler(intentDataProvider, 1, true);
+    }
+
+    @Test
+    public void navigateNewClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider =
+                createDataProviderForNewIntent(OTHER_URL, LaunchHandlerClientMode.NAVIGATE_NEW);
+
+        // Treated by IntentHandler as a wrong mode because this mode should be handled earlier by
+        // LaunchIntentDispatcher because it require launching of a new task.
+        checkLaunchHandler(intentDataProvider, 1, true);
+    }
+
+    @Test
+    public void noClientMode() {
+        mTabController.setUpInitialTab(null);
+        mTabController.finishNativeInitialization();
+        clearInvocations(env.tabFromFactory);
+        CustomTabIntentDataProvider intentDataProvider = createDataProviderForNewIntent(OTHER_URL);
+
+        // According to the specification if not specified, the default client_mode value is auto.
+        checkLaunchHandler(intentDataProvider, 1, true);
+    }
+
+    private CustomTabIntentDataProvider createDataProviderForNewIntent(
+            String url, @LaunchHandlerClientMode.ClientMode int clientMode) {
         CustomTabIntentDataProvider dataProvider = mock(CustomTabIntentDataProvider.class);
         when(dataProvider.getUrlToLoad()).thenReturn(url);
         when(dataProvider.getSession()).thenReturn(env.session);
         Intent intent = new Intent(Intent.ACTION_VIEW);
         intent.setData(Uri.parse(url));
+
+        when(dataProvider.getLaunchHandlerClientMode()).thenReturn(clientMode);
+
         when(dataProvider.getIntent()).thenReturn(intent);
         return dataProvider;
     }
+
+    private CustomTabIntentDataProvider createDataProviderForNewIntent(String url) {
+        return createDataProviderForNewIntent(url, LaunchHandlerClientMode.AUTO);
+    }
 }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
index 6f7aa0b..5033fd5 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/WebAppLaunchHandlerTest.java
@@ -41,29 +41,26 @@
     }
 
     @Test
-    public void getLaunchParams() {
+    public void getStartNewNavigation() {
         String url = JUnitTestGURLs.INITIAL_URL.getSpec();
         String packageName = null;
-        WebAppLaunchParams launchParams =
-                WebAppLaunchHandler.getLaunchParams(
+        WebAppLaunchHandler launchHandler =
+                new WebAppLaunchHandler(
                         LaunchHandlerClientMode.NAVIGATE_EXISTING, url, packageName);
-        Assert.assertTrue(launchParams.startNewNavigation);
+        Assert.assertTrue(launchHandler.getStartNewNavigation());
 
-        launchParams =
-                WebAppLaunchHandler.getLaunchParams(
-                        LaunchHandlerClientMode.FOCUS_EXISTING, url, packageName);
-        Assert.assertFalse(launchParams.startNewNavigation);
+        launchHandler =
+                new WebAppLaunchHandler(LaunchHandlerClientMode.FOCUS_EXISTING, url, packageName);
+        Assert.assertFalse(launchHandler.getStartNewNavigation());
 
-        launchParams =
-                WebAppLaunchHandler.getLaunchParams(
-                        LaunchHandlerClientMode.NAVIGATE_NEW, url, packageName);
-        Assert.assertTrue(launchParams.startNewNavigation);
+        launchHandler =
+                new WebAppLaunchHandler(LaunchHandlerClientMode.NAVIGATE_NEW, url, packageName);
+        Assert.assertTrue(launchHandler.getStartNewNavigation());
 
-        launchParams =
-                WebAppLaunchHandler.getLaunchParams(LaunchHandlerClientMode.AUTO, url, packageName);
-        Assert.assertTrue(launchParams.startNewNavigation);
+        launchHandler = new WebAppLaunchHandler(LaunchHandlerClientMode.AUTO, url, packageName);
+        Assert.assertTrue(launchHandler.getStartNewNavigation());
 
-        launchParams = WebAppLaunchHandler.getLaunchParams(65, url, packageName);
-        Assert.assertTrue(launchParams.startNewNavigation);
+        launchHandler = new WebAppLaunchHandler(65, url, packageName);
+        Assert.assertTrue(launchHandler.getStartNewNavigation());
     }
 }
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt
index ec52459..6bdb8cc 100644
--- a/chrome/android/profiles/arm.newest.txt
+++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-136.0.7082.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-arm-137.0.7113.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 75e9bf6..a1bdc50d 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-136.0.7082.0_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-137.0.7113.0_rc-r1-merged.afdo.bz2
diff --git a/chrome/app/chrome_crash_reporter_client.cc b/chrome/app/chrome_crash_reporter_client.cc
index 4f6ac73e..979fb74 100644
--- a/chrome/app/chrome_crash_reporter_client.cc
+++ b/chrome/app/chrome_crash_reporter_client.cc
@@ -41,8 +41,23 @@
 
 #if BUILDFLAG(IS_CHROMEOS)
 #include "ash/constants/ash_switches.h"
+#include "build/util/LASTCHANGE_commit_position.h"
 #endif
 
+namespace {
+
+constexpr const char* UpdaterVersion() {
+#if BUILDFLAG(IS_CHROMEOS) && CHROMIUM_COMMIT_POSITION_IS_MAIN
+  // Adds the revision number as a suffix to the version number if the chrome
+  // is built from the main branch.
+  return PRODUCT_VERSION "-r" CHROMIUM_COMMIT_POSITION_NUMBER;
+#else
+  return PRODUCT_VERSION;
+#endif
+}
+
+}  // namespace
+
 void ChromeCrashReporterClient::Create() {
   static base::NoDestructor<ChromeCrashReporterClient> crash_client;
   crash_reporter::SetCrashReporterClient(crash_client.get());
@@ -134,7 +149,7 @@
   NOTREACHED();
 #endif
 
-  product_info->version = PRODUCT_VERSION;
+  product_info->version = UpdaterVersion();
   product_info->channel =
       chrome::GetChannelName(chrome::WithExtendedStable(true));
 }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 3f6b3d6..417abba 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -14417,9 +14417,6 @@
       <message name="IDS_SYNC_NEEDS_VERIFICATION_BUBBLE_VIEW_TITLE" desc="Title in the sync error bubble view/notification for the case where sync needs to verify the user.">
         Sync needs to verify it's you
       </message>
-      <message name="IDS_SIGNIN_PAUSED_USER_MENU_VERIFY_MESSAGE" desc="This is the text of a card that means the user needs to sign back in to Chrome in order to continue saving and using data (like passwords or payment methods) in their Google Account. This is an error message that appears when the user's sign-in credential has expired; to fix the issue, the user needs to sign back in. The tone should be straightforward and motivating.">
-        To keep using the passwords and more in your Google Account, verify it's you
-      </message>
       <if expr="use_titlecase">
         <message name="IDS_SYNC_ERROR_USER_MENU_SIGNIN_BUTTON" desc="Button in the header of desktop user menu that prompts the user to sign in again to fix the out-of-date signin info error.">
           Sign In Again
diff --git a/chrome/app/generated_resources_grd/IDS_SIGNIN_PAUSED_USER_MENU_VERIFY_MESSAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_SIGNIN_PAUSED_USER_MENU_VERIFY_MESSAGE.png.sha1
deleted file mode 100644
index ea98095..0000000
--- a/chrome/app/generated_resources_grd/IDS_SIGNIN_PAUSED_USER_MENU_VERIFY_MESSAGE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-830644d1e47a1cbf3b22aeefe9efde35ec1161ec
\ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp
index cbe25ff08e..08caef6 100644
--- a/chrome/app/profiles_strings.grdp
+++ b/chrome/app/profiles_strings.grdp
@@ -121,12 +121,6 @@
         Verify it’s you
       </message>
     </if>
-  <message name="IDS_PROFILES_CREDIT_CARDS_LINK" desc="Text of the menu item leading to the list of saved credit cards.">
-    Payment methods
-  </message>
-  <message name="IDS_PROFILES_ADDRESSES_LINK" desc="Text of the menu item leading to the list of autofill addresses.">
-    Addresses and more
-  </message>
   <message name="IDS_PROFILE_MENU_SIGNIN_PROMO_DESCRIPTION" desc="Text for the sign-in promo in the profile menu when the used is signed out, describing the benefits of signing in.">
     Sign in to get your passwords and more on all your devices
   </message>
@@ -164,9 +158,6 @@
       other {Close this profile (# windows)}
       }
     </message>
-    <message name="IDS_PROFILE_MENU_ADD_NEW_PROFILE" desc="The text label of the add new profile item in the profile menu.">
-      Add new profile
-    </message>
     <message name="IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON" desc="Button in the profile menu to open sync settings when sync is on.">
       Sync is on
     </message>
@@ -196,9 +187,6 @@
       other {Close This Profile (# Windows)}
       }
     </message>
-    <message name="IDS_PROFILE_MENU_ADD_NEW_PROFILE" desc="The text label of the add new profile item in the profile menu.">
-      Add New Profile
-    </message>
     <message name="IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON" desc="Button in the profile menu to open sync settings when sync is on.">
       Sync Is On
     </message>
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_MENU_ADD_NEW_PROFILE.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_MENU_ADD_NEW_PROFILE.png.sha1
deleted file mode 100644
index b6a586b..0000000
--- a/chrome/app/profiles_strings_grdp/IDS_PROFILE_MENU_ADD_NEW_PROFILE.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-1a605be7c7ece954b03b2960433328284c751ab5
\ No newline at end of file
diff --git a/chrome/app/vector_icons/BUILD.gn b/chrome/app/vector_icons/BUILD.gn
index f8f9967..fe99987 100644
--- a/chrome/app/vector_icons/BUILD.gn
+++ b/chrome/app/vector_icons/BUILD.gn
@@ -177,7 +177,6 @@
     "settings_menu.icon",
     "sharing_hub_screenshot.icon",
     "side_panel.icon",
-    "sign_out.icon",
     "smartphone.icon",
     "smartphone_refresh.icon",
     "speaker.icon",
diff --git a/chrome/app/vector_icons/sign_out.icon b/chrome/app/vector_icons/sign_out.icon
deleted file mode 100644
index 521a8f5..0000000
--- a/chrome/app/vector_icons/sign_out.icon
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2018 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 10.09, 15.59,
-LINE_TO, 11.5, 17,
-R_LINE_TO, 5, -5,
-R_LINE_TO, -5, -5,
-R_LINE_TO, -1.41, 1.41,
-LINE_TO, 12.67, 11,
-H_LINE_TO, 3,
-R_V_LINE_TO, 2,
-R_H_LINE_TO, 9.67,
-R_LINE_TO, -2.58, 2.59,
-CLOSE,
-MOVE_TO, 19, 3,
-H_LINE_TO, 5,
-R_CUBIC_TO, -1.11, 0, -2, 0.9, -2, 2,
-R_V_LINE_TO, 4,
-R_H_LINE_TO, 2,
-V_LINE_TO, 5,
-R_H_LINE_TO, 14,
-R_V_LINE_TO, 14,
-H_LINE_TO, 5,
-R_V_LINE_TO, -4,
-H_LINE_TO, 3,
-R_V_LINE_TO, 4,
-R_CUBIC_TO, 0, 1.1, 0.89, 2, 2, 2,
-R_H_LINE_TO, 14,
-R_CUBIC_TO, 1.1, 0, 2, -0.9, 2, -2,
-V_LINE_TO, 5,
-R_CUBIC_TO, 0, -1.1, -0.9, -2, -2, -2,
-CLOSE
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index e2276abf..844ecd29 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -2883,6 +2883,7 @@
       "android/webapps/twa_launch_queue_delegate.h",
       "android/webapps/twa_launch_queue_tab_helper.cc",
       "android/webapps/twa_launch_queue_tab_helper.h",
+      "android/webapps/web_app_launch_handler.cc",
       "android/webapps/webapp_registry.cc",
       "android/webapps/webapp_registry.h",
       "auxiliary_search/auxiliary_search_provider.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index ccb0cc1..ff9cce7 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -10419,9 +10419,6 @@
          "SendTabToSelfIOSPushNotifications")},
 
 #if BUILDFLAG(IS_CHROMEOS)
-    {"desk-profiles", flag_descriptions::kDeskProfilesName,
-     flag_descriptions::kDeskProfilesDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(chromeos::features::kDeskProfiles)},
     {"enable-display-performance-mode",
      flag_descriptions::kEnableDisplayPerformanceModeName,
      flag_descriptions::kEnableDisplayPerformanceModeDescription, kOsCrOS,
@@ -11916,6 +11913,13 @@
      FEATURE_VALUE_TYPE(input::features::kInputOnViz)},
 #endif  // BUILDFLAG(IS_ANDROID)
 
+#if BUILDFLAG(IS_ANDROID)
+    {"aaudio-per-stream-device-selection",
+     flag_descriptions::kAAudioPerStreamDeviceSelectionName,
+     flag_descriptions::kAAudioPerStreamDeviceSelectionDescription, kOsAndroid,
+     FEATURE_VALUE_TYPE(features::kAAudioPerStreamDeviceSelection)}
+#endif  // BUILDFLAG(IS_ANDROID)
+
     // Add new entries above this line.
 
     // NOTE: Adding a new flag requires adding a corresponding entry to enum
diff --git a/chrome/browser/android/webapps/web_app_launch_handler.cc b/chrome/browser/android/webapps/web_app_launch_handler.cc
new file mode 100644
index 0000000..f3620087
--- /dev/null
+++ b/chrome/browser/android/webapps/web_app_launch_handler.cc
@@ -0,0 +1,19 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/android/jni_string.h"
+#include "content/public/browser/web_contents.h"
+
+// Must come after all headers that specialize FromJniType() / ToJniType().
+#include "chrome/android/chrome_jni_headers/WebAppLaunchHandler_jni.h"
+
+namespace webapps {
+static void JNI_WebAppLaunchHandler_NotifyLaunchQueue(
+    JNIEnv* env,
+    content::WebContents* web_contents,
+    bool start_new_navigation,
+    std::string& start_url,
+    std::string& package_name) {}
+
+}  // namespace webapps
diff --git a/chrome/browser/ash/DEPS b/chrome/browser/ash/DEPS
index dd220e0..dd93e44 100644
--- a/chrome/browser/ash/DEPS
+++ b/chrome/browser/ash/DEPS
@@ -11,4 +11,9 @@
   # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for
   # details.
   "-chrome",
+
+  # Browser abstraction for use by ChromeOS feature code. Will eventually be
+  # moved out of chrome/.
+  "+chrome/browser/ash/browser_delegate/browser_controller.h",
+  "+chrome/browser/ash/browser_delegate/browser_delegate.h",
 ]
diff --git a/chrome/browser/ash/browser_delegate/BUILD.gn b/chrome/browser/ash/browser_delegate/BUILD.gn
new file mode 100644
index 0000000..899ec51
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/BUILD.gn
@@ -0,0 +1,42 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+assert(is_chromeos)
+
+# To be moved out of //chrome.
+static_library("browser_delegate") {
+  sources = [
+    "browser_controller.cc",
+    "browser_controller.h",
+    "browser_delegate.h",
+  ]
+
+  public_deps = [
+    "//base",
+    "//components/sessions:session_id",
+  ]
+}
+
+static_library("impl") {
+  sources = [
+    "browser_controller_impl.cc",
+    "browser_controller_impl.h",
+    "browser_delegate_impl.cc",
+    "browser_delegate_impl.h",
+  ]
+
+  public_deps = [
+    ":browser_delegate",
+    "//base",
+    "//chrome/browser/ui:browser_list",
+  ]
+
+  deps = [
+    "//chrome/browser:browser_public_dependencies",
+    "//chrome/browser/profiles:profile",
+    "//chrome/browser/ui:browser_navigator_params_headers",
+    "//chromeos/ash/components/browser_context_helper",
+    "//components/sessions:session_id",
+  ]
+}
diff --git a/chrome/browser/ash/browser_delegate/DEPS b/chrome/browser/ash/browser_delegate/DEPS
new file mode 100644
index 0000000..3ee3e402
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+    "-chrome",
+    "+chrome/browser",
+]
diff --git a/chrome/browser/ash/browser_delegate/README.md b/chrome/browser/ash/browser_delegate/README.md
new file mode 100644
index 0000000..3f9cf860
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/README.md
@@ -0,0 +1,15 @@
+This is an evolving abstraction of the `Browser` (chrome/browser/ui/browser.h)
+and `BrowserList` (chrome/browser/ui/browser\_list.h) classes for use by
+ChromeOS feature code.
+
+The abstraction consists of two (C++) interfaces, `BrowserDelegate` &
+`BrowserController`, and their implementation. Think of `BrowserDelegate` as an
+abstract version of the existing `Browser` class and `BrowserController` as a
+supervising entity that primarily creates or finds `BrowserDelegate` objects for
+you.
+
+Development is incremental and in the first phase we prioritize making these
+classes the bottleneck for `Browser` access over them offering a clean API.
+
+We aim to eventually move these interfaces out of chrome/browser/ash/ into
+chromeos/.
diff --git a/chrome/browser/ash/browser_delegate/browser_controller.cc b/chrome/browser/ash/browser_delegate/browser_controller.cc
new file mode 100644
index 0000000..7f81dd9
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_controller.cc
@@ -0,0 +1,30 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/browser_delegate/browser_controller.h"
+
+#include "base/check.h"
+#include "base/check_op.h"
+
+namespace {
+ash::BrowserController* g_browser_controller = nullptr;
+}  // namespace
+
+namespace ash {
+
+BrowserController* BrowserController::GetInstance() {
+  return g_browser_controller;
+}
+
+BrowserController::BrowserController() {
+  CHECK(!g_browser_controller);
+  g_browser_controller = this;
+}
+
+BrowserController::~BrowserController() {
+  CHECK_EQ(g_browser_controller, this);
+  g_browser_controller = nullptr;
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/browser_delegate/browser_controller.h b/chrome/browser/ash/browser_delegate/browser_controller.h
new file mode 100644
index 0000000..2e1f07e
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_controller.h
@@ -0,0 +1,47 @@
+// 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_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_H_
+#define CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_H_
+
+#include <string_view>
+
+#include "base/containers/span.h"
+
+class GURL;
+
+namespace user_manager {
+class User;
+}  // namespace user_manager
+
+namespace ash {
+
+class BrowserDelegate;
+
+// BrowserController is a singleton created by
+// ChromeBrowserMainExtraPartsAsh::PostProfileInit. See also README.md.
+class BrowserController {
+ public:
+  static BrowserController* GetInstance();
+
+  // Makes a POST request in a new tab in the last active tabbed browser. If no
+  // such browser exists, a new one is created. Returns nullptr if the creation
+  // is not possible for the given arguments.
+  // This is needed by the Media app.
+  virtual BrowserDelegate* NewTabWithPostData(
+      user_manager::User& user,
+      const GURL& url,
+      base::span<const uint8_t> post_data,
+      std::string_view extra_headers) = 0;
+
+ protected:
+  BrowserController();
+  BrowserController(const BrowserController&) = delete;
+  BrowserController& operator=(const BrowserController&) = delete;
+  virtual ~BrowserController();
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_H_
diff --git a/chrome/browser/ash/browser_delegate/browser_controller_impl.cc b/chrome/browser/ash/browser_delegate/browser_controller_impl.cc
new file mode 100644
index 0000000..961fbea
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_controller_impl.cc
@@ -0,0 +1,83 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/browser_delegate/browser_controller_impl.h"
+
+#include <memory>
+#include <unordered_map>
+
+#include "base/check.h"
+#include "chrome/browser/ash/browser_delegate/browser_delegate_impl.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "chrome/browser/ui/browser_navigator.h"
+#include "chrome/browser/ui/browser_navigator_params.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
+
+namespace ash {
+
+BrowserControllerImpl::BrowserControllerImpl() {
+  observation_.Observe(BrowserList::GetInstance());
+}
+
+BrowserControllerImpl::~BrowserControllerImpl() = default;
+
+BrowserDelegate* BrowserControllerImpl::NewTabWithPostData(
+    user_manager::User& user,
+    const GURL& url,
+    base::span<const uint8_t> post_data,
+    std::string_view extra_headers) {
+  Profile* profile = Profile::FromBrowserContext(
+      BrowserContextHelper::Get()->GetBrowserContextByUser(&user));
+  CHECK(profile);
+
+  NavigateParams navigate_params(
+      profile, url,
+      // TODO(crbug.com/369688254): The page transition was chosen to satisfy
+      // some obsolete condition and should be revisited.
+      ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
+                                ui::PAGE_TRANSITION_FROM_API |
+                                ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
+  navigate_params.window_action = NavigateParams::SHOW_WINDOW;
+  navigate_params.post_data =
+      network::ResourceRequestBody::CreateFromCopyOfBytes(post_data);
+  navigate_params.extra_headers = std::string(extra_headers);
+
+  navigate_params.browser = chrome::FindTabbedBrowser(profile, false);
+  if (!navigate_params.browser &&
+      Browser::GetCreationStatusForProfile(profile) ==
+          Browser::CreationStatus::kOk) {
+    Browser::CreateParams create_params(profile, navigate_params.user_gesture);
+    create_params.should_trigger_session_restore = false;
+    navigate_params.browser = Browser::Create(create_params);
+  }
+
+  Navigate(&navigate_params);
+  return GetBrowserDelegate(navigate_params.browser);
+}
+
+BrowserDelegate* BrowserControllerImpl::GetBrowserDelegate(Browser* browser) {
+  if (browser == nullptr) {
+    return nullptr;
+  }
+
+  auto it = browsers_.find(browser);
+  if (it == browsers_.end()) {
+    it = browsers_
+             .insert({browser, std::make_unique<BrowserDelegateImpl>(browser)})
+             .first;
+  }
+  return it->second.get();
+}
+
+void BrowserControllerImpl::OnBrowserRemoved(Browser* browser) {
+  browsers_.erase(browser);
+  // The corresponding BrowserDelegateImpl, if any, is now dead.
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/browser_delegate/browser_controller_impl.h b/chrome/browser/ash/browser_delegate/browser_controller_impl.h
new file mode 100644
index 0000000..e775190
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_controller_impl.h
@@ -0,0 +1,48 @@
+// 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_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_IMPL_H_
+#define CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_IMPL_H_
+
+#include <memory>
+
+#include "base/scoped_observation.h"
+#include "chrome/browser/ash/browser_delegate/browser_controller.h"
+#include "chrome/browser/ui/browser_list_observer.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
+
+class Browser;
+class BrowserList;
+
+namespace ash {
+
+class BrowserDelegate;
+class BrowserDelegateImpl;
+
+class BrowserControllerImpl : public BrowserController,
+                              public BrowserListObserver {
+ public:
+  BrowserControllerImpl();
+  ~BrowserControllerImpl() override;
+
+  // BrowserController:
+  BrowserDelegate* NewTabWithPostData(user_manager::User& user,
+                                      const GURL& url,
+                                      base::span<const uint8_t> post_data,
+                                      std::string_view extra_headers) override;
+
+  // BrowserListObserver:
+  void OnBrowserRemoved(Browser* browser) override;
+
+ private:
+  BrowserDelegate* GetBrowserDelegate(Browser* browser);
+
+  absl::flat_hash_map<Browser*, std::unique_ptr<BrowserDelegateImpl>> browsers_;
+
+  base::ScopedObservation<BrowserList, BrowserListObserver> observation_{this};
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_CONTROLLER_IMPL_H_
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate.h b/chrome/browser/ash/browser_delegate/browser_delegate.h
new file mode 100644
index 0000000..072860a
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_delegate.h
@@ -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.
+
+#ifndef CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_H_
+#define CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_H_
+
+#include "components/sessions/core/session_id.h"
+
+namespace ash {
+
+// Abstraction of the `Browser` class from chrome/browser/ui/browser.h for use
+// by ChromeOS feature code. See README.md.
+class BrowserDelegate {
+ public:
+  // Returns the browser's unique ID for the current session.
+  virtual SessionID GetSessionID() const = 0;
+
+ protected:
+  ~BrowserDelegate() = default;
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_H_
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc b/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc
new file mode 100644
index 0000000..e512a6719
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_delegate_impl.cc
@@ -0,0 +1,20 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ash/browser_delegate/browser_delegate_impl.h"
+
+#include "chrome/browser/ui/browser.h"
+
+namespace ash {
+
+BrowserDelegateImpl::BrowserDelegateImpl(Browser* browser)
+    : browser_(browser) {}
+
+BrowserDelegateImpl::~BrowserDelegateImpl() = default;
+
+SessionID BrowserDelegateImpl::GetSessionID() const {
+  return browser_->session_id();
+}
+
+}  // namespace ash
diff --git a/chrome/browser/ash/browser_delegate/browser_delegate_impl.h b/chrome/browser/ash/browser_delegate/browser_delegate_impl.h
new file mode 100644
index 0000000..6096c56b
--- /dev/null
+++ b/chrome/browser/ash/browser_delegate/browser_delegate_impl.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 CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_IMPL_H_
+#define CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_IMPL_H_
+
+#include "base/memory/raw_ptr.h"
+#include "chrome/browser/ash/browser_delegate/browser_delegate.h"
+
+class Browser;
+
+namespace ash {
+
+class BrowserDelegateImpl : public BrowserDelegate {
+ public:
+  explicit BrowserDelegateImpl(Browser* browser);
+  virtual ~BrowserDelegateImpl();
+
+  // BrowserDelegate:
+  SessionID GetSessionID() const override;
+
+ private:
+  raw_ptr<Browser> const browser_;
+};
+
+}  // namespace ash
+
+#endif  // CHROME_BROWSER_ASH_BROWSER_DELEGATE_BROWSER_DELEGATE_IMPL_H_
diff --git a/chrome/browser/ash/login/signin/token_handle_checker.cc b/chrome/browser/ash/login/signin/token_handle_checker.cc
index 94bd662..ae750a0 100644
--- a/chrome/browser/ash/login/signin/token_handle_checker.cc
+++ b/chrome/browser/ash/login/signin/token_handle_checker.cc
@@ -85,13 +85,14 @@
     const Status& outcome,
     bool should_record_response_time) {
   CHECK(callback_) << "Unexpected response received";
-  std::move(callback_).Run(account_id_, token_, outcome);
   VLOG(1) << "Token handle check completed, status: "
           << StatusToString(outcome);
 
   if (should_record_response_time) {
     RecordTokenCheckResponseTime();
   }
+
+  std::move(callback_).Run(account_id_, token_, outcome);
 }
 
 void TokenHandleChecker::RecordTokenCheckResponseTime() {
diff --git a/chrome/browser/ash/login/signin/token_handle_store_impl.cc b/chrome/browser/ash/login/signin/token_handle_store_impl.cc
index 0166bf0..def15e9 100644
--- a/chrome/browser/ash/login/signin/token_handle_store_impl.cc
+++ b/chrome/browser/ash/login/signin/token_handle_store_impl.cc
@@ -5,9 +5,12 @@
 #include "chrome/browser/ash/login/signin/token_handle_store_impl.h"
 
 #include "base/json/values_util.h"
-#include "base/no_destructor.h"
 #include "chrome/browser/browser_process.h"
+#include "chrome/browser/profiles/profile.h"
 #include "components/account_id/account_id.h"
+#include "components/user_manager/known_user.h"
+#include "components/user_manager/user.h"
+#include "components/user_manager/user_manager.h"
 
 namespace ash {
 
@@ -18,13 +21,32 @@
 constexpr char kTokenHandleLastCheckedPref[] = "TokenHandleLastChecked";
 constexpr char kTokenHandleStatusInvalid[] = "invalid";
 constexpr char kTokenHandleStatusValid[] = "valid";
+constexpr char kTokenHandleStatusStale[] = "stale";
 constexpr base::TimeDelta kCacheStatusTime = base::Hours(1);
 
+bool IsReauthRequired(const TokenHandleChecker::Status& status,
+                      bool user_has_gaia_password) {
+  switch (status) {
+    case TokenHandleChecker::Status::kUnknown:
+    case TokenHandleChecker::Status::kValid:
+      return false;
+    case TokenHandleChecker::Status::kInvalid:
+      return true;
+    case TokenHandleChecker::Status::kExpired:
+      // When the status of the token is `kExpired`, enforce re-authentication
+      // only if the user is using their Gaia password for logging in.
+      return user_has_gaia_password;
+  }
+  NOTREACHED();
+}
+
 }  // namespace
 
 TokenHandleStoreImpl::TokenHandleStoreImpl(
-    std::unique_ptr<user_manager::KnownUser> known_user)
-    : known_user_(std::move(known_user)) {}
+    std::unique_ptr<user_manager::KnownUser> known_user,
+    DoesUserHaveGaiaPasswordCallback does_user_have_gaia_password)
+    : known_user_(std::move(known_user)),
+      does_user_have_gaia_password_(std::move(does_user_have_gaia_password)) {}
 
 TokenHandleStoreImpl::~TokenHandleStoreImpl() = default;
 
@@ -58,7 +80,39 @@
 void TokenHandleStoreImpl::IsReauthRequired(
     const AccountId& account_id,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
-    TokenValidationCallback callback) {}
+    TokenValidationCallback callback) {
+  if (const user_manager::User* user =
+          user_manager::UserManager::Get()->FindUser(account_id);
+      !user) {
+    DUMP_WILL_BE_NOTREACHED() << "Invalid user";
+    std::move(callback).Run(account_id, /*token=*/std::string(),
+                            /*reauth_required=*/false);
+    return;
+  }
+
+  const std::string* token =
+      known_user_->FindStringPath(account_id, kTokenHandlePref);
+  if (!token) {
+    // A token fetch is still in flight and we do not have a token yet. This is
+    // not an error case, so no error handling or logging is required.
+    std::move(callback).Run(account_id, /*token=*/std::string(),
+                            /*reauth_required=*/false);
+    return;
+  }
+
+  pending_callbacks_[account_id].push_back(std::move(callback));
+
+  // Overwriting the `TokenHandleChecker` for `account_id` while the check is
+  // pending will effectively cancel the previous check, and issue and newer
+  // one. Destroying the previous instance of `TokenHandleChecker` will also
+  // destroy the owned `GaiaOAuthClient`, therefore invalidating the weak_ptrs
+  // referencing it.
+  pending_checks_[account_id] = std::make_unique<TokenHandleChecker>(
+      account_id, *token, url_loader_factory);
+
+  pending_checks_[account_id]->StartCheck(base::BindOnce(
+      &TokenHandleStoreImpl::OnCheckToken, weak_factory_.GetWeakPtr()));
+}
 
 void TokenHandleStoreImpl::StoreTokenHandle(const AccountId& account_id,
                                             const std::string& handle) {
@@ -69,6 +123,70 @@
                        base::TimeToValue(base::Time::Now()));
 }
 
+void TokenHandleStoreImpl::OnCheckToken(
+    const AccountId& account_id,
+    const std::string& token,
+    const TokenHandleChecker::Status& status) {
+  CHECK(pending_checks_.find(account_id) != pending_checks_.end());
+
+  does_user_have_gaia_password_.Run(
+      account_id,
+      base::BindOnce(&TokenHandleStoreImpl::ReplyToTokenHandleCheck,
+                     weak_factory_.GetWeakPtr(), token, account_id, status));
+}
+
+// This method maintains the following invariants:
+// - A vector of token handle check callbacks, ordered such that the back of the
+// vector contains the more recent requests. When the most recent request
+// returns, we empty the queue and reply to all of the pending callbacks with
+// its result.
+// - Setting a token handle's status to stale will defer replying to all pending
+// checks until we fetch a new token handle. At which point we'll reply to all
+// pending callbacks that the new token is valid.
+void TokenHandleStoreImpl::ReplyToTokenHandleCheck(
+    const std::string& token,
+    const AccountId& account_id,
+    const TokenHandleChecker::Status& status,
+    std::optional<bool> user_has_gaia_password) {
+  if (const std::string* pref_status =
+          known_user_->FindStringPath(account_id, kTokenHandleStatusPref);
+      pref_status != nullptr && *pref_status == kTokenHandleStatusStale) {
+    // Token handle has been marked as stale, we defer replying to checks
+    // until we fetch the new token handle.
+    return;
+  }
+
+  if (status != TokenHandleChecker::Status::kUnknown) {
+    // Update last checked timestamp.
+    known_user_->SetPath(account_id, kTokenHandleLastCheckedPref,
+                         base::TimeToValue(base::Time::Now()));
+  }
+
+  bool is_reauth_required =
+      ::ash::IsReauthRequired(status, user_has_gaia_password.value_or(true));
+
+  if (is_reauth_required) {
+    known_user_->SetStringPref(account_id, kTokenHandleStatusPref,
+                               kTokenHandleStatusInvalid);
+  }
+
+  std::ranges::for_each(
+      pending_callbacks_[account_id], [&](TokenValidationCallback& callback) {
+        std::move(callback).Run(account_id, token,
+                                /*reauth_required=*/is_reauth_required);
+      });
+
+  pending_callbacks_[account_id].clear();
+
+  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+      FROM_HERE, base::BindOnce(&TokenHandleStoreImpl::ScheduleCheckerDelete,
+                                weak_factory_.GetWeakPtr(), account_id));
+}
+
+void TokenHandleStoreImpl::ScheduleCheckerDelete(const AccountId& account_id) {
+  pending_checks_.erase(account_id);
+}
+
 bool TokenHandleStoreImpl::HasTokenStatusInvalid(
     const AccountId& account_id) const {
   const std::string* status =
diff --git a/chrome/browser/ash/login/signin/token_handle_store_impl.h b/chrome/browser/ash/login/signin/token_handle_store_impl.h
index 60b8fe6..93300725 100644
--- a/chrome/browser/ash/login/signin/token_handle_store_impl.h
+++ b/chrome/browser/ash/login/signin/token_handle_store_impl.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "ash/public/cpp/token_handle_store.h"
+#include "base/containers/flat_map.h"
 #include "base/no_destructor.h"
 #include "chrome/browser/ash/login/signin/token_handle_checker.h"
 #include "components/account_id/account_id.h"
@@ -21,8 +22,18 @@
 // TODO(387248794): Rename to `TokenHandleStore` as part of cleanup.
 class TokenHandleStoreImpl : public TokenHandleStore {
  public:
-  explicit TokenHandleStoreImpl(
-      std::unique_ptr<user_manager::KnownUser> known_user);
+  // Takes an account id, and a callback.
+  // Responds on the callback with -
+  // `true` if the given account id uses Gaia password for authentication.
+  // `false` if the given account id does not use Gaia password for
+  // authentication. `nullopt` if the given account id uses an unknown
+  // authentication scheme.
+  using DoesUserHaveGaiaPasswordCallback = base::RepeatingCallback<
+      void(const AccountId&, base::OnceCallback<void(std::optional<bool>)>)>;
+
+  TokenHandleStoreImpl(
+      std::unique_ptr<user_manager::KnownUser> known_user,
+      DoesUserHaveGaiaPasswordCallback does_user_have_gaia_password);
   ~TokenHandleStoreImpl() override;
 
   TokenHandleStoreImpl(const TokenHandleStoreImpl&) = delete;
@@ -45,10 +56,43 @@
   void MaybeFetchTokenHandle(const AccountId& account_id);
 
  private:
+  void OnCheckToken(const AccountId& account_id,
+                    const std::string& token,
+                    const TokenHandleChecker::Status& status);
+
+  // Replies to all pending token handle checks for `account_id`.
+  // `user_has_gaia_password` is used to determine whether reauth is required in
+  // the case where the token handle has expired. If the user does have a gaia
+  // password, an expired token will lead to a reauth.
+  void ReplyToTokenHandleCheck(const std::string& token,
+                               const AccountId& account_id,
+                               const TokenHandleChecker::Status& status,
+                               std::optional<bool> user_has_gaia_password);
+
+  // We schedule the delete for `account_id`'s checker to give a chance for
+  // the stack to unwind. Otherwise we might return to invalid memory, causing
+  // a use-after-free.
+  void ScheduleCheckerDelete(const AccountId& account_id);
+
   // Checks if token handle is explicitly marked as valid for `account_id`.
   bool HasTokenStatusInvalid(const AccountId& account_id) const;
 
+  // Associates an `AccountId` with a pending token handle check.
+  base::flat_map<AccountId, std::unique_ptr<TokenHandleChecker>>
+      pending_checks_;
+
+  // Stores a collection of callbacks to clients that initiated a token handle
+  // check request that is currently pending. The callbacks are grouped by
+  // `AccountId` as concurrent requests are pooled and replied to when the most
+  // recent request for a token handle check for `AccountId` returns.
+  base::flat_map<AccountId, std::vector<TokenValidationCallback>>
+      pending_callbacks_;
+
   std::unique_ptr<user_manager::KnownUser> known_user_;
+
+  DoesUserHaveGaiaPasswordCallback does_user_have_gaia_password_;
+
+  base::WeakPtrFactory<TokenHandleStoreImpl> weak_factory_{this};
 };
 
 }  // namespace ash
diff --git a/chrome/browser/ash/login/signin/token_handle_store_unittest.cc b/chrome/browser/ash/login/signin/token_handle_store_unittest.cc
index 0de535e4..31c8ed2 100644
--- a/chrome/browser/ash/login/signin/token_handle_store_unittest.cc
+++ b/chrome/browser/ash/login/signin/token_handle_store_unittest.cc
@@ -2,13 +2,27 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <memory>
+
 #include "base/json/values_util.h"
+#include "base/strings/stringprintf.h"
+#include "base/test/bind.h"
 #include "base/test/scoped_mock_clock_override.h"
+#include "base/test/task_environment.h"
+#include "base/test/test_future.h"
 #include "base/time/time.h"
 #include "chrome/browser/ash/login/signin/token_handle_store_impl.h"
+#include "chromeos/ash/components/settings/cros_settings.h"
 #include "components/prefs/pref_registry_simple.h"
 #include "components/prefs/testing_pref_service.h"
+#include "components/user_manager/fake_user_manager_delegate.h"
 #include "components/user_manager/known_user.h"
+#include "components/user_manager/test_helper.h"
+#include "components/user_manager/user_manager.h"
+#include "components/user_manager/user_manager_impl.h"
+#include "google_apis/gaia/gaia_urls.h"
+#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
+#include "services/network/test/test_url_loader_factory.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace ash {
@@ -16,8 +30,11 @@
 namespace {
 
 constexpr char kFakeToken[] = "fake-token";
+constexpr char kFakeOtherToken[] = "fake-other-token";
 constexpr char kFakeEmail[] = "fake-email@example.com";
-constexpr char kKnownUserPref[] = "KnownUsers";
+constexpr char kFakeOtherEmail[] = "fake-other-email@example.com";
+constexpr GaiaId::Literal kFakeGaiaId("fake-gaia-id");
+constexpr GaiaId::Literal kFakeOtherGaiaId("fake-other-gaia-id");
 
 constexpr char kTokenHandlePref[] = "PasswordTokenHandle";
 constexpr char kTokenHandleStatusPref[] = "TokenHandleStatus";
@@ -25,22 +42,68 @@
 constexpr char kTokenHandleStatusInvalid[] = "invalid";
 constexpr char kTokenHandleStatusValid[] = "valid";
 
+constexpr char kValidTokenInfoResponse[] =
+    R"(
+      { "email": "%s",
+        "user_id": "1234567890",
+        "expires_in": %d
+      }
+   )";
+
 constexpr base::TimeDelta kCacheStatusTime = base::Hours(1);
 
+std::string GetValidTokenInfoResponse(const std::string& email,
+                                      int expires_in) {
+  return base::StringPrintf(kValidTokenInfoResponse, email, expires_in);
+}
+
+void AssertLastCheckedTimestampWithinTolerance(
+    std::unique_ptr<user_manager::KnownUser> known_user,
+    const AccountId& account_id,
+    base::Time expected_last_checked_timestamp,
+    base::TimeDelta tolerance) {
+  base::Time actual_last_checked_time =
+      base::ValueToTime(
+          *known_user->FindPath(account_id, kTokenHandleLastCheckedPref))
+          .value();
+
+  EXPECT_NEAR(expected_last_checked_timestamp.InMillisecondsSinceUnixEpoch(),
+              actual_last_checked_time.InMillisecondsSinceUnixEpoch(),
+              tolerance.InMilliseconds());
+}
+
 }  // namespace
 
 class TokenHandleStoreTest : public ::testing::Test {
  public:
+  using TokenValidationFuture =
+      base::test::TestFuture<const AccountId&, const std::string&, bool>;
+
   TokenHandleStoreTest() = default;
   ~TokenHandleStoreTest() override = default;
 
   void SetUp() override {
+    user_manager::UserManagerImpl::RegisterPrefs(local_state_.registry());
     local_state_.registry()->RegisterDictionaryPref(kTokenHandlePref);
-    local_state_.registry()->RegisterListPref(kKnownUserPref);
+  }
+
+  std::unique_ptr<TokenHandleStore> CreateTokenHandleStore(
+      std::unique_ptr<user_manager::KnownUser> known_user,
+      bool user_has_gaia_password = true) {
+    auto does_user_have_gaia_password =
+        [user_has_gaia_password](
+            const AccountId& account_id,
+            base::OnceCallback<void(std::optional<bool>)> continuation) {
+          std::move(continuation).Run(user_has_gaia_password);
+        };
+    return std::make_unique<TokenHandleStoreImpl>(
+        std::move(known_user),
+        base::BindLambdaForTesting(std::move(does_user_have_gaia_password)));
   }
 
  protected:
   TestingPrefServiceSimple local_state_;
+  std::unique_ptr<user_manager::UserManager> user_manager_;
 };
 
 TEST_F(TokenHandleStoreTest, HasTokenReturnsTrueWhenTokenIsOnDisk) {
@@ -48,7 +111,7 @@
   auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
   known_user->SetStringPref(account_id, kTokenHandlePref, kFakeToken);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool has_token = token_handle_store->HasToken(account_id);
 
@@ -60,7 +123,7 @@
   auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
   known_user->SetStringPref(account_id, kTokenHandlePref, std::string());
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool has_token = token_handle_store->HasToken(account_id);
 
@@ -71,7 +134,7 @@
   AccountId account_id = AccountId::FromUserEmail(kFakeEmail);
   auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool has_token = token_handle_store->HasToken(account_id);
 
@@ -86,7 +149,7 @@
   known_user->SetStringPref(account_id, kTokenHandleStatusPref,
                             kTokenHandleStatusInvalid);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool should_obtain_handle =
       token_handle_store->ShouldObtainHandle(account_id);
@@ -98,7 +161,7 @@
   AccountId account_id = AccountId::FromUserEmail(kFakeEmail);
   auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool should_obtain_handle =
       token_handle_store->ShouldObtainHandle(account_id);
@@ -114,7 +177,7 @@
   known_user->SetStringPref(account_id, kTokenHandleStatusPref,
                             kTokenHandleStatusValid);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool should_obtain_handle =
       token_handle_store->ShouldObtainHandle(account_id);
@@ -126,7 +189,7 @@
   AccountId account_id = AccountId::FromUserEmail(kFakeEmail);
   auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
 
   bool is_recently_checked = token_handle_store->IsRecentlyChecked(account_id);
 
@@ -141,7 +204,7 @@
   known_user->SetPath(account_id, kTokenHandleLastCheckedPref,
                       base::TimeToValue(base::Time::Now()));
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
   mock_clock.Advance(kCacheStatusTime - base::Minutes(1));
 
   bool is_recently_checked = token_handle_store->IsRecentlyChecked(account_id);
@@ -157,7 +220,7 @@
   known_user->SetPath(account_id, kTokenHandleLastCheckedPref,
                       base::TimeToValue(base::Time::Now()));
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(known_user));
+      CreateTokenHandleStore(std::move(known_user));
   mock_clock.Advance(kCacheStatusTime * 2);
 
   bool is_recently_checked = token_handle_store->IsRecentlyChecked(account_id);
@@ -176,7 +239,7 @@
                                base::TimeToValue(previous_last_checked));
   base::TimeDelta delta = base::Seconds(1);
   std::unique_ptr<TokenHandleStore> token_handle_store =
-      std::make_unique<TokenHandleStoreImpl>(std::move(injected_known_user));
+      CreateTokenHandleStore(std::move(injected_known_user));
   mock_clock.Advance(delta);
 
   token_handle_store->StoreTokenHandle(account_id, kFakeToken);
@@ -186,14 +249,331 @@
             *known_user->FindStringPath(account_id, kTokenHandlePref));
   EXPECT_EQ(kTokenHandleStatusValid,
             *known_user->FindStringPath(account_id, kTokenHandleStatusPref));
-  base::Time expected_last_checked_time = previous_last_checked + delta;
-  base::Time actual_last_checked_time =
-      base::ValueToTime(
-          *known_user->FindPath(account_id, kTokenHandleLastCheckedPref))
-          .value();
-  EXPECT_NEAR(expected_last_checked_time.InMillisecondsSinceUnixEpoch(),
-              actual_last_checked_time.InMillisecondsSinceUnixEpoch(),
-              (delta / 2).InMilliseconds());
+  AssertLastCheckedTimestampWithinTolerance(
+      std::move(known_user), account_id,
+      /*expected_last_checked_timestamp*/ previous_last_checked + delta,
+      /*tolerance=*/delta / 2);
+}
+
+class TokenHandleStoreIsReauthRequiredTest : public TokenHandleStoreTest {
+ public:
+  TokenHandleStoreIsReauthRequiredTest() = default;
+  ~TokenHandleStoreIsReauthRequiredTest() override = default;
+
+  void SetUp() override {
+    account_id_ = AccountId::FromUserEmailGaiaId(kFakeEmail, kFakeGaiaId);
+    other_account_id_ =
+        AccountId::FromUserEmailGaiaId(kFakeOtherEmail, kFakeOtherGaiaId);
+    user_manager::UserManagerImpl::RegisterPrefs(local_state_.registry());
+    user_manager::TestHelper::RegisterPersistedUser(local_state_, account_id_);
+    user_manager::TestHelper::RegisterPersistedUser(local_state_,
+                                                    other_account_id_);
+    local_state_.registry()->RegisterDictionaryPref(kTokenHandlePref);
+
+    cros_settings_ = std::make_unique<ash::CrosSettings>();
+    user_manager_ = std::make_unique<user_manager::UserManagerImpl>(
+        std::make_unique<user_manager::FakeUserManagerDelegate>(),
+        &local_state_, cros_settings_.get());
+
+    user_manager_->Initialize();
+  }
+
+  void TearDown() override {
+    user_manager_->Destroy();
+    user_manager_.reset();
+    cros_settings_.reset();
+  }
+
+  scoped_refptr<network::SharedURLLoaderFactory> GetSharedURLLoaderFactory() {
+    return url_loader_factory_.GetSafeWeakWrapper();
+  }
+
+  void AddFakeResponseForStatus(TokenHandleChecker::Status status) {
+    switch (status) {
+      case TokenHandleChecker::Status::kValid:
+        AddFakeResponse(
+            GetValidTokenInfoResponse(kFakeEmail, /*expires_in=*/1000),
+            net::HTTP_OK);
+        return;
+      case TokenHandleChecker::Status::kInvalid:
+        AddFakeResponse(
+            GetValidTokenInfoResponse(kFakeEmail, /*expires_in=*/1000),
+            net::HTTP_UNAUTHORIZED);
+        return;
+      case TokenHandleChecker::Status::kExpired:
+        AddFakeResponse(
+            GetValidTokenInfoResponse(kFakeEmail, /*expires_in=*/-1),
+            net::HTTP_OK);
+        return;
+      case TokenHandleChecker::Status::kUnknown:
+        AddFakeResponse(std::string(), net::HTTP_OK);
+        return;
+    }
+  }
+
+  void AddFakeResponse(const std::string& response,
+                       net::HttpStatusCode http_status) {
+    url_loader_factory_.AddResponse(
+        GaiaUrls::GetInstance()->oauth2_token_info_url().spec(), response,
+        http_status);
+  }
+
+ protected:
+  AccountId account_id_;
+  AccountId other_account_id_;
+  std::unique_ptr<user_manager::UserManager> user_manager_;
+  std::unique_ptr<ash::CrosSettings> cros_settings_;
+  network::TestURLLoaderFactory url_loader_factory_;
+  base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredReturnsFalseIfTokenDoesNotExist) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(std::string(), future.Get<std::string>());
+  EXPECT_EQ(false, future.Get<bool>());
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredReturnsTrueIfTokenExistsAndInvalid) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kInvalid);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future.Get<std::string>());
+  EXPECT_EQ(true, future.Get<bool>());
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredReturnsFalseIfTokenExistsAndValid) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                            kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kValid);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future.Get<std::string>());
+  EXPECT_EQ(false, future.Get<bool>());
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredReturnsFalseIfTokenExistsAndStatusUnknown) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                            kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kUnknown);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future.Get<std::string>());
+  EXPECT_EQ(false, future.Get<bool>());
+}
+
+TEST_F(
+    TokenHandleStoreIsReauthRequiredTest,
+    IsReauthRequiredReturnsTrueIfUserHasGaiaPasswordAndTokenExistsAndExpired) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                            kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kExpired);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future.Get<std::string>());
+  EXPECT_EQ(true, future.Get<bool>());
+}
+
+TEST_F(
+    TokenHandleStoreIsReauthRequiredTest,
+    IsReauthRequiredReturnsFalseIfUserHasNoGaiaPasswordAndTokenExistsAndExpired) {
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                            kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kExpired);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(known_user),
+                             /*user_has_gaia_password=*/false);
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_EQ(account_id_, future.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future.Get<std::string>());
+  EXPECT_EQ(false, future.Get<bool>());
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredSetsStatusPrefToInvalidWhenTokenInvalid) {
+  auto injected_known_user =
+      std::make_unique<user_manager::KnownUser>(&local_state_);
+  injected_known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  injected_known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                                     kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kInvalid);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(injected_known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  EXPECT_TRUE(future.Wait());
+  EXPECT_EQ(kTokenHandleStatusInvalid,
+            *known_user->FindStringPath(account_id_, kTokenHandleStatusPref));
+}
+
+TEST_F(
+    TokenHandleStoreIsReauthRequiredTest,
+    IsReauthRequiredSetsStatusPrefToInvalidWhenTokenExpiredAndUserHasGaiaPassword) {
+  auto injected_known_user =
+      std::make_unique<user_manager::KnownUser>(&local_state_);
+  injected_known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  injected_known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                                     kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kExpired);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(injected_known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  auto known_user = std::make_unique<user_manager::KnownUser>(&local_state_);
+  EXPECT_TRUE(future.Wait());
+  EXPECT_EQ(kTokenHandleStatusInvalid,
+            *known_user->FindStringPath(account_id_, kTokenHandleStatusPref));
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       IsReauthRequiredSetsLastCheckedPrefTimestampWhenStatusIsNotUnknown) {
+  base::ScopedMockClockOverride mock_clock;
+  base::Time previous_last_checked = base::Time::Now();
+  base::TimeDelta delta = base::Seconds(1);
+  mock_clock.Advance(delta);
+  auto injected_known_user =
+      std::make_unique<user_manager::KnownUser>(&local_state_);
+  injected_known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  injected_known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                                     kTokenHandleStatusValid);
+  AddFakeResponseForStatus(TokenHandleChecker::Status::kValid);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(injected_known_user));
+  TokenValidationFuture future;
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future.GetCallback());
+
+  EXPECT_TRUE(future.Wait());
+  AssertLastCheckedTimestampWithinTolerance(
+      std::make_unique<user_manager::KnownUser>(&local_state_), account_id_,
+      /*expected_last_checked_timestamp=*/previous_last_checked + delta,
+      /*tolerance=*/delta / 2);
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       ConcurrentIsReauthRequiredRequestsForTheSameAccountIdGetPooled) {
+  auto injected_known_user =
+      std::make_unique<user_manager::KnownUser>(&local_state_);
+  injected_known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  injected_known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                                     kTokenHandleStatusValid);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(injected_known_user));
+  TokenValidationFuture future1;
+  TokenValidationFuture future2;
+  const GURL& url = GaiaUrls::GetInstance()->oauth2_token_info_url();
+
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future1.GetCallback());
+  url_loader_factory_.WaitForRequest(url);
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future2.GetCallback());
+
+  // Reply to the second request, which should reply to both pending concurrent
+  // requests.
+  url_loader_factory_.SimulateResponseForPendingRequest(
+      url.spec(), GetValidTokenInfoResponse(kFakeEmail, /*expires_in=*/1000),
+      net::HTTP_OK);
+
+  EXPECT_TRUE(future1.Wait());
+  EXPECT_TRUE(future2.Wait());
+  EXPECT_EQ(account_id_, future1.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future1.Get<std::string>());
+  EXPECT_EQ(false, future1.Get<bool>());
+  EXPECT_EQ(account_id_, future2.Get<AccountId>());
+  EXPECT_EQ(kFakeToken, future2.Get<std::string>());
+  EXPECT_EQ(false, future2.Get<bool>());
+}
+
+TEST_F(TokenHandleStoreIsReauthRequiredTest,
+       ConcurrentIsReauthRequiredRequestsForDifferentAccountIdsDoNotGetPooled) {
+  auto injected_known_user =
+      std::make_unique<user_manager::KnownUser>(&local_state_);
+  injected_known_user->SetStringPref(account_id_, kTokenHandlePref, kFakeToken);
+  injected_known_user->SetStringPref(account_id_, kTokenHandleStatusPref,
+                                     kTokenHandleStatusValid);
+  injected_known_user->SetStringPref(other_account_id_, kTokenHandlePref,
+                                     kFakeOtherToken);
+  injected_known_user->SetStringPref(other_account_id_, kTokenHandlePref,
+                                     kFakeOtherToken);
+  std::unique_ptr<TokenHandleStore> token_handle_store =
+      CreateTokenHandleStore(std::move(injected_known_user));
+  TokenValidationFuture future1;
+  TokenValidationFuture future2;
+  const GURL& url = GaiaUrls::GetInstance()->oauth2_token_info_url();
+
+  token_handle_store->IsReauthRequired(
+      other_account_id_, GetSharedURLLoaderFactory(), future1.GetCallback());
+  url_loader_factory_.WaitForRequest(url);
+  token_handle_store->IsReauthRequired(account_id_, GetSharedURLLoaderFactory(),
+                                       future2.GetCallback());
+
+  // Reply to only second request, leaving the first one pending.
+  url_loader_factory_.SimulateResponseForPendingRequest(
+      url.spec(), GetValidTokenInfoResponse(kFakeEmail, /*expires_in=*/1000),
+      net::HTTP_OK, network::TestURLLoaderFactory::kMostRecentMatch);
+
+  EXPECT_TRUE(future2.Wait());
+  // As we only replied to the check for `account_id_`, the check for
+  // `other_account_id_` should still be pending.
+  EXPECT_FALSE(future1.IsReady());
 }
 
 }  // namespace ash
diff --git a/chrome/browser/ash/system_web_apps/apps/media_app/BUILD.gn b/chrome/browser/ash/system_web_apps/apps/media_app/BUILD.gn
index 144a652..cbedd0ff 100644
--- a/chrome/browser/ash/system_web_apps/apps/media_app/BUILD.gn
+++ b/chrome/browser/ash/system_web_apps/apps/media_app/BUILD.gn
@@ -19,8 +19,8 @@
     "//ash/webui/media_app_ui:mojo_bindings_untrusted",
     "//base",
     "//chrome/browser:browser_public_dependencies",
-    "//chromeos/ash/experiences/system_web_apps/types",
     "//chromeos/ash/components/specialized_features",
+    "//chromeos/ash/experiences/system_web_apps/types",
     "//content/public/browser",
     "//mojo/public/cpp/bindings",
     "//storage/browser",
@@ -35,18 +35,19 @@
     "//chrome/browser:browser_process",
     "//chrome/browser/apps/app_service:constants",
     "//chrome/browser/ash/app_list/arc",
+    "//chrome/browser/ash/browser_delegate",
     "//chrome/browser/ash/file_manager",
     "//chrome/browser/ash/hats",
     "//chrome/browser/ash/system_web_apps/apps",
     "//chrome/browser/feedback",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/search_engines",
-    "//chrome/browser/ui:browser_navigator_params_headers",
     "//chrome/browser/web_applications",
     "//chrome/browser/web_applications/mojom:mojom_web_apps_enum",
     "//chrome/common",
     "//chrome/common:channel_info",
     "//chrome/common:constants",
+    "//chromeos/ash/components/browser_context_helper",
     "//chromeos/components/mahi/public/cpp",
     "//chromeos/strings",
     "//components/prefs",
diff --git a/chrome/browser/ash/system_web_apps/apps/media_app/chrome_media_app_ui_delegate.cc b/chrome/browser/ash/system_web_apps/apps/media_app/chrome_media_app_ui_delegate.cc
index 045e686..8dc2296 100644
--- a/chrome/browser/ash/system_web_apps/apps/media_app/chrome_media_app_ui_delegate.cc
+++ b/chrome/browser/ash/system_web_apps/apps/media_app/chrome_media_app_ui_delegate.cc
@@ -9,6 +9,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/webui/media_app_ui/file_system_access_helpers.h"
 #include "ash/webui/media_app_ui/url_constants.h"
+#include "base/check_deref.h"
 #include "base/containers/flat_map.h"
 #include "base/functional/bind.h"
 #include "base/notreached.h"
@@ -16,6 +17,8 @@
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
 #include "chrome/browser/apps/app_service/launch_result_type.h"
 #include "chrome/browser/ash/app_list/arc/arc_app_utils.h"
+#include "chrome/browser/ash/browser_delegate/browser_controller.h"
+#include "chrome/browser/ash/browser_delegate/browser_delegate.h"
 #include "chrome/browser/ash/file_manager/fileapi_util.h"
 #include "chrome/browser/ash/file_manager/volume_manager.h"
 #include "chrome/browser/ash/hats/hats_config.h"
@@ -23,15 +26,12 @@
 #include "chrome/browser/feedback/show_feedback_page.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_manager.h"
-#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_commands.h"
-#include "chrome/browser/ui/browser_finder.h"
-#include "chrome/browser/ui/browser_navigator.h"
-#include "chrome/browser/ui/browser_navigator_params.h"
 #include "chrome/common/channel_info.h"
+#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "components/services/app_service/public/cpp/app_launch_util.h"
 #include "components/services/app_service/public/cpp/intent.h"
 #include "components/services/app_service/public/cpp/intent_util.h"
+#include "components/user_manager/user.h"
 #include "components/version_info/channel.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui.h"
@@ -192,26 +192,9 @@
 void ChromeMediaAppUIDelegate::SubmitForm(const GURL& url,
                                           const std::vector<int8_t>& payload,
                                           const std::string& header) {
-  Profile* profile = Profile::FromWebUI(web_ui_);
-  NavigateParams navigate_params(
-      profile, url,
-      ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED |
-                                ui::PAGE_TRANSITION_FROM_API |
-                                ui::PAGE_TRANSITION_FROM_ADDRESS_BAR));
-  navigate_params.window_action = NavigateParams::SHOW_WINDOW;
-  navigate_params.post_data =
-      network::ResourceRequestBody::CreateFromCopyOfBytes(
-          base::as_byte_span(payload));
-  navigate_params.extra_headers = header;
-
-  navigate_params.browser = chrome::FindTabbedBrowser(profile, false);
-  if (!navigate_params.browser &&
-      Browser::GetCreationStatusForProfile(profile) ==
-          Browser::CreationStatus::kOk) {
-    Browser::CreateParams create_params(profile, navigate_params.user_gesture);
-    create_params.should_trigger_session_restore = false;
-    navigate_params.browser = Browser::Create(create_params);
-  }
-
-  Navigate(&navigate_params);
+  user_manager::User& user =
+      CHECK_DEREF(ash::BrowserContextHelper::Get()->GetUserByBrowserContext(
+          Profile::FromWebUI(web_ui_)));
+  ash::BrowserController::GetInstance()->NewTabWithPostData(
+      user, url, base::as_byte_span(payload), header);
 }
diff --git a/chrome/browser/browser_features.cc b/chrome/browser/browser_features.cc
index 7f5379b0..fdf45d1 100644
--- a/chrome/browser/browser_features.cc
+++ b/chrome/browser/browser_features.cc
@@ -257,11 +257,9 @@
 // If disabled, the blue border is not used on ChromeOS.
 //
 // Motivation:
-//  The blue border behavior used to cause problems on ChromeOS - see
-//  crbug.com/1320262 for Ash (fixed) and crbug.com/1030925 for Lacros
-//  (relatively old bug - we would like to observe whether it's still
-//  there). This flag is introduced as means of disabling this feature in case
-//  of possible future regressions.
+//  The blue border behavior used to (still does, see below) cause problems on
+//  ChromeOS - see crbug.com/1320262 (fixed). This flag is introduced as means
+//  of disabling this feature in case of possible future regressions.
 //
 // TODO(crbug.com/40198577): Remove this flag once we confirm that blue border
 // works fine on ChromeOS.
diff --git a/chrome/browser/commerce/price_change/android/BUILD.gn b/chrome/browser/commerce/price_change/android/BUILD.gn
index d327740..c5c6a13 100644
--- a/chrome/browser/commerce/price_change/android/BUILD.gn
+++ b/chrome/browser/commerce/price_change/android/BUILD.gn
@@ -27,6 +27,7 @@
     "//chrome/browser/tab:java",
     "//chrome/browser/tabmodel:java",
     "//chrome/browser/ui/android/favicon:java",
+    "//components/browser_ui/styles/android:java",
     "//components/browser_ui/util/android:java",
     "//components/commerce/core/android:core_java",
     "//components/embedder_support/android:simple_factory_key_java",
diff --git a/chrome/browser/commerce/price_change/android/java/src/org/chromium/chrome/browser/price_change/PriceChangeModuleViewUtils.java b/chrome/browser/commerce/price_change/android/java/src/org/chromium/chrome/browser/price_change/PriceChangeModuleViewUtils.java
index a16c194..8b2889b 100644
--- a/chrome/browser/commerce/price_change/android/java/src/org/chromium/chrome/browser/price_change/PriceChangeModuleViewUtils.java
+++ b/chrome/browser/commerce/price_change/android/java/src/org/chromium/chrome/browser/price_change/PriceChangeModuleViewUtils.java
@@ -5,34 +5,17 @@
 package org.chromium.chrome.browser.price_change;
 
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
 
 import androidx.annotation.ColorInt;
-import androidx.annotation.StyleRes;
 
-import com.google.android.material.color.MaterialColors;
 import com.google.android.material.elevation.ElevationOverlayProvider;
 
+import org.chromium.components.browser_ui.styles.SemanticColorUtils;
+
 /** Utility class that provides theme related attributes for price change UI. */
 public class PriceChangeModuleViewUtils {
     static @ColorInt int getBackgroundColor(Context context) {
-        int alpha =
-                context.getResources().getInteger(R.integer.tab_thumbnail_placeholder_color_alpha);
-        @StyleRes int styleRes = R.style.TabThumbnailPlaceholderStyle;
-        TypedArray ta =
-                context.obtainStyledAttributes(styleRes, R.styleable.TabThumbnailPlaceholder);
-        @ColorInt
-        int baseColor =
-                ta.getColor(R.styleable.TabThumbnailPlaceholder_colorTileBase, Color.TRANSPARENT);
-        float tileSurfaceElevation =
-                ta.getDimension(R.styleable.TabThumbnailPlaceholder_elevationTileBase, 0);
-        ta.recycle();
-        if (tileSurfaceElevation != 0) {
-            ElevationOverlayProvider eop = new ElevationOverlayProvider(context);
-            baseColor = eop.compositeOverlay(baseColor, tileSurfaceElevation);
-        }
-        return MaterialColors.compositeARGBWithAlpha(baseColor, alpha);
+        return SemanticColorUtils.getColorSurfaceContainerLow(context);
     }
 
     static @ColorInt int getIconColor(Context context) {
diff --git a/chrome/browser/devtools/features.cc b/chrome/browser/devtools/features.cc
index d5140e9..9bf35d2 100644
--- a/chrome/browser/devtools/features.cc
+++ b/chrome/browser/devtools/features.cc
@@ -138,7 +138,7 @@
 // See http://go/chrome-devtools:automatic-workspace-folders-design for details.
 BASE_FEATURE(kDevToolsAutomaticFileSystems,
              "DevToolsAutomaticFileSystems",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // Whether DevTools will attempt to load project settings from a well-known
 // URI. See https://goo.gle/devtools-json-design for additional details.
diff --git a/chrome/browser/extensions/BUILD.gn b/chrome/browser/extensions/BUILD.gn
index 52c8c4f..b6ebb77 100644
--- a/chrome/browser/extensions/BUILD.gn
+++ b/chrome/browser/extensions/BUILD.gn
@@ -407,6 +407,7 @@
     "//net:extras",
     "//storage/browser",
     "//third_party/zlib/google:zip",
+    "//ui/shell_dialogs",
   ]
   public_deps = [ "//components/safe_browsing/core/browser/db:util" ]
   defines = []
@@ -1035,7 +1036,6 @@
       "//ui/message_center/public/cpp",
       "//ui/native_theme",
       "//ui/resources",
-      "//ui/shell_dialogs",
       "//ui/strings",
       "//url",
     ]
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.cc b/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.cc
index 6b5123f..afbb671c 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.cc
@@ -32,26 +32,6 @@
     account_extension_tracker_observation_.Observe(
         AccountExtensionTracker::Get(profile));
   }
-
-  pref_change_registrar_.Init(profile->GetPrefs());
-  // The unretained is safe, since the PrefChangeRegistrar unregisters the
-  // callback on destruction.
-  pref_change_registrar_.Add(
-      prefs::kExtensionsUIDeveloperMode,
-      base::BindRepeating(&DeveloperPrivateEventRouter::OnProfilePrefChanged,
-                          base::Unretained(this)));
-  pref_change_registrar_.Add(
-      kMV2DeprecationWarningAcknowledgedGloballyPref.name,
-      base::BindRepeating(&DeveloperPrivateEventRouter::OnProfilePrefChanged,
-                          base::Unretained(this)));
-  pref_change_registrar_.Add(
-      kMV2DeprecationDisabledAcknowledgedGloballyPref.name,
-      base::BindRepeating(&DeveloperPrivateEventRouter::OnProfilePrefChanged,
-                          base::Unretained(this)));
-  pref_change_registrar_.Add(
-      kMV2DeprecationUnsupportedAcknowledgedGloballyPref.name,
-      base::BindRepeating(&DeveloperPrivateEventRouter::OnProfilePrefChanged,
-                          base::Unretained(this)));
 }
 
 DeveloperPrivateEventRouter::~DeveloperPrivateEventRouter() = default;
@@ -126,67 +106,4 @@
   }
 }
 
-void DeveloperPrivateEventRouter::OnProfilePrefChanged() {
-  base::Value::List args;
-  args.Append(CreateProfileInfo(profile_).ToValue());
-  auto event = std::make_unique<Event>(
-      events::DEVELOPER_PRIVATE_ON_PROFILE_STATE_CHANGED,
-      developer::OnProfileStateChanged::kEventName, std::move(args));
-  event_router_->BroadcastEvent(std::move(event));
-
-  // The following properties are updated when dev mode is toggled.
-  //   - error_collection.is_enabled
-  //   - error_collection.is_active
-  //   - runtime_errors
-  //   - manifest_errors
-  //   - install_warnings
-  // An alternative approach would be to factor out the dev mode state from the
-  // above properties and allow the UI control what happens when dev mode
-  // changes. If the UI rendering performance is an issue, instead of replacing
-  // the entire extension info, a diff of the old and new extension info can be
-  // made by the UI and only perform a partial update of the extension info.
-  const ExtensionSet& extensions =
-      ExtensionRegistry::Get(profile_)->enabled_extensions();
-  for (const auto& extension : extensions) {
-    BroadcastItemStateChanged(developer::EventType::kPrefsChanged,
-                              extension->id());
-  }
-}
-
-void DeveloperPrivateEventRouter::BroadcastItemStateChanged(
-    developer::EventType event_type,
-    const ExtensionId& extension_id) {
-  std::unique_ptr<ExtensionInfoGenerator> info_generator(
-      new ExtensionInfoGenerator(profile_));
-  ExtensionInfoGenerator* info_generator_weak = info_generator.get();
-  info_generator_weak->CreateExtensionInfo(
-      extension_id,
-      base::BindOnce(
-          &DeveloperPrivateEventRouter::BroadcastItemStateChangedHelper,
-          weak_factory_.GetWeakPtr(), event_type, extension_id,
-          std::move(info_generator)));
-}
-
-void DeveloperPrivateEventRouter::BroadcastItemStateChangedHelper(
-    developer::EventType event_type,
-    const ExtensionId& extension_id,
-    std::unique_ptr<ExtensionInfoGenerator> info_generator,
-    ExtensionInfoGenerator::ExtensionInfoList infos) {
-  DCHECK_LE(infos.size(), 1u);
-
-  developer::EventData event_data;
-  event_data.event_type = event_type;
-  event_data.item_id = extension_id;
-  if (!infos.empty()) {
-    event_data.extension_info = std::move(infos[0]);
-  }
-
-  base::Value::List args;
-  args.Append(event_data.ToValue());
-  std::unique_ptr<Event> event(
-      new Event(events::DEVELOPER_PRIVATE_ON_ITEM_STATE_CHANGED,
-                developer::OnItemStateChanged::kEventName, std::move(args)));
-  event_router_->BroadcastEvent(std::move(event));
-}
-
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.h b/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.h
index a42af42..30bd538 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_event_router_desktop.h
@@ -5,9 +5,6 @@
 #ifndef CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_EVENT_ROUTER_DESKTOP_H_
 #define CHROME_BROWSER_EXTENSIONS_API_DEVELOPER_PRIVATE_DEVELOPER_PRIVATE_EVENT_ROUTER_DESKTOP_H_
 
-#include <memory>
-#include <vector>
-
 #include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "chrome/browser/extensions/account_extension_tracker.h"
@@ -71,18 +68,6 @@
   void OnExtensionUploadabilityChanged(const ExtensionId& id) override;
   void OnExtensionsUploadabilityChanged() override;
 
-  // Handles a profile preference change.
-  void OnProfilePrefChanged();
-
-  // Broadcasts an event to all listeners.
-  void BroadcastItemStateChanged(api::developer_private::EventType event_type,
-                                 const ExtensionId& id) override;
-  void BroadcastItemStateChangedHelper(
-      api::developer_private::EventType event_type,
-      const ExtensionId& extension_id,
-      std::unique_ptr<ExtensionInfoGenerator> info_generator,
-      std::vector<api::developer_private::ExtensionInfo> infos);
-
   base::ScopedObservation<AppWindowRegistry, AppWindowRegistry::Observer>
       app_window_registry_observation_{this};
   base::ScopedObservation<ExtensionManagement, ExtensionManagement::Observer>
@@ -96,8 +81,6 @@
   base::ScopedObservation<AccountExtensionTracker,
                           AccountExtensionTracker::Observer>
       account_extension_tracker_observation_{this};
-
-  base::WeakPtrFactory<DeveloperPrivateEventRouter> weak_factory_{this};
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.cc b/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.cc
index 42f55c5..805b1b74 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.cc
@@ -10,9 +10,11 @@
 
 #include "base/check.h"
 #include "base/values.h"
+#include "chrome/browser/extensions/api/developer_private/profile_info_generator.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/developer_private.h"
+#include "chrome/common/pref_names.h"
 #include "content/public/browser/render_frame_host.h"
 #include "extensions/browser/disable_reason.h"
 #include "extensions/browser/event_router.h"
@@ -58,6 +60,30 @@
   extension_prefs_observation_.Observe(ExtensionPrefs::Get(profile));
   warning_service_observation_.Observe(WarningService::Get(profile));
   permissions_manager_observation_.Observe(PermissionsManager::Get(profile));
+
+  pref_change_registrar_.Init(profile->GetPrefs());
+  // The unretained is safe, since the PrefChangeRegistrar unregisters the
+  // callback on destruction.
+  pref_change_registrar_.Add(
+      prefs::kExtensionsUIDeveloperMode,
+      base::BindRepeating(
+          &DeveloperPrivateEventRouterShared::OnProfilePrefChanged,
+          base::Unretained(this)));
+  pref_change_registrar_.Add(
+      kMV2DeprecationWarningAcknowledgedGloballyPref.name,
+      base::BindRepeating(
+          &DeveloperPrivateEventRouterShared::OnProfilePrefChanged,
+          base::Unretained(this)));
+  pref_change_registrar_.Add(
+      kMV2DeprecationDisabledAcknowledgedGloballyPref.name,
+      base::BindRepeating(
+          &DeveloperPrivateEventRouterShared::OnProfilePrefChanged,
+          base::Unretained(this)));
+  pref_change_registrar_.Add(
+      kMV2DeprecationUnsupportedAcknowledgedGloballyPref.name,
+      base::BindRepeating(
+          &DeveloperPrivateEventRouterShared::OnProfilePrefChanged,
+          base::Unretained(this)));
 }
 
 DeveloperPrivateEventRouterShared::~DeveloperPrivateEventRouterShared() =
@@ -203,8 +229,66 @@
                             extension.id());
 }
 
+void DeveloperPrivateEventRouterShared::OnProfilePrefChanged() {
+  base::Value::List args;
+  args.Append(CreateProfileInfo(profile_).ToValue());
+  auto event = std::make_unique<Event>(
+      events::DEVELOPER_PRIVATE_ON_PROFILE_STATE_CHANGED,
+      developer::OnProfileStateChanged::kEventName, std::move(args));
+  event_router_->BroadcastEvent(std::move(event));
+
+  // The following properties are updated when dev mode is toggled.
+  //   - error_collection.is_enabled
+  //   - error_collection.is_active
+  //   - runtime_errors
+  //   - manifest_errors
+  //   - install_warnings
+  // An alternative approach would be to factor out the dev mode state from the
+  // above properties and allow the UI control what happens when dev mode
+  // changes. If the UI rendering performance is an issue, instead of replacing
+  // the entire extension info, a diff of the old and new extension info can be
+  // made by the UI and only perform a partial update of the extension info.
+  const ExtensionSet& extensions =
+      ExtensionRegistry::Get(profile_)->enabled_extensions();
+  for (const auto& extension : extensions) {
+    BroadcastItemStateChanged(developer::EventType::kPrefsChanged,
+                              extension->id());
+  }
+}
+
 void DeveloperPrivateEventRouterShared::BroadcastItemStateChanged(
     developer::EventType event_type,
-    const ExtensionId& extension_id) {}
+    const ExtensionId& extension_id) {
+  auto info_generator = std::make_unique<ExtensionInfoGenerator>(profile_);
+  ExtensionInfoGenerator* info_generator_weak = info_generator.get();
+  info_generator_weak->CreateExtensionInfo(
+      extension_id,
+      base::BindOnce(
+          &DeveloperPrivateEventRouterShared::BroadcastItemStateChangedHelper,
+          weak_factory_.GetWeakPtr(), event_type, extension_id,
+          std::move(info_generator)));
+}
+
+void DeveloperPrivateEventRouterShared::BroadcastItemStateChangedHelper(
+    developer::EventType event_type,
+    const ExtensionId& extension_id,
+    std::unique_ptr<ExtensionInfoGenerator> info_generator,
+    ExtensionInfoGenerator::ExtensionInfoList infos) {
+  DCHECK_LE(infos.size(), 1u);
+
+  developer::EventData event_data;
+  event_data.event_type = event_type;
+  event_data.item_id = extension_id;
+  if (!infos.empty()) {
+    event_data.extension_info = std::move(infos[0]);
+  }
+
+  base::Value::List args;
+  args.Append(event_data.ToValue());
+  auto event = std::make_unique<Event>(
+      events::DEVELOPER_PRIVATE_ON_ITEM_STATE_CHANGED,
+      developer::OnItemStateChanged::kEventName, std::move(args));
+  event_router_->BroadcastEvent(std::move(event));
+}
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.h b/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.h
index 7afe6e3e..8ec652e 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_event_router_shared.h
@@ -8,7 +8,9 @@
 #include <set>
 
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
+#include "chrome/browser/extensions/api/developer_private/extension_info_generator.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/common/extensions/api/developer_private.h"
@@ -56,6 +58,8 @@
   // has changed in a way that may affect the chrome://extensions UI.
   void OnExtensionConfigurationChanged(const ExtensionId& extension_id);
 
+  // TODO(crbug.com/392777363): Make them all private after moving all the
+  // usages to shared.cc.
  protected:
   raw_ptr<Profile> profile_;
 
@@ -63,6 +67,10 @@
 
   PrefChangeRegistrar pref_change_registrar_;
 
+  // Broadcasts an event to all listeners.
+  void BroadcastItemStateChanged(api::developer_private::EventType event_type,
+                                 const ExtensionId& id);
+
  private:
   // ExtensionRegistryObserver:
   void OnExtensionLoaded(content::BrowserContext* browser_context,
@@ -112,10 +120,14 @@
       const PermissionSet& permissions,
       PermissionsManager::UpdateReason reason) override;
 
-  // Broadcasts an event to all listeners.
-  virtual void BroadcastItemStateChanged(
+  // Handles a profile preference change.
+  void OnProfilePrefChanged();
+
+  void BroadcastItemStateChangedHelper(
       api::developer_private::EventType event_type,
-      const ExtensionId& id);
+      const ExtensionId& extension_id,
+      std::unique_ptr<ExtensionInfoGenerator> info_generator,
+      std::vector<api::developer_private::ExtensionInfo> infos);
 
   base::ScopedObservation<ExtensionRegistry, ExtensionRegistryObserver>
       extension_registry_observation_{this};
@@ -137,6 +149,8 @@
   // update. In particular, we want to avoid entering a loop, which could happen
   // when, e.g., the Apps Developer Tool throws an error.
   std::set<ExtensionId> extension_ids_;
+
+  base::WeakPtrFactory<DeveloperPrivateEventRouterShared> weak_factory_{this};
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_android.cc b/chrome/browser/extensions/api/developer_private/developer_private_functions_android.cc
index fc06ee1..648f0fe 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_android.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_android.cc
@@ -6,11 +6,6 @@
 
 #include "extensions/browser/extension_function.h"
 
-DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateAutoUpdateFunction,
-                                        "developerPrivate.autoUpdate")
-DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(
-    DeveloperPrivateGetExtensionSizeFunction,
-    "developerPrivate.getExtensionSize")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateReloadFunction,
                                         "developerPrivate.reload")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateLoadUnpackedFunction,
@@ -21,15 +16,10 @@
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(
     DeveloperPrivateNotifyDragInstallInProgressFunction,
     "developerPrivate.notifyDragInstallInProgress")
-DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateChoosePathFunction,
-                                        "developerPrivate.choosePath")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivatePackDirectoryFunction,
                                         "developerPrivate.packDirectory")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateLoadDirectoryFunction,
                                         "developerPrivate.loadDirectory")
-DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(
-    DeveloperPrivateRequestFileSourceFunction,
-    "developerPrivate.requestFileSource")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateRepairExtensionFunction,
                                         "developerPrivate.repairExtension")
 DEFINE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateShowOptionsFunction,
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_android.h b/chrome/browser/extensions/api/developer_private/developer_private_functions_android.h
index 22324e0..07ebcdb 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_android.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_android.h
@@ -8,12 +8,6 @@
 #include "chrome/common/extensions/api/developer_private.h"
 #include "extensions/browser/extension_function.h"
 
-DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateAutoUpdateFunction,
-                   "developerPrivate.autoUpdate",
-                   DEVELOPERPRIVATE_AUTOUPDATE);
-DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateGetExtensionSizeFunction,
-                   "developerPrivate.getExtensionSize",
-                   DEVELOPERPRIVATE_GETEXTENSIONSIZE);
 DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateReloadFunction,
                    "developerPrivate.reload",
                    DEVELOPERPRIVATE_RELOAD);
@@ -26,18 +20,12 @@
 DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateNotifyDragInstallInProgressFunction,
                    "developerPrivate.notifyDragInstallInProgress",
                    DEVELOPERPRIVATE_NOTIFYDRAGINSTALLINPROGRESS);
-DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateChoosePathFunction,
-                   "developerPrivate.choosePath",
-                   DEVELOPERPRIVATE_CHOOSEPATH);
 DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivatePackDirectoryFunction,
                    "developerPrivate.packDirectory",
                    DEVELOPERPRIVATE_PACKDIRECTORY);
 DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateLoadDirectoryFunction,
                    "developerPrivate.loadDirectory",
                    DEVELOPERPRIVATE_LOADUNPACKEDCROS);
-DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateRequestFileSourceFunction,
-                   "developerPrivate.requestFileSource",
-                   DEVELOPERPRIVATE_REQUESTFILESOURCE);
 DECLARE_UNIMPLEMENTED_EXTENSION_FUNCTION(DeveloperPrivateRepairExtensionFunction,
                    "developerPrivate.repairExtension",
                    DEVELOPERPRIVATE_REPAIREXTENSION);
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.cc b/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.cc
index 13c589f4..d9989ce1 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.cc
@@ -126,6 +126,8 @@
   return ExtensionSystem::Get(context)->extension_service();
 }
 
+// TODO(crbug.com/392777363): Remove this function moving all its usage to
+// shared.cc.
 std::string ReadFileToString(const base::FilePath& path) {
   std::string data;
   // This call can fail, but it doesn't matter for our purposes. If it fails,
@@ -196,57 +198,6 @@
 
 namespace api {
 
-DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() =
-    default;
-
-ExtensionFunction::ResponseAction DeveloperPrivateAutoUpdateFunction::Run() {
-  Profile* profile = Profile::FromBrowserContext(browser_context());
-  ExtensionUpdater* updater = ExtensionUpdater::Get(profile);
-  if (updater->enabled()) {
-    ExtensionUpdater::CheckParams params;
-    params.fetch_priority = DownloadFetchPriority::kForeground;
-    params.install_immediately = true;
-    params.callback =
-        base::BindOnce(&DeveloperPrivateAutoUpdateFunction::OnComplete, this);
-    updater->CheckNow(std::move(params));
-  }
-  return RespondLater();
-}
-
-void DeveloperPrivateAutoUpdateFunction::OnComplete() {
-  Respond(NoArguments());
-}
-
-DeveloperPrivateGetExtensionSizeFunction::
-    DeveloperPrivateGetExtensionSizeFunction() = default;
-
-DeveloperPrivateGetExtensionSizeFunction::
-    ~DeveloperPrivateGetExtensionSizeFunction() = default;
-
-ExtensionFunction::ResponseAction
-DeveloperPrivateGetExtensionSizeFunction::Run() {
-  std::optional<developer::GetExtensionSize::Params> params =
-      developer::GetExtensionSize::Params::Create(args());
-  EXTENSION_FUNCTION_VALIDATE(params);
-
-  const Extension* extension = GetExtensionById(params->id);
-  if (!extension) {
-    return RespondNow(Error(kNoSuchExtensionError));
-  }
-
-  extensions::path_util::CalculateAndFormatExtensionDirectorySize(
-      extension->path(), IDS_APPLICATION_INFO_SIZE_SMALL_LABEL,
-      base::BindOnce(
-          &DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated, this));
-
-  return RespondLater();
-}
-
-void DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated(
-    const std::u16string& size) {
-  Respond(WithArguments(size));
-}
-
 DeveloperPrivateReloadFunction::DeveloperPrivateReloadFunction() = default;
 DeveloperPrivateReloadFunction::~DeveloperPrivateReloadFunction() = default;
 
@@ -835,168 +786,6 @@
 DeveloperPrivateLoadDirectoryFunction::
     ~DeveloperPrivateLoadDirectoryFunction() {}
 
-DeveloperPrivateChoosePathFunction::DeveloperPrivateChoosePathFunction() =
-    default;
-
-DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {
-  // There may be pending file dialogs, we need to tell them that we've gone
-  // away so they don't try and call back to us.
-  if (select_file_dialog_.get()) {
-    select_file_dialog_->ListenerDestroyed();
-  }
-}
-
-ExtensionFunction::ResponseAction DeveloperPrivateChoosePathFunction::Run() {
-  std::optional<developer::ChoosePath::Params> params =
-      developer::ChoosePath::Params::Create(args());
-  EXTENSION_FUNCTION_VALIDATE(params);
-
-  content::WebContents* web_contents = GetSenderWebContents();
-  if (!web_contents) {
-    return RespondNow(Error(kCouldNotShowSelectFileDialogError));
-  }
-
-  // Start or cancel the file selection without showing the select file dialog
-  // for tests that require it.
-  if (accept_dialog_for_testing_.has_value()) {
-    AddRef();  // Balanced in FileSelected() / FileSelectionCanceled().
-    if (accept_dialog_for_testing_.value()) {
-      CHECK(selected_file_for_testing_.has_value());
-      FileSelected(selected_file_for_testing_.value(), /*index=*/0);
-    } else {
-      FileSelectionCanceled();
-    }
-    CHECK(did_respond());
-    return AlreadyResponded();
-  }
-
-  ui::SelectFileDialog::Type file_type = ui::SelectFileDialog::SELECT_FOLDER;
-  ui::SelectFileDialog::FileTypeInfo file_type_info;
-  std::u16string select_title;
-
-  if (params->select_type == developer::SelectType::kFile) {
-    file_type = ui::SelectFileDialog::SELECT_OPEN_FILE;
-  }
-
-  int file_type_index = 0;
-  if (params->file_type == developer::FileType::kLoad) {
-    select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
-  } else if (params->file_type == developer::FileType::kPem) {
-    select_title =
-        l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
-    file_type_info.extensions.emplace_back(1, FILE_PATH_LITERAL("pem"));
-    file_type_info.extension_description_overrides.push_back(
-        l10n_util::GetStringUTF16(
-            IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
-    file_type_info.include_all_files = true;
-    file_type_index = 1;
-  } else {
-    NOTREACHED();
-  }
-
-  const base::FilePath last_directory =
-      DeveloperPrivateAPI::Get(browser_context())->last_unpacked_directory();
-  gfx::NativeWindow owning_window =
-      platform_util::GetTopLevel(web_contents->GetNativeView());
-
-  select_file_dialog_ = ui::SelectFileDialog::Create(
-      this, std::make_unique<ChromeSelectFilePolicy>(web_contents));
-  select_file_dialog_->SelectFile(file_type, select_title, last_directory,
-                                  &file_type_info, file_type_index,
-                                  base::FilePath::StringType(), owning_window);
-
-  AddRef();  // Balanced in FileSelected() / FileSelectionCanceled().
-  return RespondLater();
-}
-
-void DeveloperPrivateChoosePathFunction::FileSelected(
-    const ui::SelectedFileInfo& file,
-    int index) {
-  Respond(WithArguments(file.path().LossyDisplayName()));
-  Release();
-}
-
-void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
-  // This isn't really an error, but we should keep it like this for
-  // backward compatability.
-  Respond(Error(kFileSelectionCanceled));
-  Release();
-}
-
-DeveloperPrivateRequestFileSourceFunction::
-    DeveloperPrivateRequestFileSourceFunction() = default;
-
-DeveloperPrivateRequestFileSourceFunction::
-    ~DeveloperPrivateRequestFileSourceFunction() = default;
-
-ExtensionFunction::ResponseAction
-DeveloperPrivateRequestFileSourceFunction::Run() {
-  params_ = developer::RequestFileSource::Params::Create(args());
-  EXTENSION_FUNCTION_VALIDATE(params_);
-
-  const developer::RequestFileSourceProperties& properties =
-      params_->properties;
-  const Extension* extension = GetExtensionById(properties.extension_id);
-  if (!extension) {
-    return RespondNow(Error(kNoSuchExtensionError));
-  }
-
-  // Under no circumstances should we ever need to reference a file outside of
-  // the extension's directory. If it tries to, abort.
-  base::FilePath path_suffix =
-      base::FilePath::FromUTF8Unsafe(properties.path_suffix);
-  if (path_suffix.empty() || path_suffix.ReferencesParent()) {
-    return RespondNow(Error(kInvalidPathError));
-  }
-
-  if (properties.path_suffix == kManifestFile && !properties.manifest_key) {
-    return RespondNow(Error(kManifestKeyIsRequiredError));
-  }
-
-  base::ThreadPool::PostTaskAndReplyWithResult(
-      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
-      base::BindOnce(&ReadFileToString, extension->path().Append(path_suffix)),
-      base::BindOnce(&DeveloperPrivateRequestFileSourceFunction::Finish, this));
-
-  return RespondLater();
-}
-
-void DeveloperPrivateRequestFileSourceFunction::Finish(
-    const std::string& file_contents) {
-  const developer::RequestFileSourceProperties& properties =
-      params_->properties;
-  const Extension* extension = GetExtensionById(properties.extension_id);
-  if (!extension) {
-    Respond(Error(kNoSuchExtensionError));
-    return;
-  }
-
-  developer::RequestFileSourceResponse response;
-  base::FilePath path_suffix =
-      base::FilePath::FromUTF8Unsafe(properties.path_suffix);
-  base::FilePath path = extension->path().Append(path_suffix);
-  response.title = base::StringPrintf("%s: %s", extension->name().c_str(),
-                                      path.BaseName().AsUTF8Unsafe().c_str());
-  response.message = properties.message;
-
-  std::unique_ptr<FileHighlighter> highlighter;
-  if (properties.path_suffix == kManifestFile) {
-    highlighter = std::make_unique<ManifestHighlighter>(
-        file_contents, *properties.manifest_key,
-        properties.manifest_specific ? *properties.manifest_specific
-                                     : std::string());
-  } else {
-    highlighter = std::make_unique<SourceHighlighter>(
-        file_contents, properties.line_number ? *properties.line_number : 0);
-  }
-
-  response.before_highlight = highlighter->GetBeforeFeature();
-  response.highlight = highlighter->GetFeature();
-  response.after_highlight = highlighter->GetAfterFeature();
-
-  Respond(WithArguments(response.ToValue()));
-}
-
 DeveloperPrivateRepairExtensionFunction::
     ~DeveloperPrivateRepairExtensionFunction() = default;
 
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.h b/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.h
index 6aab489..fea87f6d 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_desktop.h
@@ -38,39 +38,6 @@
 
 namespace api {
 
-class DeveloperPrivateAutoUpdateFunction : public DeveloperPrivateAPIFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("developerPrivate.autoUpdate",
-                             DEVELOPERPRIVATE_AUTOUPDATE)
-
- protected:
-  ~DeveloperPrivateAutoUpdateFunction() override;
-  ResponseAction Run() override;
-
- private:
-  void OnComplete();
-};
-
-class DeveloperPrivateGetExtensionSizeFunction
-    : public DeveloperPrivateAPIFunction {
- public:
-  DeveloperPrivateGetExtensionSizeFunction();
-
-  DeveloperPrivateGetExtensionSizeFunction(
-      const DeveloperPrivateGetExtensionSizeFunction&) = delete;
-  DeveloperPrivateGetExtensionSizeFunction& operator=(
-      const DeveloperPrivateGetExtensionSizeFunction&) = delete;
-
-  DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionSize",
-                             DEVELOPERPRIVATE_GETEXTENSIONSIZE)
-
- private:
-  ~DeveloperPrivateGetExtensionSizeFunction() override;
-  ResponseAction Run() override;
-
-  void OnSizeCalculated(const std::u16string& size);
-};
-
 class DeveloperPrivateReloadFunction : public DeveloperPrivateAPIFunction,
                                        public ExtensionRegistryObserver,
                                        public LoadErrorReporter::Observer {
@@ -186,41 +153,6 @@
   std::optional<ui::SelectedFileInfo> selected_file_for_testing_;
 };
 
-class DeveloperPrivateChoosePathFunction
-    : public DeveloperPrivateAPIFunction,
-      public ui::SelectFileDialog::Listener {
- public:
-  DECLARE_EXTENSION_FUNCTION("developerPrivate.choosePath",
-                             DEVELOPERPRIVATE_CHOOSEPATH)
-  DeveloperPrivateChoosePathFunction();
-
-  // ui::SelectFileDialog::Listener:
-  void FileSelected(const ui::SelectedFileInfo& file, int index) override;
-  void FileSelectionCanceled() override;
-
-  // For testing:
-  void set_accept_dialog_for_testing(bool accept) {
-    accept_dialog_for_testing_ = accept;
-  }
-  void set_selected_file_for_testing(const ui::SelectedFileInfo& file) {
-    selected_file_for_testing_ = file;
-  }
-
- protected:
-  ~DeveloperPrivateChoosePathFunction() override;
-  ResponseAction Run() override;
-
- private:
-  // The dialog with the select file picker.
-  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
-
-  // For testing:
-  // Whether to accept or reject the select file dialog without showing it.
-  std::optional<bool> accept_dialog_for_testing_;
-  // File to load when accepting the select file dialog without showing it.
-  std::optional<ui::SelectedFileInfo> selected_file_for_testing_;
-};
-
 class DeveloperPrivatePackDirectoryFunction
     : public DeveloperPrivateAPIFunction,
       public PackExtensionJob::Client {
@@ -305,23 +237,6 @@
   std::string error_;
 };
 
-class DeveloperPrivateRequestFileSourceFunction
-    : public DeveloperPrivateAPIFunction {
- public:
-  DECLARE_EXTENSION_FUNCTION("developerPrivate.requestFileSource",
-                             DEVELOPERPRIVATE_REQUESTFILESOURCE)
-  DeveloperPrivateRequestFileSourceFunction();
-
- protected:
-  ~DeveloperPrivateRequestFileSourceFunction() override;
-  ResponseAction Run() override;
-
- private:
-  void Finish(const std::string& file_contents);
-
-  std::optional<api::developer_private::RequestFileSource::Params> params_;
-};
-
 class DeveloperPrivateRepairExtensionFunction
     : public DeveloperPrivateAPIFunction {
  public:
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc
index 38da243..6a3d3b2 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.cc
@@ -5,7 +5,9 @@
 #include "chrome/browser/extensions/api/developer_private/developer_private_functions_shared.h"
 
 #include "base/barrier_closure.h"
+#include "base/files/file_util.h"
 #include "base/strings/utf_string_conversions.h"
+#include "base/task/thread_pool.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/extensions/api/developer_private/developer_private_api.h"
 #include "chrome/browser/extensions/api/developer_private/developer_private_event_router.h"
@@ -16,14 +18,19 @@
 #include "chrome/browser/extensions/extension_util.h"
 #include "chrome/browser/extensions/permissions/permissions_updater.h"
 #include "chrome/browser/extensions/permissions/scripting_permissions_modifier.h"
+#include "chrome/browser/extensions/updater/extension_updater.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/supervised_user/supervised_user_browser_utils.h"
+#include "chrome/browser/ui/chrome_select_file_policy.h"
 #include "chrome/browser/ui/safety_hub/menu_notification_service_factory.h"
+#include "chrome/grit/generated_resources.h"
 #include "content/public/common/drop_data.h"
 #include "extensions/browser/extension_prefs.h"
 #include "extensions/browser/extension_registrar.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_system.h"
+#include "extensions/browser/file_highlighter.h"
+#include "extensions/browser/path_util.h"
 #include "extensions/browser/permissions_manager.h"
 #include "extensions/browser/ui_util.h"
 #include "extensions/browser/user_script_manager.h"
@@ -31,6 +38,7 @@
 #include "extensions/common/permissions/permissions_data.h"
 #include "net/base/filename_util.h"
 #include "ui/base/clipboard/file_info.h"
+#include "ui/base/l10n/l10n_util.h"
 
 #if !BUILDFLAG(IS_ANDROID)
 #include "chrome/browser/extensions/chrome_zipfile_installer.h"
@@ -55,6 +63,14 @@
 
 ui::FileInfo* g_drop_file_for_testing = nullptr;
 
+std::string ReadFileToString(const base::FilePath& path) {
+  std::string data;
+  // This call can fail, but it doesn't matter for our purposes. If it fails,
+  // we simply return an empty string for the manifest, and ignore it.
+  std::ignore = base::ReadFileToString(path, &data);
+  return data;
+}
+
 std::optional<URLPattern> ParseRuntimePermissionsPattern(
     const std::string& pattern_str) {
   constexpr int kValidRuntimePermissionSchemes = URLPattern::SCHEME_HTTP |
@@ -270,6 +286,27 @@
       .GetByID(id);
 }
 
+DeveloperPrivateAutoUpdateFunction::~DeveloperPrivateAutoUpdateFunction() =
+    default;
+
+ExtensionFunction::ResponseAction DeveloperPrivateAutoUpdateFunction::Run() {
+  Profile* profile = Profile::FromBrowserContext(browser_context());
+  ExtensionUpdater* updater = ExtensionUpdater::Get(profile);
+  if (updater->enabled()) {
+    ExtensionUpdater::CheckParams params;
+    params.fetch_priority = DownloadFetchPriority::kForeground;
+    params.install_immediately = true;
+    params.callback =
+        base::BindOnce(&DeveloperPrivateAutoUpdateFunction::OnComplete, this);
+    updater->CheckNow(std::move(params));
+  }
+  return RespondLater();
+}
+
+void DeveloperPrivateAutoUpdateFunction::OnComplete() {
+  Respond(NoArguments());
+}
+
 DeveloperPrivateGetExtensionsInfoFunction::
     DeveloperPrivateGetExtensionsInfoFunction() = default;
 
@@ -335,6 +372,36 @@
                        : WithArguments(list[0].ToValue()));
 }
 
+DeveloperPrivateGetExtensionSizeFunction::
+    DeveloperPrivateGetExtensionSizeFunction() = default;
+
+DeveloperPrivateGetExtensionSizeFunction::
+    ~DeveloperPrivateGetExtensionSizeFunction() = default;
+
+ExtensionFunction::ResponseAction
+DeveloperPrivateGetExtensionSizeFunction::Run() {
+  std::optional<developer::GetExtensionSize::Params> params =
+      developer::GetExtensionSize::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  const Extension* extension = GetExtensionById(params->id);
+  if (!extension) {
+    return RespondNow(Error(kNoSuchExtensionError));
+  }
+
+  extensions::path_util::CalculateAndFormatExtensionDirectorySize(
+      extension->path(), IDS_APPLICATION_INFO_SIZE_SMALL_LABEL,
+      base::BindOnce(
+          &DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated, this));
+
+  return RespondLater();
+}
+
+void DeveloperPrivateGetExtensionSizeFunction::OnSizeCalculated(
+    const std::u16string& size) {
+  Respond(WithArguments(size));
+}
+
 DeveloperPrivateGetProfileConfigurationFunction::
     ~DeveloperPrivateGetProfileConfigurationFunction() = default;
 
@@ -1089,6 +1156,168 @@
   return RespondNow(NoArguments());
 }
 
+DeveloperPrivateChoosePathFunction::DeveloperPrivateChoosePathFunction() =
+    default;
+
+DeveloperPrivateChoosePathFunction::~DeveloperPrivateChoosePathFunction() {
+  // There may be pending file dialogs, we need to tell them that we've gone
+  // away so they don't try and call back to us.
+  if (select_file_dialog_.get()) {
+    select_file_dialog_->ListenerDestroyed();
+  }
+}
+
+ExtensionFunction::ResponseAction DeveloperPrivateChoosePathFunction::Run() {
+  std::optional<developer::ChoosePath::Params> params =
+      developer::ChoosePath::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params);
+
+  content::WebContents* web_contents = GetSenderWebContents();
+  if (!web_contents) {
+    return RespondNow(Error(kCouldNotShowSelectFileDialogError));
+  }
+
+  // Start or cancel the file selection without showing the select file dialog
+  // for tests that require it.
+  if (accept_dialog_for_testing_.has_value()) {
+    AddRef();  // Balanced in FileSelected() / FileSelectionCanceled().
+    if (accept_dialog_for_testing_.value()) {
+      CHECK(selected_file_for_testing_.has_value());
+      FileSelected(selected_file_for_testing_.value(), /*index=*/0);
+    } else {
+      FileSelectionCanceled();
+    }
+    CHECK(did_respond());
+    return AlreadyResponded();
+  }
+
+  ui::SelectFileDialog::Type file_type = ui::SelectFileDialog::SELECT_FOLDER;
+  ui::SelectFileDialog::FileTypeInfo file_type_info;
+  std::u16string select_title;
+
+  if (params->select_type == developer::SelectType::kFile) {
+    file_type = ui::SelectFileDialog::SELECT_OPEN_FILE;
+  }
+
+  int file_type_index = 0;
+  if (params->file_type == developer::FileType::kLoad) {
+    select_title = l10n_util::GetStringUTF16(IDS_EXTENSION_LOAD_FROM_DIRECTORY);
+  } else if (params->file_type == developer::FileType::kPem) {
+    select_title =
+        l10n_util::GetStringUTF16(IDS_EXTENSION_PACK_DIALOG_SELECT_KEY);
+    file_type_info.extensions.emplace_back(1, FILE_PATH_LITERAL("pem"));
+    file_type_info.extension_description_overrides.push_back(
+        l10n_util::GetStringUTF16(
+            IDS_EXTENSION_PACK_DIALOG_KEY_FILE_TYPE_DESCRIPTION));
+    file_type_info.include_all_files = true;
+    file_type_index = 1;
+  } else {
+    NOTREACHED();
+  }
+
+  const base::FilePath last_directory =
+      DeveloperPrivateAPI::Get(browser_context())->last_unpacked_directory();
+  gfx::NativeWindow owning_window =
+      platform_util::GetTopLevel(web_contents->GetNativeView());
+
+  select_file_dialog_ = ui::SelectFileDialog::Create(
+      this, std::make_unique<ChromeSelectFilePolicy>(web_contents));
+  select_file_dialog_->SelectFile(file_type, select_title, last_directory,
+                                  &file_type_info, file_type_index,
+                                  base::FilePath::StringType(), owning_window);
+
+  AddRef();  // Balanced in FileSelected() / FileSelectionCanceled().
+  return RespondLater();
+}
+
+void DeveloperPrivateChoosePathFunction::FileSelected(
+    const ui::SelectedFileInfo& file,
+    int index) {
+  Respond(WithArguments(file.path().LossyDisplayName()));
+  Release();
+}
+
+void DeveloperPrivateChoosePathFunction::FileSelectionCanceled() {
+  // This isn't really an error, but we should keep it like this for
+  // backward compatability.
+  Respond(Error(kFileSelectionCanceled));
+  Release();
+}
+
+DeveloperPrivateRequestFileSourceFunction::
+    DeveloperPrivateRequestFileSourceFunction() = default;
+
+DeveloperPrivateRequestFileSourceFunction::
+    ~DeveloperPrivateRequestFileSourceFunction() = default;
+
+ExtensionFunction::ResponseAction
+DeveloperPrivateRequestFileSourceFunction::Run() {
+  params_ = developer::RequestFileSource::Params::Create(args());
+  EXTENSION_FUNCTION_VALIDATE(params_);
+
+  const developer::RequestFileSourceProperties& properties =
+      params_->properties;
+  const Extension* extension = GetExtensionById(properties.extension_id);
+  if (!extension) {
+    return RespondNow(Error(kNoSuchExtensionError));
+  }
+
+  // Under no circumstances should we ever need to reference a file outside of
+  // the extension's directory. If it tries to, abort.
+  base::FilePath path_suffix =
+      base::FilePath::FromUTF8Unsafe(properties.path_suffix);
+  if (path_suffix.empty() || path_suffix.ReferencesParent()) {
+    return RespondNow(Error(kInvalidPathError));
+  }
+
+  if (properties.path_suffix == kManifestFile && !properties.manifest_key) {
+    return RespondNow(Error(kManifestKeyIsRequiredError));
+  }
+
+  base::ThreadPool::PostTaskAndReplyWithResult(
+      FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE},
+      base::BindOnce(&ReadFileToString, extension->path().Append(path_suffix)),
+      base::BindOnce(&DeveloperPrivateRequestFileSourceFunction::Finish, this));
+
+  return RespondLater();
+}
+
+void DeveloperPrivateRequestFileSourceFunction::Finish(
+    const std::string& file_contents) {
+  const developer::RequestFileSourceProperties& properties =
+      params_->properties;
+  const Extension* extension = GetExtensionById(properties.extension_id);
+  if (!extension) {
+    Respond(Error(kNoSuchExtensionError));
+    return;
+  }
+
+  developer::RequestFileSourceResponse response;
+  base::FilePath path_suffix =
+      base::FilePath::FromUTF8Unsafe(properties.path_suffix);
+  base::FilePath path = extension->path().Append(path_suffix);
+  response.title = base::StringPrintf("%s: %s", extension->name().c_str(),
+                                      path.BaseName().AsUTF8Unsafe().c_str());
+  response.message = properties.message;
+
+  std::unique_ptr<FileHighlighter> highlighter;
+  if (properties.path_suffix == kManifestFile) {
+    highlighter = std::make_unique<ManifestHighlighter>(
+        file_contents, *properties.manifest_key,
+        properties.manifest_specific ? *properties.manifest_specific
+                                     : std::string());
+  } else {
+    highlighter = std::make_unique<SourceHighlighter>(
+        file_contents, properties.line_number ? *properties.line_number : 0);
+  }
+
+  response.before_highlight = highlighter->GetBeforeFeature();
+  response.highlight = highlighter->GetFeature();
+  response.after_highlight = highlighter->GetAfterFeature();
+
+  Respond(WithArguments(response.ToValue()));
+}
+
 DeveloperPrivateOpenDevToolsFunction::DeveloperPrivateOpenDevToolsFunction() =
     default;
 DeveloperPrivateOpenDevToolsFunction::~DeveloperPrivateOpenDevToolsFunction() =
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.h b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.h
index 09f5c79..1f1a13d 100644
--- a/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.h
+++ b/chrome/browser/extensions/api/developer_private/developer_private_functions_shared.h
@@ -10,6 +10,8 @@
 #include "extensions/browser/extension_function.h"
 #include "extensions/common/extension.h"
 #include "ui/base/clipboard/file_info.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+#include "ui/shell_dialogs/selected_file_info.h"
 
 namespace extensions::api {
 
@@ -81,6 +83,19 @@
   const Extension* GetEnabledExtensionById(const ExtensionId& id);
 };
 
+class DeveloperPrivateAutoUpdateFunction : public DeveloperPrivateAPIFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("developerPrivate.autoUpdate",
+                             DEVELOPERPRIVATE_AUTOUPDATE)
+
+ protected:
+  ~DeveloperPrivateAutoUpdateFunction() override;
+  ResponseAction Run() override;
+
+ private:
+  void OnComplete();
+};
+
 class DeveloperPrivateGetExtensionsInfoFunction
     : public DeveloperPrivateAPIFunction {
  public:
@@ -127,6 +142,26 @@
   std::unique_ptr<ExtensionInfoGenerator> info_generator_;
 };
 
+class DeveloperPrivateGetExtensionSizeFunction
+    : public DeveloperPrivateAPIFunction {
+ public:
+  DeveloperPrivateGetExtensionSizeFunction();
+
+  DeveloperPrivateGetExtensionSizeFunction(
+      const DeveloperPrivateGetExtensionSizeFunction&) = delete;
+  DeveloperPrivateGetExtensionSizeFunction& operator=(
+      const DeveloperPrivateGetExtensionSizeFunction&) = delete;
+
+  DECLARE_EXTENSION_FUNCTION("developerPrivate.getExtensionSize",
+                             DEVELOPERPRIVATE_GETEXTENSIONSIZE)
+
+ private:
+  ~DeveloperPrivateGetExtensionSizeFunction() override;
+  ResponseAction Run() override;
+
+  void OnSizeCalculated(const std::u16string& size);
+};
+
 class DeveloperPrivateGetProfileConfigurationFunction
     : public DeveloperPrivateAPIFunction {
  public:
@@ -383,6 +418,58 @@
       override;
 };
 
+class DeveloperPrivateChoosePathFunction
+    : public DeveloperPrivateAPIFunction,
+      public ui::SelectFileDialog::Listener {
+ public:
+  DECLARE_EXTENSION_FUNCTION("developerPrivate.choosePath",
+                             DEVELOPERPRIVATE_CHOOSEPATH)
+  DeveloperPrivateChoosePathFunction();
+
+  // ui::SelectFileDialog::Listener:
+  void FileSelected(const ui::SelectedFileInfo& file, int index) override;
+  void FileSelectionCanceled() override;
+
+  // For testing:
+  void set_accept_dialog_for_testing(bool accept) {
+    accept_dialog_for_testing_ = accept;
+  }
+  void set_selected_file_for_testing(const ui::SelectedFileInfo& file) {
+    selected_file_for_testing_ = file;
+  }
+
+ protected:
+  ~DeveloperPrivateChoosePathFunction() override;
+  ResponseAction Run() override;
+
+ private:
+  // The dialog with the select file picker.
+  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
+
+  // For testing:
+  // Whether to accept or reject the select file dialog without showing it.
+  std::optional<bool> accept_dialog_for_testing_;
+  // File to load when accepting the select file dialog without showing it.
+  std::optional<ui::SelectedFileInfo> selected_file_for_testing_;
+};
+
+class DeveloperPrivateRequestFileSourceFunction
+    : public DeveloperPrivateAPIFunction {
+ public:
+  DECLARE_EXTENSION_FUNCTION("developerPrivate.requestFileSource",
+                             DEVELOPERPRIVATE_REQUESTFILESOURCE)
+  DeveloperPrivateRequestFileSourceFunction();
+
+ protected:
+  ~DeveloperPrivateRequestFileSourceFunction() override;
+  ResponseAction Run() override;
+
+ private:
+  void Finish(const std::string& file_contents);
+
+  std::optional<api::developer_private::RequestFileSource::Params> params_;
+};
+
 class DeveloperPrivateOpenDevToolsFunction
     : public DeveloperPrivateAPIFunction {
  public:
diff --git a/chrome/browser/extensions/api/printing/printing_api_utils.cc b/chrome/browser/extensions/api/printing/printing_api_utils.cc
index a55da98..cb0c760 100644
--- a/chrome/browser/extensions/api/printing/printing_api_utils.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_utils.cc
@@ -14,6 +14,7 @@
 #include "base/containers/flat_map.h"
 #include "base/containers/flat_set.h"
 #include "base/json/json_reader.h"
+#include "base/metrics/histogram_functions.h"
 #include "base/no_destructor.h"
 #include "base/notreached.h"
 #include "base/values.h"
@@ -380,13 +381,19 @@
 
   if (base::FeatureList::IsEnabled(
           printing::features::kApiPrintingMarginsAndScale)) {
+    // Default value is `kUnknownPrintScalingType`, so we only need to check if
+    // the value is not the default.
     if (settings.print_scaling() !=
-            printing::mojom::PrintScalingType::kUnknownPrintScalingType &&
-        !base::Contains(capabilities.print_scaling_types,
-                        settings.print_scaling())) {
-      LOG(ERROR) << "Print scaling '" << settings.print_scaling()
-                 << "' is not compatible with printer capabilities";
-      return false;
+        printing::mojom::PrintScalingType::kUnknownPrintScalingType) {
+      const bool uses_supported_print_scaling = base::Contains(
+          capabilities.print_scaling_types, settings.print_scaling());
+      base::UmaHistogramBoolean("Extensions.Printing.UsesSupportedPrintScaling",
+                                uses_supported_print_scaling);
+      if (!uses_supported_print_scaling) {
+        LOG(ERROR) << "Print scaling '" << settings.print_scaling()
+                   << "' is not compatible with printer capabilities";
+        return false;
+      }
     }
 
     if (settings.margin_type() !=
diff --git a/chrome/browser/extensions/api/printing/printing_api_utils_unittest.cc b/chrome/browser/extensions/api/printing/printing_api_utils_unittest.cc
index 2eb67bb..5374aee 100644
--- a/chrome/browser/extensions/api/printing/printing_api_utils_unittest.cc
+++ b/chrome/browser/extensions/api/printing/printing_api_utils_unittest.cc
@@ -5,6 +5,7 @@
 #include "chrome/browser/extensions/api/printing/printing_api_utils.h"
 
 #include "base/strings/stringprintf.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/values_test_util.h"
 #include "chromeos/crosapi/mojom/local_printer.mojom.h"
@@ -850,4 +851,71 @@
   }
 }
 
+TEST(PrintingApiUtilsTest, CheckSettingsAndCapabilities_PrintScalingHistogram) {
+  std::unique_ptr<printing::PrintSettings> settings = ConstructPrintSettings();
+  printing::PrinterSemanticCapsAndDefaults capabilities =
+      ConstructPrinterCapabilities();
+  // Set supported print scaling types.
+  capabilities.print_scaling_types = {printing::mojom::PrintScalingType::kFit,
+                                      printing::mojom::PrintScalingType::kAuto};
+
+  // Try with the feature disabled first - no matter if the print scaling is
+  // correct or not, the histogram should not be recorded.
+  {
+    base::HistogramTester histogram_tester;
+    base::test::ScopedFeatureList feature_list;
+    feature_list.InitAndDisableFeature(
+        printing::features::kApiPrintingMarginsAndScale);
+
+    // Unsupported print scaling.
+    settings->set_print_scaling(printing::mojom::PrintScalingType::kFill);
+    ASSERT_TRUE(
+        CheckSettingsAndCapabilitiesCompatibility(*settings, capabilities));
+
+    // Supported print scaling.
+    settings->set_print_scaling(printing::mojom::PrintScalingType::kFit);
+    ASSERT_TRUE(
+        CheckSettingsAndCapabilitiesCompatibility(*settings, capabilities));
+    histogram_tester.ExpectTotalCount(
+        "Extensions.Printing.UsesSupportedPrintScaling", 0);
+  }
+
+  // Enable the feature now.
+  base::test::ScopedFeatureList feature_list(
+      printing::features::kApiPrintingMarginsAndScale);
+
+  // Verify that the UMA histogram is recorded with false when unsupported
+  // print scaling is passed.
+  {
+    base::HistogramTester histogram_tester;
+    settings->set_print_scaling(printing::mojom::PrintScalingType::kAutoFit);
+    EXPECT_FALSE(
+        CheckSettingsAndCapabilitiesCompatibility(*settings, capabilities));
+    histogram_tester.ExpectUniqueSample(
+        "Extensions.Printing.UsesSupportedPrintScaling", false, 1);
+  }
+
+  // Verify that the UMA histogram is recorded with true when supported
+  // print scaling is passed.
+  {
+    base::HistogramTester histogram_tester;
+    settings->set_print_scaling(printing::mojom::PrintScalingType::kAuto);
+    ASSERT_TRUE(
+        CheckSettingsAndCapabilitiesCompatibility(*settings, capabilities));
+    histogram_tester.ExpectUniqueSample(
+        "Extensions.Printing.UsesSupportedPrintScaling", true, 1);
+  }
+
+  // If unknown print scaling is set, the histogram mustn't be recorded.
+  {
+    base::HistogramTester histogram_tester;
+    settings->set_print_scaling(
+        printing::mojom::PrintScalingType::kUnknownPrintScalingType);
+    ASSERT_TRUE(
+        CheckSettingsAndCapabilitiesCompatibility(*settings, capabilities));
+    histogram_tester.ExpectTotalCount(
+        "Extensions.Printing.UsesSupportedPrintScaling", 0);
+  }
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/web_request/web_request_apitest.cc b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
index bab7242..b2423c6d 100644
--- a/chrome/browser/extensions/api/web_request/web_request_apitest.cc
+++ b/chrome/browser/extensions/api/web_request/web_request_apitest.cc
@@ -37,7 +37,6 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/devtools/protocol/devtools_protocol_test_support.h"
 #include "chrome/browser/devtools/url_constants.h"
-#include "chrome/browser/extensions/chrome_test_extension_loader.h"
 #include "chrome/browser/extensions/error_console/error_console.h"
 #include "chrome/browser/extensions/error_console/error_console_test_observer.h"
 #include "chrome/browser/extensions/extension_apitest.h"
@@ -129,7 +128,6 @@
 #include "services/network/test/test_url_loader_client.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/blink/public/common/input/web_input_event.h"
-#include "third_party/blink/public/common/service_worker/service_worker_status_code.h"
 #include "ui/webui/untrusted_web_ui_browsertest_util.h"  // nogncheck
 #include "url/origin.h"
 
@@ -2611,7 +2609,7 @@
         content::EvalJs(web_contents, "document.body.textContent.trim();"));
   }
 
-  // A callback allow waiting for a response to complete with an expected status
+  // A callback allow waiting for responses to complete with an expected status
   // and given content.
   auto make_browser_request =
       [](network::mojom::URLLoaderFactory* url_loader_factory, const GURL& url,
@@ -2747,12 +2745,23 @@
   }
 }
 
+// TODO(crbug.com/409180663): test is failing on MSan, UBSan and ASan
+#if defined(MEMORY_SANITIZER) || defined(UNDEFINED_SANITIZER) || \
+    defined(ADDRESS_SANITIZER)
+#define MAYBE_WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed \
+  DISABLED_WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed
+#else
+#define MAYBE_WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed \
+  WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed
+#endif  // defined(MEMORY_SANITIZER) || defined(UNDEFINED_SANITIZER) ||
+        // defined(ADDRESS_SANITIZER)
 #if !BUILDFLAG(IS_ANDROID)
 // Regression test for http://crbug.com/878366.
 // TODO(crbug.com/371324825): Port to desktop Android. The test crashes during
 // Profile creation because Android requires a "startup data profile key".
-IN_PROC_BROWSER_TEST_F(ExtensionWebRequestApiTest,
-                       WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed) {
+IN_PROC_BROWSER_TEST_F(
+    ExtensionWebRequestApiTest,
+    MAYBE_WebRequestApiDoesNotCrashOnErrorAfterProfileDestroyed) {
   ASSERT_TRUE(StartEmbeddedTestServer());
 
   // Create a profile that will be destroyed later.
@@ -7555,189 +7564,5 @@
     }
   }
 }
-
-// Allows test to wait for the failure of a worker registration.
-class WorkerRegistrationFailureObserver
-    : public ServiceWorkerTaskQueue::TestObserver {
- public:
-  explicit WorkerRegistrationFailureObserver(const ExtensionId extension_id)
-      : extension_id_(extension_id) {
-    ServiceWorkerTaskQueue::SetObserverForTest(this);
-  }
-  ~WorkerRegistrationFailureObserver() override {
-    ServiceWorkerTaskQueue::SetObserverForTest(nullptr);
-  }
-
-  blink::ServiceWorkerStatusCode WaitForWorkerRegistrationFailure() {
-    if (!status_code_) {
-      SCOPED_TRACE("Waiting for worker registration to fail");
-      failure_loop_.Run();
-    }
-    return *status_code_;
-  }
-
- private:
-  void OnWorkerRegistrationFailed(
-      const ExtensionId& extension_id,
-      blink::ServiceWorkerStatusCode status_code) override {
-    if (extension_id == extension_id_) {
-      status_code_ = status_code;
-      failure_loop_.Quit();
-    }
-  }
-
-  ExtensionId extension_id_;
-  base::RunLoop failure_loop_;
-  std::optional<blink::ServiceWorkerStatusCode> status_code_;
-};
-
-// Allows test to wait for the call of `ResetURLLoaderFactories()` in
-// WebRequestAPI.
-class URLLoaderFactoriesResetWaiter : public WebRequestAPI::TestObserver {
- public:
-  URLLoaderFactoriesResetWaiter() { WebRequestAPI::SetObserverForTest(this); }
-  ~URLLoaderFactoriesResetWaiter() override {
-    WebRequestAPI::SetObserverForTest(nullptr);
-  }
-
-  URLLoaderFactoriesResetWaiter(const URLLoaderFactoriesResetWaiter&) = delete;
-  URLLoaderFactoriesResetWaiter& operator=(
-      const URLLoaderFactoriesResetWaiter&) = delete;
-
-  void WaitForResetURLLoaderFactoriesCalled() {
-    SCOPED_TRACE("Waiting for ResetURLLoaderFactories to be called");
-    url_loader_factory_reset_runloop_.Run();
-  }
-
- private:
-  void OnDidResetURLLoaderFactories() override {
-    url_loader_factory_reset_runloop_.Quit();
-  }
-
-  base::RunLoop url_loader_factory_reset_runloop_;
-};
-
-class ManifestV3WebRequestApiTestWithDeferResetURLLoaderFactories
-    : public ManifestV3WebRequestApiTest,
-      public testing::WithParamInterface<bool> {
- public:
-  ManifestV3WebRequestApiTestWithDeferResetURLLoaderFactories() {
-    feature_list_.InitWithFeatureState(
-        extensions_features::kDeferResetURLLoaderFactories, GetParam());
-  }
-  ~ManifestV3WebRequestApiTestWithDeferResetURLLoaderFactories() override =
-      default;
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-// Tests that the call to `ResetURLLoaderFactories()` performed by WebRequestAPI
-// doesn't break the registration process of other extensions.
-// Regression test for https://crbug.com/394523691.
-IN_PROC_BROWSER_TEST_P(
-    ManifestV3WebRequestApiTestWithDeferResetURLLoaderFactories,
-    ResetURLLoaderFactoryDoesntBreakRegistration) {
-  bool feature_enabled = GetParam();
-  ASSERT_TRUE(StartEmbeddedTestServer());
-
-  // A simple extension that sends a message and waits for a response in its
-  // background script.
-  const ExtensionId extension_id("iegclhlplifhodhkoafiokenjoapiobj");
-  static constexpr const char kKey[] =
-      "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjzv7dI7Ygyh67VHE1DdidudpYf8P"
-      "Ffv8iucWvzO+3xpF/Dm5xNo7aQhPNiEaNfHwJQ7lsp4gc+C+4bbaVewBFspTruoSJhZc5uEf"
-      "qxwovJwN+v1/SUFXTXQmQBv6gs0qZB4gBbl4caNQBlqrFwAMNisnu1V6UROna8rOJQ90D7Nv"
-      "7TCwoVPKBfVshpFjdDOTeBg4iLctO3S/06QYqaTDrwVceSyHkVkvzBY6tc6mnYX0RZu78J9i"
-      "L8bdqwfllOhs69cqoHHgrLdI6JdOyiuh6pBP6vxMlzSKWJ3YTNjaQTPwfOYaLMuzdl0v+Ydz"
-      "afIzV9zwe4Xiskk+5JNGt8b2rQIDAQAB";
-  static constexpr char kManifest[] =
-      R"({
-           "name": "TestExtension",
-           "manifest_version": 3,
-           "version": "0.1",
-           "key": "%s",
-           "background": {"service_worker": "background.js"}
-         })";
-  static constexpr char kBackgroundJs[] =
-      R"(chrome.test.sendMessage('will_receive').then(() => {
-           console.log('received');
-         }))";
-  TestExtensionDir extension_dir;
-  extension_dir.WriteManifest(base::StringPrintf(kManifest, kKey));
-  extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), kBackgroundJs);
-
-  ServiceWorkerTaskQueue* task_queue = ServiceWorkerTaskQueue::Get(profile());
-  ASSERT_TRUE(task_queue);
-  WebRequestAPI* web_request_api =
-      BrowserContextKeyedAPIFactory<WebRequestAPI>::Get(profile());
-  ASSERT_TRUE(web_request_api);
-
-  // Listen to "will_receive" message from the extension.
-  ExtensionTestMessageListener will_receive_listener("will_receive",
-                                                     ReplyBehavior::kWillReply);
-  // Listen to the completion of the registration storage.
-  service_worker_test_utils::TestServiceWorkerContextObserver
-      registration_observer(profile());
-  // Listen for a failure in the worker registration.
-  WorkerRegistrationFailureObserver worker_failure_observer(extension_id);
-
-  // Asynchronously load the extension so we can wait for a step in the loading
-  // process in the test.
-  std::optional<base::UnguessableToken> activation_token;
-  ChromeTestExtensionLoader(profile()).LoadUnpackedExtensionAsync(
-      extension_dir.UnpackedPath(),
-      base::BindLambdaForTesting([&](const Extension* extension) {
-        ASSERT_TRUE(extension);
-        activation_token =
-            task_queue->GetCurrentActivationToken(extension->id());
-        ASSERT_TRUE(activation_token.has_value());
-      }));
-  // ...and wait for the moment right after the worker is requested to start
-  // during the registration process.
-  registration_observer.WaitForStartWorkerMessageSent();
-  URLLoaderFactoriesResetWaiter url_loader_factories_reset_waiter;
-  // Simulate the effect of loading an extension with WebRequestAPI permissions.
-  // In other words, make sure we're proxying for the current profile.
-  // This will cause WebRequestAPI to attempt calling
-  // `ResetURLLoaderFactories()`. Because the extension is still in the early
-  // phases of starting its worker here, this would break its registration
-  // before it has a chance of being completed and stored.
-  // Instead, the call to `ResetURLLoaderFactories()` will be deferred.
-  // NOTE: We simulate the call to `ResetURLLoaderFactories()` rather
-  // than loading an extension with WebRequestAPI permissions, as that
-  // would take too long and won't trigger the bug in all cases.
-  web_request_api->ForceProxyForTesting();
-
-  if (feature_enabled) {
-    // DeferResetURLLoaderFactories feature enabled: expect successful
-    // execution. Check that the worker is still running and functional.
-    registration_observer.WaitForWorkerStarted();
-    std::optional<WorkerId> worker_id = GetWorkerIdForExtension(extension_id);
-    EXPECT_TRUE(worker_id);
-    SCOPED_TRACE(
-        "Waiting for extension background to signal that it can send messages");
-    ASSERT_TRUE(will_receive_listener.WaitUntilSatisfied());
-    will_receive_listener.Reply("go");
-    // Check `ResetURLLoaderFactories()` is called after registration is stored.
-    registration_observer.WaitForRegistrationStored();
-    url_loader_factories_reset_waiter.WaitForResetURLLoaderFactoriesCalled();
-  } else {
-    // DeferResetURLLoaderFactories feature disabled: expect worker registration
-    // to fail. We have observed that the registration can fail with either
-    // `kErrorStartWorkerFailed` or `kErrorNetwork` depending on when exactly
-    // it's interrupted.
-    auto status_code =
-        worker_failure_observer.WaitForWorkerRegistrationFailure();
-    EXPECT_NE(status_code, blink::ServiceWorkerStatusCode::kOk);
-  }
-}
-
-INSTANTIATE_TEST_SUITE_P(
-    All,
-    ManifestV3WebRequestApiTestWithDeferResetURLLoaderFactories,
-    testing::Bool());
-
 #endif  // !BUILDFLAG(IS_ANDROID)
-
 }  // namespace extensions
diff --git a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_browsertest.cc b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_browsertest.cc
index 529bb22..a5bc0a8 100644
--- a/chrome/browser/file_system_access/chrome_file_system_access_permission_context_browsertest.cc
+++ b/chrome/browser/file_system_access/chrome_file_system_access_permission_context_browsertest.cc
@@ -269,8 +269,6 @@
   base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-// TODO(b/276433834): Implement an end-to-end test for getDirectoryPicker in
-// Chrome apps.
 IN_PROC_BROWSER_TEST_F(FileSystemChromeAppTest,
                        FileSystemAccessPermissionRequestManagerExists) {
   ASSERT_TRUE(embedded_test_server()->Start());
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index 83126b9..1eddc68f 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -29,6 +29,11 @@
 
 [
   {
+    "name": "aaudio-per-stream-device-selection",
+    "owners": [ "mjel@google.com", "cros-web-apps-team@google.com" ],
+    "expiry_milestone": 150
+  },
+  {
     "name": "accessible-pdf-form",
     "owners": [ "bravi@microsoft.com", "mohitb@microsoft.com" ],
     "expiry_milestone": 110
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc
index e8c32ae..96d344f 100644
--- a/chrome/browser/flag_descriptions.cc
+++ b/chrome/browser/flag_descriptions.cc
@@ -3344,9 +3344,8 @@
     "Split notification permission settings";
 const char kSettingsAppNotificationSettingsDescription[] =
     "Remove per-app notification permissions settings from the quick settings "
-    "menu. Notification permission settings will be split between the "
-    "lacros-chrome browser's notification permission page "
-    "and the ChromeOS settings app.";
+    "menu. Notification permission settings will be moved to the ChromeOS "
+    "settings app.";
 
 const char kSyncPointGraphValidationName[] = "Sync point graph validation";
 const char kSyncPointGraphValidationDescription[] =
@@ -4297,6 +4296,12 @@
 
 #if BUILDFLAG(IS_ANDROID)
 
+const char kAAudioPerStreamDeviceSelectionName[] =
+    "AAudio per-stream device selection";
+const char kAAudioPerStreamDeviceSelectionDescription[] =
+    "Enables per-stream device selection for AAudio streams. No effect on "
+    "versions of Android prior to Android Q.";
+
 const char kAccessibilityDeprecateTypeAnnounceName[] =
     "Accessibility Deprecate TYPE_ANNOUNCE";
 const char kAccessibilityDeprecateTypeAnnounceDescription[] =
@@ -6249,10 +6254,6 @@
     "Tags used for component updater to select Omaha cohort for Demo Mode.";
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
-const char kDeskProfilesName[] = "Desk profiles";
-const char kDeskProfilesDescription[] =
-    "Enable association of lacros profiles with desks.";
-
 const char kDisableCancelAllTouchesName[] = "Disable CancelAllTouches()";
 const char kDisableCancelAllTouchesDescription[] =
     "If enabled, a canceled touch will not force all other touches to be "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index b3fd17f..e53276e 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -2518,6 +2518,9 @@
 
 #if BUILDFLAG(IS_ANDROID)
 
+extern const char kAAudioPerStreamDeviceSelectionName[];
+extern const char kAAudioPerStreamDeviceSelectionDescription[];
+
 extern const char kAccessibilityDeprecateTypeAnnounceName[];
 extern const char kAccessibilityDeprecateTypeAnnounceDescription[];
 extern const char kAccessibilityIncludeLongClickActionName[];
@@ -3685,9 +3688,6 @@
 extern const char kConchSystemAudioFromMicName[];
 extern const char kConchSystemAudioFromMicDescription[];
 
-extern const char kDeskProfilesName[];
-extern const char kDeskProfilesDescription[];
-
 extern const char kDisableCancelAllTouchesName[];
 extern const char kDisableCancelAllTouchesDescription[];
 
diff --git a/chrome/browser/glic/host/glic_api_uitest.cc b/chrome/browser/glic/host/glic_api_uitest.cc
index 2e79e17..d52e5253 100644
--- a/chrome/browser/glic/host/glic_api_uitest.cc
+++ b/chrome/browser/glic/host/glic_api_uitest.cc
@@ -440,6 +440,38 @@
   RunTestSequence(CheckTabCount(2));
 }
 
+IN_PROC_BROWSER_TEST_F(GlicApiTest, testCreateTabFailsWithUnsupportedScheme) {
+  RunTestSequence(OpenGlicWindow(GlicWindowMode::kDetached,
+                                 GlicInstrumentMode::kHostAndContents),
+                  CheckTabCount(1));
+  ExecuteJsTest();
+  RunTestSequence(CheckTabCount(1));
+}
+
+IN_PROC_BROWSER_TEST_F(GlicApiTest, testCreateTabInBackground) {
+  RunTestSequence(OpenGlicWindow(GlicWindowMode::kDetached,
+                                 GlicInstrumentMode::kHostAndContents),
+                  CheckTabCount(1));
+
+  // Creating a new tab via the glic API in the foreground should change the
+  // active tab.
+  ExecuteJsTest();
+  RunTestSequence(CheckTabCount(2));
+  tabs::TabInterface* active_tab =
+      InProcessBrowserTest::browser()->tab_strip_model()->GetActiveTab();
+  ASSERT_THAT(active_tab->GetContents()->GetURL().spec(),
+              testing::EndsWith("#foreground"));
+
+  // Creating a new tab via the glic API in the background should not change the
+  // active tab.
+  ContinueJsTest();
+  RunTestSequence(CheckTabCount(3));
+  active_tab =
+      InProcessBrowserTest::browser()->tab_strip_model()->GetActiveTab();
+  ASSERT_THAT(active_tab->GetContents()->GetURL().spec(),
+              testing::EndsWith("#foreground"));
+}
+
 IN_PROC_BROWSER_TEST_F(GlicApiTestWithOneTab, testOpenGlicSettingsPage) {
   ExecuteJsTest();
 
diff --git a/chrome/browser/navigation_predictor/navigation_predictor_preconnect_client_browsertest.cc b/chrome/browser/navigation_predictor/navigation_predictor_preconnect_client_browsertest.cc
index 0ec2cda..e554111 100644
--- a/chrome/browser/navigation_predictor/navigation_predictor_preconnect_client_browsertest.cc
+++ b/chrome/browser/navigation_predictor/navigation_predictor_preconnect_client_browsertest.cc
@@ -319,13 +319,8 @@
     NavigationPredictorPreconnectClientBrowserTestWithSearch,
     testing::Bool());
 
-#if BUILDFLAG(IS_WIN) && defined(ADDRESS_SANITIZER)
-#define MAYBE_PreconnectSearchWithFeature DISABLED_PreconnectSearchWithFeature
-#else
-#define MAYBE_PreconnectSearchWithFeature PreconnectSearchWithFeature
-#endif
 IN_PROC_BROWSER_TEST_P(NavigationPredictorPreconnectClientBrowserTestWithSearch,
-                       MAYBE_PreconnectSearchWithFeature) {
+                       DISABLED_PreconnectSearchWithFeature) {
   static const char16_t kShortName[] = u"test";
   static const char kSearchURL[] =
       "/anchors_different_area.html?q={searchTerms}";
diff --git a/chrome/browser/navigation_predictor/search_engine_preconnector.cc b/chrome/browser/navigation_predictor/search_engine_preconnector.cc
index d78428a..389877b 100644
--- a/chrome/browser/navigation_predictor/search_engine_preconnector.cc
+++ b/chrome/browser/navigation_predictor/search_engine_preconnector.cc
@@ -34,6 +34,9 @@
 const bool kDefaultSkipInBackground = true;
 #endif
 
+constexpr int kPreconnectIntervalSec = 60;
+constexpr int kPreconnectRetryDelayMs = 50;
+
 }  // namespace
 
 namespace features {
@@ -45,9 +48,6 @@
 BASE_FEATURE(kPreconnectToSearch,
              "PreconnectToSearch",
              base::FEATURE_ENABLED_BY_DEFAULT);
-BASE_FEATURE(kPreconnectToSearchWithPrivacyModeEnabled,
-             "PreconnectToSearchWithPrivacyModeEnabled",
-             base::FEATURE_DISABLED_BY_DEFAULT);
 }  // namespace features
 
 WebContentVisibilityManager::WebContentVisibilityManager()
@@ -103,6 +103,12 @@
   return enabled_for_otr;
 }
 
+bool SearchEnginePreconnector::SearchEnginePreconnect2Enabled() {
+  static bool preconnect2_enabled =
+      base::FeatureList::IsEnabled(net::features::kSearchEnginePreconnect2);
+  return preconnect2_enabled;
+}
+
 SearchEnginePreconnector::SearchEnginePreconnector(
     content::BrowserContext* browser_context)
     : browser_context_(browser_context) {
@@ -113,18 +119,18 @@
 SearchEnginePreconnector::~SearchEnginePreconnector() = default;
 
 void SearchEnginePreconnector::StopPreconnecting() {
+  preconnector_started_ = false;
   timer_.Stop();
 }
 
 void SearchEnginePreconnector::StartPreconnecting(bool with_startup_delay) {
+  preconnector_started_ = true;
   timer_.Stop();
   if (with_startup_delay) {
-    timer_.Start(FROM_HERE,
-                 base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
-                     features::kPreconnectToSearch, "startup_delay_ms",
-                     kDefaultStartupDelayMs)),
-                 base::BindOnce(&SearchEnginePreconnector::PreconnectDSE,
-                                base::Unretained(this)));
+    StartPreconnectWithDelay(
+        base::Milliseconds(base::GetFieldTrialParamByFeatureAsInt(
+            features::kPreconnectToSearch, "startup_delay_ms",
+            kDefaultStartupDelayMs)));
     return;
   }
 
@@ -177,27 +183,13 @@
         preconnect_url, /*allow_credentials=*/true, network_anonymziation_key,
         predictors::kSearchEnginePreconnectTrafficAnnotation,
         /*storage_partition_config=*/nullptr);
-
-    if (base::FeatureList::IsEnabled(
-            features::kPreconnectToSearchWithPrivacyModeEnabled)) {
-      GetPreconnectManager().StartPreconnectUrl(
-          preconnect_url,
-          /*allow_credentials=*/false, network_anonymziation_key,
-          predictors::kSearchEnginePreconnectTrafficAnnotation,
-          /*storage_partition_config=*/nullptr);
-    }
   }
 
-  // The delay beyond the idle socket timeout that net uses when
-  // re-preconnecting. If negative, no retries occur.
-  const base::TimeDelta retry_delay = base::Milliseconds(50);
-
-  // Set/Reset the timer to fire after the preconnect times out. Add an extra
-  // delay to make sure the preconnect has expired if it wasn't used.
-  timer_.Start(FROM_HERE,
-               base::Seconds(GetPreconnectIntervalSec()) + retry_delay,
-               base::BindOnce(&SearchEnginePreconnector::PreconnectDSE,
-                              base::Unretained(this)));
+  // Periodically preconnect to the DSE. If the browser app is likely in
+  // background, we will reattempt preconnect later.
+  if (!SearchEnginePreconnect2Enabled()) {
+    StartPreconnectWithDelay(GetPreconnectInterval());
+  }
 }
 
 GURL SearchEnginePreconnector::GetDefaultSearchEngineOriginURL() const {
@@ -211,12 +203,27 @@
   return search_provider->GenerateSearchURL({}).DeprecatedGetOriginAsURL();
 }
 
-int SearchEnginePreconnector::GetPreconnectIntervalSec() const {
-  constexpr int kPreconnectIntervalSec = 60;
-  int preconnect_interval = base::GetFieldTrialParamByFeatureAsInt(
-      net::features::kSearchEnginePreconnectInterval, "preconnect_interval",
-      kPreconnectIntervalSec);
-  return preconnect_interval;
+base::TimeDelta SearchEnginePreconnector::GetPreconnectInterval() const {
+  if (!SearchEnginePreconnect2Enabled()) {
+    int preconnect_interval = base::GetFieldTrialParamByFeatureAsInt(
+        net::features::kSearchEnginePreconnectInterval, "preconnect_interval",
+        kPreconnectIntervalSec);
+
+    // Add an extra delay to make sure the preconnect has expired if it wasn't
+    // used.
+    return base::Seconds(preconnect_interval) +
+           base::Milliseconds(kPreconnectRetryDelayMs);
+  }
+
+  // TODO(crbug.com/406022435): Update the logic to use exponential backoff.
+  return base::Seconds(net::features::kMaxPreconnectRetryInterval.Get());
+}
+
+void SearchEnginePreconnector::StartPreconnectWithDelay(base::TimeDelta delay) {
+  //  Set/Reset the timer to fire after the specified `delay`.
+  timer_.Start(FROM_HERE, delay,
+               base::BindOnce(&SearchEnginePreconnector::PreconnectDSE,
+                              base::Unretained(this)));
 }
 
 predictors::PreconnectManager&
@@ -228,3 +235,28 @@
 
   return *preconnect_manager_.get();
 }
+
+void SearchEnginePreconnector::OnWebContentsVisibilityChanged(
+    content::WebContents* web_contents,
+    bool is_in_foreground) {
+  WebContentVisibilityManager::OnWebContentsVisibilityChanged(web_contents,
+                                                              is_in_foreground);
+
+  if (!SearchEnginePreconnect2Enabled()) {
+    return;
+  }
+
+  // Early stop when we know that the visibility change did not trigger
+  // foregrounding of the app and also when the preconnector is not started.
+  if (!IsBrowserAppLikelyInForeground() || !preconnector_started_) {
+    return;
+  }
+
+  // Stop the timer explicitly here so that we do not have any duplicate
+  // attempts.
+  timer_.Stop();
+
+  // Attempt reconnect again in case the visibility has changed after the last
+  // preconnect attempt so that we will preconnect sooner.
+  PreconnectDSE();
+}
diff --git a/chrome/browser/navigation_predictor/search_engine_preconnector.h b/chrome/browser/navigation_predictor/search_engine_preconnector.h
index 226e3d9ec..466adfc8 100644
--- a/chrome/browser/navigation_predictor/search_engine_preconnector.h
+++ b/chrome/browser/navigation_predictor/search_engine_preconnector.h
@@ -20,8 +20,6 @@
 namespace features {
 BASE_DECLARE_FEATURE(kPreconnectFromKeyedService);
 BASE_DECLARE_FEATURE(kPreconnectToSearch);
-BASE_DECLARE_FEATURE(kPreconnectToSearchNonGoogle);
-BASE_DECLARE_FEATURE(kPreconnectToSearchWithPrivacyModeEnabled);
 }  // namespace features
 
 // Class to keep track of the current visibility. It is used to determine if the
@@ -35,8 +33,9 @@
   // Might be called more than once with the same |is_in_foreground| and
   // |web_contents| in case user starts a new navigation with same
   // |web_contents|.
-  void OnWebContentsVisibilityChanged(content::WebContents* web_contents,
-                                      bool is_in_foreground);
+  virtual void OnWebContentsVisibilityChanged(
+      content::WebContents* web_contents,
+      bool is_in_foreground);
 
   // Notifies |this| that the web contents tracked by |client| has destroyed.
   void OnWebContentsDestroyed(content::WebContents* web_contents);
@@ -66,6 +65,7 @@
  public:
   static bool ShouldBeEnabledAsKeyedService();
   static bool ShouldBeEnabledForOffTheRecord();
+  static bool SearchEnginePreconnect2Enabled();
 
   explicit SearchEnginePreconnector(content::BrowserContext* browser_context);
   ~SearchEnginePreconnector() override;
@@ -90,20 +90,32 @@
   // Lazily creates the PreconnectManager instance.
   predictors::PreconnectManager& GetPreconnectManager();
 
+  // WebContentVisibilityManager methods
+  // TODO(crbug.com/406022435): Update to observe the
+  // `WebContentVisibilityManager` and not override them.
+  void OnWebContentsVisibilityChanged(content::WebContents* web_contents,
+                                      bool is_in_foreground) override;
+
  private:
   // Preconnects to the default search engine synchronously. Preconnects in
-  // credentialed and uncredentialed mode.
+  // uncredentialed mode.
   void PreconnectDSE();
 
+  // Runs `PreconnectDSE` after the `delay`.
+  void StartPreconnectWithDelay(base::TimeDelta delay);
+
   // Queries template service for the current DSE URL.
   GURL GetDefaultSearchEngineOriginURL() const;
 
-  int GetPreconnectIntervalSec() const;
+  base::TimeDelta GetPreconnectInterval() const;
 
   base::WeakPtr<SearchEnginePreconnector> GetWeakPtr() {
     return weak_factory_.GetWeakPtr();
   }
 
+  // Determines whether the preconnector is started or not.
+  bool preconnector_started_ = false;
+
   // Used to get keyed services.
   const raw_ptr<content::BrowserContext> browser_context_;
 
diff --git a/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc b/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
index 18da23e..4f8b019 100644
--- a/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
+++ b/chrome/browser/navigation_predictor/search_engine_preconnector_browsertest.cc
@@ -157,13 +157,6 @@
          {{"preconnect_interval", "0"}}}};
 
     std::vector<base::test::FeatureRef> disabled_features;
-    if (PreconnectWithPrivacyModeEnabled()) {
-      enabled_features.push_back(
-          {features::kPreconnectToSearchWithPrivacyModeEnabled, {}});
-    } else {
-      disabled_features.emplace_back(
-          features::kPreconnectToSearchWithPrivacyModeEnabled);
-    }
 
     if (PreconnectFromKeyedServiceEnabled()) {
       enabled_features.push_back(
@@ -172,14 +165,20 @@
       disabled_features.emplace_back(features::kPreconnectFromKeyedService);
     }
 
+    if (SearchEnginePreconnect2Enabled()) {
+      enabled_features.push_back({net::features::kSearchEnginePreconnect2, {}});
+    } else {
+      disabled_features.emplace_back(net::features::kSearchEnginePreconnect2);
+    }
+
     feature_list_.InitWithFeaturesAndParameters(enabled_features,
                                                 disabled_features);
   }
 
-  bool PreconnectWithPrivacyModeEnabled() const {
+  bool PreconnectFromKeyedServiceEnabled() const override {
     return std::get<0>(GetParam());
   }
-  bool PreconnectFromKeyedServiceEnabled() const override {
+  bool SearchEnginePreconnect2Enabled() const {
     return std::get<1>(GetParam());
   }
 
@@ -228,27 +227,13 @@
 
   // After switching search providers, the test URL should now start being
   // preconnected.
-  if (PreconnectWithPrivacyModeEnabled()) {
-    WaitForPreresolveCountForURL(GetTestURL("/"), 2);
-    // Preconnect should occur for DSE.
-    EXPECT_EQ(2,
-              preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
+  WaitForPreresolveCountForURL(GetTestURL("/"), 1);
+  // Preconnect should occur for DSE.
+  EXPECT_EQ(1, preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
 
-    WaitForPreresolveCountForURL(GetTestURL("/"), 4);
-    // Preconnect should occur again for DSE.
-    EXPECT_EQ(4,
-              preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
-  } else {
-    WaitForPreresolveCountForURL(GetTestURL("/"), 1);
-    // Preconnect should occur for DSE.
-    EXPECT_EQ(1,
-              preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
-
-    WaitForPreresolveCountForURL(GetTestURL("/"), 2);
-    // Preconnect should occur again for DSE.
-    EXPECT_EQ(2,
-              preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
-  }
+  WaitForPreresolveCountForURL(GetTestURL("/"), 2);
+  // Preconnect should occur again for DSE.
+  EXPECT_EQ(2, preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
 }
 
 IN_PROC_BROWSER_TEST_P(SearchEnginePreconnectorNoDelaysBrowserTest,
@@ -289,17 +274,10 @@
   GetSearchEnginePreconnector()->StartPreconnecting(
       /*with_startup_delay=*/false);
   const GURL search_url = template_url->GenerateSearchURL({});
-  if (PreconnectWithPrivacyModeEnabled()) {
-    WaitForPreresolveCountForURL(search_url, 2);
+  WaitForPreresolveCountForURL(search_url, 1);
 
-    // Preconnect should occur for fake search (2 since there are 2 NAKs).
-    EXPECT_EQ(2, preresolve_counts_[search_url]);
-  } else {
-    WaitForPreresolveCountForURL(search_url, 1);
-
-    // Preconnect should occur for fake search.
-    EXPECT_EQ(1, preresolve_counts_[search_url]);
-  }
+  // Preconnect should occur for fake search.
+  EXPECT_EQ(1, preresolve_counts_[search_url]);
 
   // No preconnects should have been issued for the test URL.
   EXPECT_EQ(0, preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
@@ -322,13 +300,6 @@
                                     {{"startup_delay_ms", "1000000"},
                                      {"skip_in_background", "false"}}});
       }
-      if (preconnect_to_search_with_privacy_mode_enabled()) {
-        enabled_features.push_back(
-            {features::kPreconnectToSearchWithPrivacyModeEnabled, {}});
-      } else {
-        disabled_features.emplace_back(
-            features::kPreconnectToSearchWithPrivacyModeEnabled);
-      }
 
       if (PreconnectFromKeyedServiceEnabled()) {
         enabled_features.push_back(
@@ -336,6 +307,13 @@
       } else {
         disabled_features.emplace_back(features::kPreconnectFromKeyedService);
       }
+
+      if (SearchEnginePreconnect2Enabled()) {
+        enabled_features.push_back(
+            {net::features::kSearchEnginePreconnect2, {}});
+      } else {
+        disabled_features.emplace_back(net::features::kSearchEnginePreconnect2);
+      }
       feature_list_.InitWithFeaturesAndParameters(enabled_features,
                                                   disabled_features);
     }
@@ -345,11 +323,11 @@
 
   bool load_page() const { return std::get<1>(GetParam()); }
 
-  bool preconnect_to_search_with_privacy_mode_enabled() const {
+  bool PreconnectFromKeyedServiceEnabled() const override {
     return std::get<2>(GetParam());
   }
 
-  bool PreconnectFromKeyedServiceEnabled() const override {
+  bool SearchEnginePreconnect2Enabled() const {
     return std::get<3>(GetParam());
   }
 
@@ -417,29 +395,22 @@
                                              GetTestURL(kSearchURLWithQuery)));
   }
 
-  // Put the fake search URL to be preconnected in foreground.
-  GetSearchEnginePreconnector()->StartPreconnecting(
-      /*with_startup_delay=*/false);
-
-  if (preconnect_to_search_with_privacy_mode_enabled()) {
-    if (!skip_in_background() || load_page()) {
-      WaitForPreresolveCountForURL(fake_search_url, 2);
-    }
-
-    // If preconnects are skipped in background and no web contents is in
-    // foreground, then no preconnect should happen.
-    EXPECT_EQ(skip_in_background() && !load_page() ? 0 : 2,
-              preresolve_counts_[fake_search_url]);
-  } else {
-    if (!skip_in_background() || load_page()) {
-      WaitForPreresolveCountForURL(fake_search_url, 1);
-    }
-
-    // If preconnects are skipped in background and no web contents is in
-    // foreground, then no preconnect should happen.
-    EXPECT_EQ(skip_in_background() && !load_page() ? 0 : 1,
-              preresolve_counts_[fake_search_url]);
+  // Skip enabling the preconnect as it is already handled in the KeyedService
+  // for the `SearchEnginePreconnect2` feature.
+  if (!SearchEnginePreconnect2Enabled() || !load_page()) {
+    // Put the fake search URL to be preconnected in foreground.
+    GetSearchEnginePreconnector()->StartPreconnecting(
+        /*with_startup_delay=*/false);
   }
+
+  if (!skip_in_background() || load_page()) {
+    WaitForPreresolveCountForURL(fake_search_url, 1);
+  }
+
+  // If preconnects are skipped in background and no web contents is in
+  // foreground, then no preconnect should happen.
+  EXPECT_EQ(skip_in_background() && !load_page() ? 0 : 1,
+            preresolve_counts_[fake_search_url]);
   histogram_tester.ExpectUniqueSample(
       "NavigationPredictor.SearchEnginePreconnector."
       "IsBrowserAppLikelyInForeground",
@@ -546,14 +517,6 @@
            {{"preconnect_interval", "60"}}}};
 
       std::vector<base::test::FeatureRef> disabled_features;
-      if (PreconnectWithPrivacyModeEnabled()) {
-        enabled_features.push_back(
-            {features::kPreconnectToSearchWithPrivacyModeEnabled, {}});
-      } else {
-        disabled_features.emplace_back(
-            features::kPreconnectToSearchWithPrivacyModeEnabled);
-      }
-
       if (PreconnectFromKeyedServiceEnabled()) {
         enabled_features.push_back(
             {features::kPreconnectFromKeyedService, {{"run_on_otr", "false"}}});
@@ -561,15 +524,22 @@
         disabled_features.emplace_back(features::kPreconnectFromKeyedService);
       }
 
+      if (SearchEnginePreconnect2Enabled()) {
+        enabled_features.push_back(
+            {net::features::kSearchEnginePreconnect2, {}});
+      } else {
+        disabled_features.emplace_back(net::features::kSearchEnginePreconnect2);
+      }
+
       feature_list_.InitWithFeaturesAndParameters(enabled_features,
                                                   disabled_features);
     }
   }
 
-  bool PreconnectWithPrivacyModeEnabled() const {
+  bool PreconnectFromKeyedServiceEnabled() const override {
     return std::get<0>(GetParam());
   }
-  bool PreconnectFromKeyedServiceEnabled() const override {
+  bool SearchEnginePreconnect2Enabled() const {
     return std::get<1>(GetParam());
   }
 
@@ -619,17 +589,10 @@
       /*with_startup_delay=*/false);
 
   const GURL search_url = template_url->GenerateSearchURL({});
-  if (PreconnectWithPrivacyModeEnabled()) {
-    WaitForPreresolveCountForURL(search_url, 2);
+  WaitForPreresolveCountForURL(search_url, 1);
 
-    // Preconnect should occur for Google search (2 since there are 2 NAKs).
-    EXPECT_EQ(2, preresolve_counts_[search_url]);
-  } else {
-    WaitForPreresolveCountForURL(search_url, 1);
-
-    // Preconnect should occur for Google search.
-    EXPECT_EQ(1, preresolve_counts_[search_url]);
-  }
+  // Preconnect should occur for Google search.
+  EXPECT_EQ(1, preresolve_counts_[search_url]);
 
   // No preconnects should have been issued for the test URL.
   EXPECT_EQ(0, preresolve_counts_[GetTestURL("/").DeprecatedGetOriginAsURL()]);
diff --git a/chrome/browser/preloading/prerender/prerender_browsertest.cc b/chrome/browser/preloading/prerender/prerender_browsertest.cc
index 87a0e94..5896034 100644
--- a/chrome/browser/preloading/prerender/prerender_browsertest.cc
+++ b/chrome/browser/preloading/prerender/prerender_browsertest.cc
@@ -898,4 +898,75 @@
       kFinalStatusTriggerDestroyed, 1);
 }
 
+class PrerenderSpeculationRulesTagsBrowserTest
+    : public PrerenderBrowserTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  PrerenderSpeculationRulesTagsBrowserTest() {
+    if (IsSpeculationRulesTagsEnabled()) {
+      // Explicitly enables blink::features::kSpeculationRulesTag to enable
+      // SpeculationRulesTag.
+      feature_list_.InitAndEnableFeature(blink::features::kSpeculationRulesTag);
+    } else {
+      feature_list_.InitAndDisableFeature(
+          blink::features::kSpeculationRulesTag);
+    }
+  }
+  ~PrerenderSpeculationRulesTagsBrowserTest() override = default;
+
+  bool IsSpeculationRulesTagsEnabled() const { return GetParam(); }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(All,
+                         PrerenderSpeculationRulesTagsBrowserTest,
+                         testing::Bool(),
+                         [](const testing::TestParamInfo<bool>& info) {
+                           return info.param ? "TagsEnabled" : "TagsDisabled";
+                         });
+
+IN_PROC_BROWSER_TEST_P(PrerenderSpeculationRulesTagsBrowserTest, UseCounter) {
+  base::HistogramTester histogram_tester;
+
+  histogram_tester.ExpectBucketCount(
+      "Blink.UseCounter.Features",
+      blink::mojom::WebFeature::kSpeculationRulesTags, 0);
+
+  // Navigate to an initial page.
+  GURL url =
+      embedded_test_server()->GetURL("/prerender/prerender_with_tags.html");
+  GURL prerender_url = embedded_test_server()->GetURL("/prerender/empty.html");
+  ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url));
+  content::test::PrerenderTestHelper::WaitForPrerenderLoadCompletion(
+      *GetActiveWebContents(), prerender_url);
+
+  histogram_tester.ExpectBucketCount(
+      "Blink.UseCounter.Features",
+      blink::mojom::WebFeature::kSpeculationRulesTags,
+      IsSpeculationRulesTagsEnabled() ? 1 : 0);
+}
+
+// Tests that if no tag is specified, then UseCounter will not increase.
+IN_PROC_BROWSER_TEST_P(PrerenderSpeculationRulesTagsBrowserTest,
+                       NoUseCountIfTagEmpty) {
+  base::HistogramTester histogram_tester;
+
+  histogram_tester.ExpectBucketCount(
+      "Blink.UseCounter.Features",
+      blink::mojom::WebFeature::kSpeculationRulesTags, 0);
+
+  // Navigate to an initial page.
+  GURL url = embedded_test_server()->GetURL("/prerender/empty.html");
+  GURL prerender_url =
+      embedded_test_server()->GetURL("/prerender/empty.html?prerender");
+  ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url));
+  prerender_helper().AddPrerender(prerender_url);
+
+  histogram_tester.ExpectBucketCount(
+      "Blink.UseCounter.Features",
+      blink::mojom::WebFeature::kSpeculationRulesTags, 0);
+}
+
 }  // namespace
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_entry_row.html b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_entry_row.html
index 510672d7..8e6994d 100644
--- a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_entry_row.html
+++ b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_entry_row.html
@@ -39,12 +39,15 @@
      type="text"
      on-change="saveWord_"></cr-input>
   <div class="category-div" >
-    <div class="cr-form-field-label category-label">$i18n{japaneseDictionaryCategory}</div>
+    <label id="categoryLabel" class="cr-form-field-label category-label">
+      $i18n{japaneseDictionaryCategory}
+    </label>
     <!--
       These Japanese terms are not translated on purpose since they are technical linguistic terms
       The option values needs to corresponds to the int value of the mojo enum JpPosType.
     -->
-    <select id="posDropdownMenu" class="md-select" on-change="onOptionChanged_">
+    <select id="posDropdownMenu" class="md-select" on-change="onOptionChanged_"
+       aria-labelledby="categoryLabel">
        <template is="dom-repeat" items="[[posTypeOptions_]]">
          <option value="[[item.value]]"
             selected="[[isSelectedOption_(item.value)]]">
diff --git a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.html b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.html
index 13ac4ab..1b38231 100644
--- a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.html
+++ b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.html
@@ -19,17 +19,28 @@
   <div id="web-content-filters">
     <h2>Web content filters</h2>
     <form id="web-content-filters-form">
-    <h2>Override Google Safe Search</h2>
-        <label>
-          <input type="radio" name="search-content-filters-enabled"
-          id="search-content-filters-enabled-on" value="on"></input>
-          SafeSearch filtering ON
-        </label>
-        <label>
-          <input type="radio" name="search-content-filters-enabled"
-          id="search-content-filters-enabled-off" value="off"></input>
-          SafeSearch filtering OFF
-        </label>
+      <h2>Override Chrome and Web</h2>
+      <label>
+        <input type="radio" name="browser-content-filters-enabled"
+        id="browser-content-filters-enabled-on" value="on"></input>
+        Try to block explicit sites
+      </label>
+      <label>
+        <input type="radio" name="browser-content-filters-enabled"
+        id="browser-content-filters-enabled-off" value="off"></input>
+        Allow all sites
+      </label>
+      <h2>Override Google Safe Search</h2>
+      <label>
+        <input type="radio" name="search-content-filters-enabled"
+        id="search-content-filters-enabled-on" value="on"></input>
+        SafeSearch filtering ON
+      </label>
+      <label>
+        <input type="radio" name="search-content-filters-enabled"
+        id="search-content-filters-enabled-off" value="off"></input>
+        SafeSearch filtering OFF
+      </label>
     </form>
   </div>
 
diff --git a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.ts b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.ts
index 80eed936..31e05d5b 100644
--- a/chrome/browser/resources/family_link_user_internals/family_link_user_internals.ts
+++ b/chrome/browser/resources/family_link_user_internals/family_link_user_internals.ts
@@ -30,6 +30,7 @@
 interface WebContentsInfo {
   enabled: boolean;
   search_content_filtering: 'on'|'off';
+  browser_content_filtering: 'on'|'off';
 }
 
 type UserSettings = Record<string, any>;
@@ -105,12 +106,19 @@
   function changeSearchContentFilters(newState: 'on'|'off') {
     chrome.send('changeSearchContentFilters', [newState]);
   }
+  function changeBrowserContentFilters(newState: 'on'|'off') {
+    chrome.send('changeBrowserContentFilters', [newState]);
+  }
 
   getRequiredElement('try-url').addEventListener('submit', submitURL);
   getRequiredElement('search-content-filters-enabled-on')
       .addEventListener('click', () => changeSearchContentFilters('on'));
   getRequiredElement('search-content-filters-enabled-off')
       .addEventListener('click', () => changeSearchContentFilters('off'));
+  getRequiredElement('browser-content-filters-enabled-on')
+      .addEventListener('click', () => changeBrowserContentFilters('on'));
+  getRequiredElement('browser-content-filters-enabled-off')
+      .addEventListener('click', () => changeBrowserContentFilters('off'));
 
   addWebUiListener('basic-info-received', receiveBasicInfo);
   addWebUiListener('user-settings-received', receiveUserSettings);
@@ -197,29 +205,41 @@
 }
 
 function receiveWebContentsFilterInfo(result: WebContentsInfo) {
-  getRequiredElement<HTMLInputElement>('search-content-filters-enabled-on')
-      .readOnly = !result.enabled;
-  getRequiredElement<HTMLInputElement>('search-content-filters-enabled-off')
-      .readOnly = !result.enabled;
-  getRequiredElement<HTMLInputElement>('search-content-filters-enabled-on')
-      .disabled = !result.enabled;
-  getRequiredElement<HTMLInputElement>('search-content-filters-enabled-off')
-      .disabled = !result.enabled;
+  /**
+   * Synchronizes the UI with WebContentsInfo result coming from the handler.
+   *
+   * @param toggleIdPrefix the HTML layout should contain two radio toggles
+   *     grouped under this `name` attribute, one each for `-on` and `-off`
+   *     options.
+   * @param value determines whether on or off radio should be checked.
+   */
+  function updateToggles(toggleIdPrefix: string, value: 'on'|'off') {
+    const onToggleId = `${toggleIdPrefix}-on`;
+    const offToggleId = `${toggleIdPrefix}-off`;
 
-  switch (result.search_content_filtering) {
-    case 'on':
-      getRequiredElement<HTMLInputElement>('search-content-filters-enabled-on')
-          .checked = true;
-      getRequiredElement<HTMLInputElement>('search-content-filters-enabled-off')
-          .checked = false;
-      break;
-    case 'off':
-      getRequiredElement<HTMLInputElement>('search-content-filters-enabled-on')
-          .checked = false;
-      getRequiredElement<HTMLInputElement>('search-content-filters-enabled-off')
-          .checked = true;
-      break;
+    getRequiredElement<HTMLInputElement>(onToggleId).readOnly = !result.enabled;
+    getRequiredElement<HTMLInputElement>(offToggleId).readOnly =
+        !result.enabled;
+    getRequiredElement<HTMLInputElement>(onToggleId).disabled = !result.enabled;
+    getRequiredElement<HTMLInputElement>(offToggleId).disabled =
+        !result.enabled;
+
+    switch (value) {
+      case 'on':
+        getRequiredElement<HTMLInputElement>(onToggleId).checked = true;
+        getRequiredElement<HTMLInputElement>(offToggleId).checked = false;
+        break;
+      case 'off':
+        getRequiredElement<HTMLInputElement>(onToggleId).checked = false;
+        getRequiredElement<HTMLInputElement>(offToggleId).checked = true;
+        break;
+    }
   }
+
+  updateToggles(
+      'search-content-filters-enabled', result.search_content_filtering);
+  updateToggles(
+      'browser-content-filters-enabled', result.browser_content_filtering);
 }
 
 document.addEventListener('DOMContentLoaded', initialize);
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.html.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.html.ts
index 1068840..fc5568b 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.html.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.html.ts
@@ -7,52 +7,48 @@
 import type {PowerBookmarkRowElement} from './power_bookmark_row.ts';
 
 export function getHtml(this: PowerBookmarkRowElement) {
-  const { id, url, title, children } = this.bookmark || {};
   // clang-format off
   const urlListItem = html`
 <cr-url-list-item id="crUrlListItem"
     role="listitem"
     .size="${this.listItemSize}"
-    .url="${url}"
-    .imageUrls="${this.getBookmarkImageUrls_(this.bookmark)}"
-    .count="${children?.length}"
-    .title="${title}"
+    .url="${this.bookmark.url}"
+    .imageUrls="${this.getBookmarkImageUrls_()}"
+    .count="${this.bookmark.children?.length}"
+    .title="${this.bookmark.title}"
     .description="${this.getBookmarkDescription_(this.bookmark)}"
-    .descriptionMeta="${this.getBookmarkDescriptionMeta_(this.bookmark)}"
-    .itemAriaLabel="${this.getBookmarkA11yLabel_(url,title)}"
-    .itemAriaDescription="${this.getBookmarkA11yDescription_(this.bookmark)}"
+    .descriptionMeta="${this.getBookmarkDescriptionMeta_()}"
+    .itemAriaLabel="${this.getBookmarkA11yLabel_()}"
+    .itemAriaDescription="${this.getBookmarkA11yDescription_()}"
     @click="${this.onRowClicked_}"
     @auxclick="${this.onRowClicked_}"
     @contextmenu="${this.onContextMenu_}"
-    .forceHover="${this.getBookmarkForceHover_(this.bookmark)}">
+    ?force-hover="${this.getBookmarkForceHover_()}">
 
   ${this.hasCheckbox ? html`
     <cr-checkbox id="checkbox" slot="prefix"
         ?checked="${this.isCheckboxChecked_()}"
         @checked-changed="${this.onCheckboxChange_}"
-        ?disabled="${!this.canEdit_(this.bookmark)}">
+        ?disabled="${!this.canEdit_()}">
       $i18n{checkboxA11yLabel}
     </cr-checkbox>` : ''}
 
-  ${this.renamingItem_(id) ? html`
-    <cr-input slot="content" id="input" .value="${title}"
+  ${this.isRenamingItem_() ? html`
+    <cr-input slot="content" id="input" .value="${this.bookmark.title}"
         class="stroked"
         @change="${this.onInputChange_}" @blur="${this.onInputBlur_}"
         @keydown="${this.onInputKeyDown_}"
-        .ariaLabel="${this.getBookmarkA11yLabel_(url,title)}"
-        .ariaDescription="${this.getBookmarkA11yDescription_(this.bookmark)}">
+        .ariaLabel="${this.getBookmarkA11yLabel_()}"
+        .ariaDescription="${this.getBookmarkA11yDescription_()}">
     </cr-input>` : ''}
 
   ${this.showTrailingIcon_() ? html`
     ${this.isPriceTracked ? html`
     <sp-list-item-badge slot="badges"
-        ?was-updated="${this.showDiscountedPrice_(this.bookmark)}">
+        ?was-updated="${this.showDiscountedPrice_()}">
       <cr-icon icon="bookmarks:price-tracking"></cr-icon>
-      <div>
-        ${this.getCurrentPrice_(this.bookmark)}
-      </div>
-      <div slot="previous-badge"
-          ?hidden="${!this.showDiscountedPrice_(this.bookmark)}">
+      <div>${this.getCurrentPrice_(this.bookmark)}</div>
+      <div slot="previous-badge" ?hidden="${!this.showDiscountedPrice_()}">
         ${this.getPreviousPrice_(this.bookmark)}
       </div>
     </sp-list-item-badge>
@@ -60,7 +56,7 @@
     <cr-icon-button slot="suffix" iron-icon="cr:more-vert"
         @click="${this.onTrailingIconClicked_}"
         .title="${this.trailingIconTooltip}"
-        .ariaLabel="${this.getBookmarkMenuA11yLabel_(url, title)}">
+        .ariaLabel="${this.getBookmarkMenuA11yLabel_()}">
     </cr-icon-button>
   ` : ''}
 
@@ -69,14 +65,14 @@
         icon="bookmarks:bookmarks-bar"></cr-icon>
   ` :''}
 
-  ${this.isShoppingCollection_(this.bookmark) ? html`
+  ${this.isShoppingCollection_() ? html`
     <cr-icon slot="folder-icon" icon="bookmarks:shopping-collection">
     </cr-icon>
   ` : ''}
 </cr-url-list-item>`;
 
-if (this.shouldExpand_()) {
-  return html`
+  if (this.shouldExpand_()) {
+    return html`
 <cr-expand-button no-hover id="expandButton"
     collapse-icon="cr:expand-more"
     expand-icon="cr:chevron-right"
@@ -84,33 +80,32 @@
   ${urlListItem}
 </cr-expand-button>
   ${this.toggleExpand ? html`
-    ${children!.map((item: chrome.bookmarks.BookmarkTreeNode)=> html`
+    ${this.bookmark.children!.map(item => html`
       <power-bookmark-row
           id="bookmark-${item.id}"
           .bookmark="${item}"
-          .compact="${this.compact}"
+          ?compact="${this.compact}"
           .depth="${this.depth + 1}"
           trailingIconTooltip="$i18n{tooltipMore}"
-          .hasCheckbox="${this.hasCheckbox}"
+          ?has-checkbox="${this.hasCheckbox}"
           .selectedBookmarks="${this.selectedBookmarks}"
           .renamingId="${this.renamingId}"
           .imageUrls="${this.imageUrls}"
           .shoppingCollectionFolderId="${this.shoppingCollectionFolderId}"
           .bookmarksService="${this.bookmarksService}"
-          .draggable="${this.canDrag}"
-          .can-drag="${this.canDrag}"
+          .draggable="${String(this.canDrag)}"
+          ?can-drag="${this.canDrag}"
           .keyArrowNavigationService="${this.keyArrowNavigationService}"
           .contextMenuBookmark="${this.contextMenuBookmark}">
       </power-bookmark-row>
     `)}`: ''
   }`;
-} else {
-    return html`
-    ${this.compact && this.bookmarksTreeViewEnabled ? html`
-      <div id="bookmark">
-        ${urlListItem}
-      </div>` : urlListItem
-    }`;
   }
+
+  return html`
+    ${this.compact && this.bookmarksTreeViewEnabled ?
+        html`<div id="bookmark">${urlListItem}</div>` :
+        urlListItem
+  }`;
 }
 // clang-format off
diff --git a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
index deef389..87b839b 100644
--- a/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
+++ b/chrome/browser/resources/side_panel/bookmarks/power_bookmark_row.ts
@@ -74,13 +74,12 @@
     };
   }
 
-  bookmark: chrome.bookmarks.BookmarkTreeNode;
+  bookmark: chrome.bookmarks.BookmarkTreeNode = {id: '', title: ''};
   compact: boolean = false;
   contextMenuBookmark: chrome.bookmarks.BookmarkTreeNode|undefined;
   bookmarksTreeViewEnabled: boolean =
       loadTimeData.getBoolean('bookmarksTreeViewEnabled');
   depth: number = 0;
-  forceHover: boolean = false;
   hasCheckbox: boolean = false;
   selectedBookmarks: chrome.bookmarks.BookmarkTreeNode[];
   renamingId: string = '';
@@ -108,7 +107,7 @@
     this.onInputDisplayChange_();
     this.addEventListener('keydown', this.onKeydown_);
     this.addEventListener('focus', this.onFocus_);
-    this.isPriceTracked = this.isPriceTracked_(this.bookmark);
+    this.isPriceTracked = this.isPriceTracked_();
 
     const callbackRouter = this.priceTrackingProxy_.getCallbackRouter();
     this.shoppingListenerIds_.push(
@@ -238,8 +237,8 @@
     }));
   }
 
-  protected renamingItem_(id: string) {
-    return id === this.renamingId;
+  protected isRenamingItem_(): boolean {
+    return this.bookmark.id === this.renamingId;
   }
 
   protected isCheckboxChecked_(): boolean {
@@ -251,7 +250,7 @@
   }
 
   protected showTrailingIcon_(): boolean {
-    return !this.renamingItem_(this.bookmark?.id) && !this.hasCheckbox;
+    return !this.isRenamingItem_() && !this.hasCheckbox;
   }
 
   protected onExpandedChanged_(event: CustomEvent<{value: boolean}>) {
@@ -291,8 +290,7 @@
     // Ignore clicks on the row when it has an input, to ensure the row doesn't
     // eat input clicks. Also ignore clicks if the row has no associated
     // bookmark, or if the event is a right-click.
-    if (this.renamingItem_(this.bookmark?.id) || !this.bookmark ||
-        event.button === 2) {
+    if (this.isRenamingItem_() || !this.bookmark || event.button === 2) {
       return;
     }
     // In compact view, if the item is a folder, ignore row clicks to toggle
@@ -304,7 +302,7 @@
     }
     event.preventDefault();
     event.stopPropagation();
-    if (this.hasCheckbox && this.canEdit_(this.bookmark)) {
+    if (this.hasCheckbox && this.canEdit_()) {
       // Clicking the row should trigger a checkbox click rather than a
       // standard row click.
       const checkbox =
@@ -414,18 +412,16 @@
     this.dispatchEvent(this.createInputChangeEvent_(null));
   }
 
-  private isPriceTracked_(bookmark: chrome.bookmarks.BookmarkTreeNode):
-      boolean {
-    return !!this.bookmarksService?.getPriceTrackedInfo(bookmark);
+  private isPriceTracked_(): boolean {
+    return !!this.bookmarksService?.getPriceTrackedInfo(this.bookmark);
   }
 
   /**
    * Whether the given price-tracked bookmark should display as if discounted.
    */
-  protected showDiscountedPrice_(bookmark: chrome.bookmarks.BookmarkTreeNode):
-      boolean {
+  protected showDiscountedPrice_(): boolean {
     const bookmarkProductInfo =
-        this.bookmarksService?.getPriceTrackedInfo(bookmark);
+        this.bookmarksService?.getPriceTrackedInfo(this.bookmark);
     if (bookmarkProductInfo) {
       return bookmarkProductInfo.info.previousPrice.length > 0;
     }
@@ -454,9 +450,8 @@
     }
   }
 
-  protected getBookmarkForceHover_(bookmark: chrome.bookmarks.BookmarkTreeNode):
-      boolean {
-    return bookmark === this.contextMenuBookmark;
+  protected getBookmarkForceHover_(): boolean {
+    return this.bookmark === this.contextMenuBookmark;
   }
 
   protected shouldExpand_(): boolean|undefined {
@@ -464,14 +459,14 @@
         this.compact;
   }
 
-  protected canEdit_(bookmark: chrome.bookmarks.BookmarkTreeNode): boolean {
-    return bookmark?.id !== loadTimeData.getString('bookmarksBarId') &&
-        bookmark?.id !== loadTimeData.getString('managedBookmarksFolderId');
+  protected canEdit_(): boolean {
+    return this.bookmark?.id !== loadTimeData.getString('bookmarksBarId') &&
+        this.bookmark?.id !==
+        loadTimeData.getString('managedBookmarksFolderId');
   }
 
-  protected isShoppingCollection_(bookmark: chrome.bookmarks.BookmarkTreeNode):
-      boolean {
-    return bookmark?.id === this.shoppingCollectionFolderId;
+  protected isShoppingCollection_(): boolean {
+    return this.bookmark?.id === this.shoppingCollectionFolderId;
   }
 
   protected getBookmarkDescription_(
@@ -503,20 +498,19 @@
     }
   }
 
-  protected getBookmarkImageUrls_(bookmark: chrome.bookmarks.BookmarkTreeNode):
-      string[] {
+  protected getBookmarkImageUrls_(): string[] {
     const imageUrls: string[] = [];
-    if (bookmark?.url) {
+    if (this.bookmark?.url) {
       const imageUrl = Object.entries(this.imageUrls)
-                           .find(([key, _val]) => key === bookmark.id)
+                           .find(([key, _val]) => key === this.bookmark.id)
                            ?.[1];
       if (imageUrl) {
         imageUrls.push(imageUrl);
       }
     } else if (
-        this.canEdit_(bookmark) && bookmark?.children &&
-        !this.isShoppingCollection_(bookmark)) {
-      bookmark?.children.forEach((child) => {
+        this.canEdit_() && this.bookmark?.children &&
+        !this.isShoppingCollection_()) {
+      this.bookmark?.children.forEach(child => {
         const childImageUrl: string =
             Object.entries(this.imageUrls)
                 .find(([key, _val]) => key === child.id)
@@ -529,38 +523,32 @@
     return imageUrls;
   }
 
-  protected getBookmarkMenuA11yLabel_(url: string|undefined, title: string):
-      string {
-    if (url) {
-      return loadTimeData.getStringF('bookmarkMenuLabel', title);
-    } else {
-      return loadTimeData.getStringF('folderMenuLabel', title);
-    }
+  protected getBookmarkMenuA11yLabel_(): string {
+    return loadTimeData.getStringF(
+        this.bookmark.url ? 'bookmarkMenuLabel' : 'folderMenuLabel',
+        this.bookmark.title);
   }
 
-  protected getBookmarkA11yLabel_(url: string|undefined, title: string):
-      string {
+  protected getBookmarkA11yLabel_(): string {
     if (this.hasCheckbox) {
       if (this.isCheckboxChecked_()) {
-        if (url) {
-          return loadTimeData.getStringF('deselectBookmarkLabel', title);
-        }
-        return loadTimeData.getStringF('deselectFolderLabel', title);
-      } else {
-        if (url) {
-          return loadTimeData.getStringF('selectBookmarkLabel', title);
-        }
-        return loadTimeData.getStringF('selectFolderLabel', title);
+        return loadTimeData.getStringF(
+            this.bookmark.url ? 'deselectBookmarkLabel' : 'deselectFolderLabel',
+            this.bookmark.title);
       }
+
+      return loadTimeData.getStringF(
+          this.bookmark.url ? 'selectBookmarkLabel' : 'selectFolderLabel',
+          this.bookmark.title);
     }
-    if (url) {
-      return loadTimeData.getStringF('openBookmarkLabel', title);
-    }
-    return loadTimeData.getStringF('openFolderLabel', title);
+
+    return loadTimeData.getStringF(
+        this.bookmark.url ? 'openBookmarkLabel' : 'openFolderLabel',
+        this.bookmark.title);
   }
 
-  protected getBookmarkA11yDescription_(
-      bookmark: chrome.bookmarks.BookmarkTreeNode): string {
+  protected getBookmarkA11yDescription_(): string {
+    const bookmark = this.bookmark;
     let description = '';
     if (this.bookmarksService?.getPriceTrackedInfo(bookmark)) {
       description += loadTimeData.getStringF(
@@ -575,15 +563,14 @@
     return description;
   }
 
-  protected getBookmarkDescriptionMeta_(bookmark:
-                                            chrome.bookmarks.BookmarkTreeNode) {
+  protected getBookmarkDescriptionMeta_() {
     // If there is a price available for the product and it isn't being
     // tracked, return the current price which will be added to the description
     // meta section.
     const productInfo =
-        this.bookmarksService?.getAvailableProductInfo(bookmark);
+        this.bookmarksService?.getAvailableProductInfo(this.bookmark);
     if (productInfo && productInfo.info.currentPrice &&
-        !this.isPriceTracked_(bookmark)) {
+        !this.isPriceTracked_()) {
       return productInfo.info.currentPrice;
     }
 
diff --git a/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.cc b/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.cc
index 17a5c52..4f969937 100644
--- a/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.cc
+++ b/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.cc
@@ -8,6 +8,7 @@
 #include "base/metrics/user_metrics_action.h"
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/supervised_user/supervised_user_service_factory.h"
@@ -106,3 +107,8 @@
       break;
   }
 }
+
+bool ChromeSupervisedUserServicePlatformDelegateBase::ShouldCloseIncognitoTabs()
+    const {
+  return !IncognitoModePrefs::IsIncognitoAllowed(&profile_.get());
+}
diff --git a/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.h b/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.h
index a88b8c1..4113f8fa 100644
--- a/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.h
+++ b/chrome/browser/supervised_user/chrome_supervised_user_service_platform_delegate_base.h
@@ -23,6 +23,7 @@
   // supervised_user::SupervisedUserService::PlatformDelegate::
   std::string GetCountryCode() const override;
   version_info::Channel GetChannel() const override;
+  bool ShouldCloseIncognitoTabs() const override;
 
   // ProfileObserver::
   void OnOffTheRecordProfileCreated(Profile* off_the_record) override;
diff --git a/chrome/browser/supervised_user/supervised_user_incognito_browsertest.cc b/chrome/browser/supervised_user/supervised_user_incognito_browsertest.cc
index 452ddca..c698c3d 100644
--- a/chrome/browser/supervised_user/supervised_user_incognito_browsertest.cc
+++ b/chrome/browser/supervised_user/supervised_user_incognito_browsertest.cc
@@ -7,10 +7,12 @@
 #include "chrome/browser/ui/browser_list.h"
 #include "chrome/browser/ui/browser_list_observer.h"
 #include "chrome/test/supervised_user/supervision_mixin.h"
+#include "components/supervised_user/core/browser/supervised_user_preferences.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/test_utils.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+namespace supervised_user {
 namespace {
 
 class AllIncognitoBrowsersClosedWaiter : public BrowserListObserver {
@@ -40,16 +42,13 @@
 };
 
 class SupervisedUserIncognitoBrowserTest
-    : public MixinBasedInProcessBrowserTest,
-      public ::testing::WithParamInterface<
-          supervised_user::SupervisionMixin::SignInMode> {
+    : public MixinBasedInProcessBrowserTest {
  protected:
-  supervised_user::SupervisionMixin supervision_mixin{
+  SupervisionMixin supervision_mixin{
       mixin_host_,
       this,
       embedded_test_server(),
-      {.sign_in_mode =
-           supervised_user::SupervisionMixin::SignInMode::kSignedOut}};
+      {.sign_in_mode = SupervisionMixin::SignInMode::kSignedOut}};
 };
 
 // ChromeOS Ash does not support the browser being signed out on a supervised
@@ -66,8 +65,7 @@
   CHECK_EQ(browser_list->GetIncognitoBrowserCount(), 1u);
 
   // Sign in as a regular user.
-  supervision_mixin.SignIn(
-      supervised_user::SupervisionMixin::SignInMode::kRegular);
+  supervision_mixin.SignIn(SupervisionMixin::SignInMode::kRegular);
 
   // Check the incognito window remains open.
   base::RunLoop().RunUntilIdle();
@@ -87,12 +85,42 @@
   AllIncognitoBrowsersClosedWaiter incognito_closed_waiter;
 
   // Sign in as a supervised user.
-  supervision_mixin.SignIn(
-      supervised_user::SupervisionMixin::SignInMode::kSupervised);
+  supervision_mixin.SignIn(SupervisionMixin::SignInMode::kSupervised);
 
   // Check the incognito window remains open.
   incognito_closed_waiter.Wait();
+  ASSERT_EQ(browser_list->GetIncognitoBrowserCount(), 0u);
 }
+
+IN_PROC_BROWSER_TEST_F(SupervisedUserIncognitoBrowserTest,
+                       BrowserContentFiltersCloseIncognito) {
+  BrowserList* browser_list = BrowserList::GetInstance();
+
+  // Create a new incognito window (this is allowed as the user is not signed
+  // in).
+  CHECK_EQ(browser_list->GetIncognitoBrowserCount(), 0u);
+  CreateIncognitoBrowser();
+  CHECK_EQ(browser_list->GetIncognitoBrowserCount(), 1u);
+
+  AllIncognitoBrowsersClosedWaiter incognito_closed_waiter;
+
+  // This filtering is account-agnostic (Family Link users do not have
+  // entrypoint here).
+  EnableBrowserContentFilters(*browser()->profile()->GetPrefs());
+
+  // Check the incognito window remains open.
+  incognito_closed_waiter.Wait();
+  ASSERT_EQ(browser_list->GetIncognitoBrowserCount(), 0u);
+  // CreateIncognitoBrowser() would crash here.
+
+  // This filtering is account-agnostic (Family Link users do not have
+  // entrypoint here).
+  DisableBrowserContentFilters(*browser()->profile()->GetPrefs());
+  CreateIncognitoBrowser();
+  CHECK_EQ(browser_list->GetIncognitoBrowserCount(), 1u);
+}
+
 #endif  // !BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace
+}  // namespace supervised_user
diff --git a/chrome/browser/tab_ui/android/BUILD.gn b/chrome/browser/tab_ui/android/BUILD.gn
index 5a2b3c65..f743765 100644
--- a/chrome/browser/tab_ui/android/BUILD.gn
+++ b/chrome/browser/tab_ui/android/BUILD.gn
@@ -69,7 +69,6 @@
     "java/res/values/attrs.xml",
     "java/res/values/colors.xml",
     "java/res/values/dimens.xml",
-    "java/res/values/styles.xml",
     "java/res/values/values.xml",
   ]
   deps = [
diff --git a/chrome/browser/tab_ui/android/java/res/values/attrs.xml b/chrome/browser/tab_ui/android/java/res/values/attrs.xml
index f476722f..916f279 100644
--- a/chrome/browser/tab_ui/android/java/res/values/attrs.xml
+++ b/chrome/browser/tab_ui/android/java/res/values/attrs.xml
@@ -7,11 +7,6 @@
 -->
 
 <resources>
-  <declare-styleable name="TabThumbnailPlaceholder">
-    <attr name="colorTileBase" format="color" />
-    <attr name="elevationTileBase" format="dimension" />
-  </declare-styleable>
-
   <declare-styleable name="TabThumbnailView">
     <attr name="cornerRadiusTopStart" format="dimension" />
     <attr name="cornerRadiusTopEnd" format="dimension" />
diff --git a/chrome/browser/tab_ui/android/java/res/values/colors.xml b/chrome/browser/tab_ui/android/java/res/values/colors.xml
index 00d2ba7..0125f877 100644
--- a/chrome/browser/tab_ui/android/java/res/values/colors.xml
+++ b/chrome/browser/tab_ui/android/java/res/values/colors.xml
@@ -9,8 +9,8 @@
   <color name="incognito_tab_title_color">@color/baseline_neutral_90</color>
   <color name="incognito_tab_title_selected_color">@color/baseline_primary_20</color>
 
-  <color name="incognito_tab_thumbnail_placeholder_color">@color/baseline_neutral_variant_80_alpha_15</color>
-  <color name="incognito_tab_thumbnail_placeholder_selected_color">@color/baseline_primary_90</color>
+  <color name="incognito_tab_thumbnail_placeholder_color">@color/gm3_baseline_surface_container_low_dark</color>
+  <color name="incognito_tab_thumbnail_placeholder_selected_color">@color/baseline_primary_20_alpha_38</color>
 
   <color name="incognito_tab_bg_color">@color/gm3_baseline_surface_container_highest_dark</color>
   <color name="incognito_tab_bg_selected_color">@color/baseline_primary_80</color>
diff --git a/chrome/browser/tab_ui/android/java/res/values/dimens.xml b/chrome/browser/tab_ui/android/java/res/values/dimens.xml
index a20d67c..946779cc 100644
--- a/chrome/browser/tab_ui/android/java/res/values/dimens.xml
+++ b/chrome/browser/tab_ui/android/java/res/values/dimens.xml
@@ -15,5 +15,4 @@
   <dimen name="tab_bg_elevation">@dimen/default_elevation_5</dimen>
 
   <integer name="tab_thumbnail_placeholder_selected_color_alpha">38</integer>
-  <integer name="tab_thumbnail_placeholder_color_alpha">255</integer>
 </resources>
diff --git a/chrome/browser/tab_ui/android/java/res/values/styles.xml b/chrome/browser/tab_ui/android/java/res/values/styles.xml
deleted file mode 100644
index a38a70b..0000000
--- a/chrome/browser/tab_ui/android/java/res/values/styles.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-
-<!--
-Copyright 2024 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-
-<resources>
-  <style name="TabThumbnailPlaceholderStyle">
-    <item name="colorTileBase">?attr/colorSurface</item>
-    <item name="elevationTileBase">@dimen/default_elevation_1</item>
-  </style>
-
-  <style name="TabThumbnailPlaceholderStyle.Selected">
-    <item name="colorTileBase">?attr/colorOnPrimary</item>
-    <item name="elevationTileBase">@dimen/default_elevation_0</item>
-  </style>
-</resources>
\ No newline at end of file
diff --git a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabUiThemeUtils.java b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabUiThemeUtils.java
index 1fbff6e..7f08c5a 100644
--- a/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabUiThemeUtils.java
+++ b/chrome/browser/tab_ui/android/java/src/org/chromium/chrome/browser/tab_ui/TabUiThemeUtils.java
@@ -5,21 +5,22 @@
 package org.chromium.chrome.browser.tab_ui;
 
 import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Color;
 
 import androidx.annotation.ColorInt;
 import androidx.annotation.ColorRes;
-import androidx.annotation.StyleRes;
 import androidx.core.content.ContextCompat;
 
 import com.google.android.material.color.MaterialColors;
-import com.google.android.material.elevation.ElevationOverlayProvider;
 
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.components.browser_ui.styles.SemanticColorUtils;
 
-/** Utility methods for providing colors and styles for the tab UI. */
+/**
+ * Utility methods for providing colors and styles for the tab UI.
+ * @deprecated Add new changes to TabUiThemeUtil.java, or TabUiThemeProvider.java.
+ */
 @NullMarked
+@Deprecated
 public class TabUiThemeUtils {
     private static final String TAG = "TabUiThemeUtils";
 
@@ -77,38 +78,17 @@
                             ? R.color.incognito_tab_thumbnail_placeholder_selected_color
                             : R.color.incognito_tab_thumbnail_placeholder_color;
             return context.getColor(colorRes);
-        } else {
+        }
+
+        if (isSelected) {
             int alpha =
                     context.getResources()
-                            .getInteger(
-                                    isSelected
-                                            ? R.integer
-                                                    .tab_thumbnail_placeholder_selected_color_alpha
-                                            : R.integer.tab_thumbnail_placeholder_color_alpha);
-
-            @StyleRes
-            int styleRes =
-                    isSelected
-                            ? R.style.TabThumbnailPlaceholderStyle_Selected
-                            : R.style.TabThumbnailPlaceholderStyle;
-            TypedArray ta =
-                    context.obtainStyledAttributes(styleRes, R.styleable.TabThumbnailPlaceholder);
-
-            @ColorInt
-            int baseColor =
-                    ta.getColor(
-                            R.styleable.TabThumbnailPlaceholder_colorTileBase, Color.TRANSPARENT);
-            float tileSurfaceElevation =
-                    ta.getDimension(R.styleable.TabThumbnailPlaceholder_elevationTileBase, 0);
-
-            ta.recycle();
-            if (tileSurfaceElevation != 0) {
-                ElevationOverlayProvider eop = new ElevationOverlayProvider(context);
-                baseColor = eop.compositeOverlay(baseColor, tileSurfaceElevation);
-            }
-
+                            .getInteger(R.integer.tab_thumbnail_placeholder_selected_color_alpha);
+            @ColorInt int baseColor = SemanticColorUtils.getColorOnPrimary(context);
             return MaterialColors.compositeARGBWithAlpha(baseColor, alpha);
         }
+
+        return SemanticColorUtils.getColorSurfaceContainerLow(context);
     }
 
     /**
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn
index 4818d5c..6c11f15 100644
--- a/chrome/browser/ui/BUILD.gn
+++ b/chrome/browser/ui/BUILD.gn
@@ -2260,6 +2260,7 @@
       "//chrome/browser/ash/boca/on_task",
       "//chrome/browser/ash/boot_times_recorder",
       "//chrome/browser/ash/borealis",
+      "//chrome/browser/ash/browser_delegate:impl",
       "//chrome/browser/ash/bruschetta",
       "//chrome/browser/ash/child_accounts",
       "//chrome/browser/ash/child_accounts/on_device_controls",
@@ -2782,6 +2783,7 @@
       "//chrome/browser/ash/boca/on_task",
       "//chrome/browser/ash/boot_times_recorder",
       "//chrome/browser/ash/borealis",
+      "//chrome/browser/ash/browser_delegate:impl",
       "//chrome/browser/ash/camera_mic",
       "//chrome/browser/ash/child_accounts",
       "//chrome/browser/ash/child_accounts/on_device_controls",
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
index e944920..24639131 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
@@ -1303,7 +1303,6 @@
         // This method only has an Account to match the type of the event listener. However, it
         // should be non-null because an account must have been selected in order to reach an error
         // dialog.
-        assert buttonData.mIdpMetadata == null;
         assert buttonData.mAccount != null;
         if (!shouldInputBeProcessed()) return;
         onDismissed(IdentityRequestDialogDismissReason.GOT_IT_BUTTON);
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionWidgetModeControllerTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionWidgetModeControllerTest.java
index da341d3..9ec2fc2 100644
--- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionWidgetModeControllerTest.java
+++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionWidgetModeControllerTest.java
@@ -147,7 +147,7 @@
             mModel.get(ItemProperties.CONTINUE_BUTTON)
                     .get(ContinueButtonProperties.PROPERTIES)
                     .mOnClickListener
-                    .onResult(new ButtonData(mAnaAccount, /* idpMetadata= */ null));
+                    .onResult(new ButtonData(mAnaAccount, /* idpMetadata= */ mIdpMetadata));
             verify(mMockDelegate, times(++count))
                     .onDismissed(IdentityRequestDialogDismissReason.GOT_IT_BUTTON);
             assertTrue(mMediator.wasDismissed());
diff --git a/chrome/browser/ui/ash/DEPS b/chrome/browser/ui/ash/DEPS
index 1ff44b6..5d0d5d6 100644
--- a/chrome/browser/ui/ash/DEPS
+++ b/chrome/browser/ui/ash/DEPS
@@ -5,6 +5,11 @@
   # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for
   # details.
   "-chrome",
+
+  # Browser abstraction for use by ChromeOS feature code. Will eventually be
+  # moved out of chrome/.
+  "+chrome/browser/ash/browser_delegate/browser_controller.h",
+  "+chrome/browser/ash/browser_delegate/browser_delegate.h",
 ]
 
 specific_include_rules = {
diff --git a/chrome/browser/ui/ash/main_extra_parts/BUILD.gn b/chrome/browser/ui/ash/main_extra_parts/BUILD.gn
index 8b9c75d1..3c659ee 100644
--- a/chrome/browser/ui/ash/main_extra_parts/BUILD.gn
+++ b/chrome/browser/ui/ash/main_extra_parts/BUILD.gn
@@ -31,6 +31,7 @@
     "//chrome/browser/ash/app_list",
     "//chrome/browser/ash/app_restore:app_restore",
     "//chrome/browser/ash/boca",
+    "//chrome/browser/ash/browser_delegate:impl",
     "//chrome/browser/ash/geolocation",
     "//chrome/browser/ash/growth",
     "//chrome/browser/ash/input_device_settings",
diff --git a/chrome/browser/ui/ash/main_extra_parts/DEPS b/chrome/browser/ui/ash/main_extra_parts/DEPS
index 4e4e9e9..8662382 100644
--- a/chrome/browser/ui/ash/main_extra_parts/DEPS
+++ b/chrome/browser/ui/ash/main_extra_parts/DEPS
@@ -15,9 +15,9 @@
   "+chrome/browser/ash/arc/util",
   "+chrome/browser/ash/auth",
   "+chrome/browser/ash/boca",
+  "+chrome/browser/ash/browser_delegate",
   "+chrome/browser/ash/geolocation",
   "+chrome/browser/ash/growth",
-  "+chrome/browser/ui/ash/graduation",
   "+chrome/browser/ash/input_device_settings",
   "+chrome/browser/ash/lobster",
   "+chrome/browser/ash/login/demo_mode",
@@ -46,6 +46,7 @@
   "+chrome/browser/ui/ash/arc",
   "+chrome/browser/ui/ash/cast_config",
   "+chrome/browser/ui/ash/desks",
+  "+chrome/browser/ui/ash/graduation",
   "+chrome/browser/ui/ash/input_method",
   "+chrome/browser/ui/ash/in_session_auth",
   "+chrome/browser/ui/ash/login",
diff --git a/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.cc b/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.cc
index bf1318d..06115c4e 100644
--- a/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.cc
+++ b/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.cc
@@ -35,6 +35,7 @@
 #include "chrome/browser/ash/app_restore/full_restore_service.h"
 #include "chrome/browser/ash/auth/active_session_fingerprint_client_impl.h"
 #include "chrome/browser/ash/boca/boca_app_client_impl.h"
+#include "chrome/browser/ash/browser_delegate/browser_controller_impl.h"
 #include "chrome/browser/ash/geolocation/system_geolocation_source.h"
 #include "chrome/browser/ash/growth/campaigns_manager_client_impl.h"
 #include "chrome/browser/ash/growth/campaigns_manager_session.h"
@@ -376,6 +377,7 @@
 
   read_write_cards_manager_ =
       std::make_unique<chromeos::ReadWriteCardsManagerImpl>(
+          g_browser_process->GetFeatures()->application_locale_storage(),
           g_browser_process->shared_url_loader_factory());
 
   if (base::FeatureList::IsEnabled(ash::features::kReadaheadForLogin)) {
@@ -453,6 +455,8 @@
         std::make_unique<ash::graduation::GraduationManagerImpl>();
   }
 
+  browser_controller_ = std::make_unique<ash::BrowserControllerImpl>();
+
   if (ash::features::IsWelcomeExperienceEnabled()) {
     peripherals_app_delegate_ =
         std::make_unique<ash::PeripheralsAppDelegateImpl>();
diff --git a/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.h b/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.h
index b40600c..9eb27070 100644
--- a/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.h
+++ b/chrome/browser/ui/ash/main_extra_parts/chrome_browser_main_extra_parts_ash.h
@@ -17,6 +17,7 @@
 namespace ash {
 class ArcWindowWatcher;
 class ActiveSessionFingerprintClient;
+class BrowserControllerImpl;
 class InSessionAuthTokenProviderImpl;
 class MagicBoostStateAsh;
 class NetworkPortalNotificationController;
@@ -198,6 +199,7 @@
   std::unique_ptr<ash::OobeDialogUtil> oobe_dialog_util_;
   std::unique_ptr<chromeos::ReadWriteCardsManager> read_write_cards_manager_;
   std::unique_ptr<ash::graduation::GraduationManager> graduation_manager_;
+  std::unique_ptr<ash::BrowserControllerImpl> browser_controller_;
 
   // Initialized in PostBrowserStart in all configs:
   std::unique_ptr<MobileDataNotifications> mobile_data_notifications_;
diff --git a/chrome/browser/ui/ash/quick_answers/BUILD.gn b/chrome/browser/ui/ash/quick_answers/BUILD.gn
index 7de05b3..520bf74 100644
--- a/chrome/browser/ui/ash/quick_answers/BUILD.gn
+++ b/chrome/browser/ui/ash/quick_answers/BUILD.gn
@@ -36,7 +36,6 @@
 
   deps = [
     "//ash",
-    "//chrome/browser:browser_process",
     "//chrome/browser/profiles:profile",
     "//chrome/browser/ui/ash/editor_menu:utils",
     "//chrome/browser/ui/ash/quick_answers/ui:loading_view",
@@ -56,6 +55,7 @@
     "//chromeos/strings:strings_grit",
     "//chromeos/ui/vector_icons",
     "//components/account_id",
+    "//components/application_locale_storage",
     "//components/language/core/browser",
     "//components/omnibox/browser:vector_icons",
     "//components/prefs",
diff --git a/chrome/browser/ui/ash/quick_answers/DEPS b/chrome/browser/ui/ash/quick_answers/DEPS
index 6ad4567..92db8371 100644
--- a/chrome/browser/ui/ash/quick_answers/DEPS
+++ b/chrome/browser/ui/ash/quick_answers/DEPS
@@ -17,6 +17,7 @@
     "+chrome/browser/ash/accessibility",
     "+chrome/browser/ash/login/users",
     "+chrome/browser/ash/profiles",
+    "+chrome/browser/global_features.h",
     "+chrome/browser/notifications",
   ],
   ".*pixeltest\.cc": [
@@ -26,7 +27,6 @@
     "+chrome/browser/ui/browser.h",
   ],
   "quick_answers_view\.cc": [
-    "+chrome/browser/browser_process.h",
     "+chrome/browser/ui/color/chrome_color_id.h",
   ],
 }
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
index 91d5491..b7cfd08 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.cc
@@ -184,17 +184,21 @@
 }  // namespace
 
 QuickAnswersControllerImpl::QuickAnswersControllerImpl(
+    ApplicationLocaleStorage* application_locale_storage,
     chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller)
-    : QuickAnswersControllerImpl(read_write_cards_ui_controller,
+    : QuickAnswersControllerImpl(application_locale_storage,
+                                 read_write_cards_ui_controller,
                                  CreateQuickAnswersState()) {}
 
 QuickAnswersControllerImpl::QuickAnswersControllerImpl(
+    ApplicationLocaleStorage* application_locale_storage,
     chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller,
     std::unique_ptr<QuickAnswersState> quick_answers_state)
     : quick_answers_state_(std::move(quick_answers_state)),
       read_write_cards_ui_controller_(read_write_cards_ui_controller),
       quick_answers_ui_controller_(
-          std::make_unique<QuickAnswersUiController>(this)) {}
+          std::make_unique<QuickAnswersUiController>(application_locale_storage,
+                                                     this)) {}
 
 QuickAnswersControllerImpl::~QuickAnswersControllerImpl() {
   // `PerformOnConsentAccepted` depends on `QuickAnswersState`. It has to be
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h
index 0b5657c..4e0d1e30 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h
@@ -20,6 +20,7 @@
 #include "chromeos/components/quick_answers/quick_answers_model.h"
 #include "ui/gfx/geometry/rect.h"
 
+class ApplicationLocaleStorage;
 class Profile;
 class QuickAnswersUiController;
 
@@ -31,9 +32,13 @@
  public:
   using TimeTickNowFunction = base::RepeatingCallback<base::TimeTicks()>;
 
-  explicit QuickAnswersControllerImpl(
-      chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller);
+  // `application_locale_storage` must not be null and must outlive `this`.
   QuickAnswersControllerImpl(
+      ApplicationLocaleStorage* application_locale_storage,
+      chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller);
+  // `application_locale_storage` must not be null and must outlive `this`.
+  QuickAnswersControllerImpl(
+      ApplicationLocaleStorage* application_locale_storage,
       chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller,
       std::unique_ptr<QuickAnswersState> quick_answers_state);
   QuickAnswersControllerImpl(const QuickAnswersControllerImpl&) = delete;
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc
index f315520..cefe4f5 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.cc
@@ -9,9 +9,11 @@
 #include "ash/public/cpp/new_window_delegate.h"
 #include "ash/webui/settings/public/constants/routes.mojom-forward.h"
 #include "ash/webui/settings/public/constants/setting.mojom-shared.h"
+#include "base/check_deref.h"
 #include "base/check_is_test.h"
 #include "base/check_op.h"
 #include "base/functional/bind.h"
+#include "base/memory/raw_ref.h"
 #include "base/notreached.h"
 #include "base/strings/stringprintf.h"
 #include "chrome/browser/profiles/profile.h"
@@ -31,6 +33,7 @@
 #include "chromeos/components/quick_answers/quick_answers_model.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
+#include "components/application_locale_storage/application_locale_storage.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "ui/aura/client/aura_constants.h"
 #include "ui/base/l10n/l10n_util.h"
@@ -71,8 +74,10 @@
 using chromeos::ReadWriteCardsUiController;
 
 QuickAnswersUiController::QuickAnswersUiController(
+    ApplicationLocaleStorage* application_locale_storage,
     QuickAnswersControllerImpl* controller)
-    : controller_(controller) {}
+    : application_locale_storage_(CHECK_DEREF(application_locale_storage)),
+      controller_(controller) {}
 
 QuickAnswersUiController::~QuickAnswersUiController() {
   // Created Quick Answers UIs (e.g., `UserConsentView`) can have dependency to
@@ -229,7 +234,8 @@
 
   // QuickAnswersView was initiated with a loading page and will be updated
   // when quick answers result from server side is ready.
-  quick_answers_view()->SetResult(structured_result);
+  quick_answers_view()->SetResult(structured_result,
+                                  application_locale_storage_->Get());
 }
 
 void QuickAnswersUiController::SetActiveQuery(Profile* profile,
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h
index d8e816d..523dd2f 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller.h
@@ -23,6 +23,7 @@
 #include "ui/views/widget/unique_widget_ptr.h"
 #include "ui/views/widget/widget.h"
 
+class ApplicationLocaleStorage;
 class Profile;
 class QuickAnswersControllerImpl;
 
@@ -47,7 +48,9 @@
       base::RepeatingCallback<void(const std::string&)>;
   using FakeOpenWebUrlCallback = base::RepeatingCallback<void(const GURL&)>;
 
-  explicit QuickAnswersUiController(QuickAnswersControllerImpl* controller);
+  // `application_locale_storage` must not be null and must outlive `this`.
+  QuickAnswersUiController(ApplicationLocaleStorage* application_locale_storage,
+                           QuickAnswersControllerImpl* controller);
   ~QuickAnswersUiController();
 
   QuickAnswersUiController(const QuickAnswersUiController&) = delete;
@@ -167,6 +170,8 @@
   // Constructs/resets the Quick Answers rich card view.
   void CreateRichAnswersView();
 
+  const raw_ref<ApplicationLocaleStorage> application_locale_storage_;
+
   raw_ptr<QuickAnswersControllerImpl> controller_ = nullptr;
 
   // Widget pointers for quick answers related views.
diff --git a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
index 263e620..3bd1c30 100644
--- a/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
+++ b/chrome/browser/ui/ash/quick_answers/quick_answers_ui_controller_unittest.cc
@@ -14,10 +14,12 @@
 #include "base/memory/raw_ptr.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
+#include "chrome/browser/global_features.h"
 #include "chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h"
 #include "chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.h"
 #include "chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chromeos/components/quick_answers/test/fake_quick_answers_state.h"
 #include "chromeos/strings/grit/chromeos_strings.h"
 #include "testing/gmock/include/gmock/gmock.h"
@@ -103,6 +105,9 @@
         std::make_unique<FakeQuickAnswersState>();
     fake_quick_answers_state_ = fake_quick_answers_state.get();
     return std::make_unique<QuickAnswersControllerImpl>(
+        TestingBrowserProcess::GetGlobal()
+            ->GetFeatures()
+            ->application_locale_storage(),
         read_write_cards_ui_controller, std::move(fake_quick_answers_state));
   }
 
diff --git a/chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.cc b/chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.cc
index 3e2ec55..f53159c 100644
--- a/chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.cc
+++ b/chrome/browser/ui/ash/quick_answers/test/chrome_quick_answers_test_base.cc
@@ -11,8 +11,10 @@
 #include "base/strings/utf_string_conversions.h"
 #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
 #include "chrome/browser/ash/profiles/profile_helper.h"
+#include "chrome/browser/global_features.h"
 #include "chrome/browser/ui/ash/quick_answers/quick_answers_controller_impl.h"
 #include "chrome/browser/ui/ash/read_write_cards/read_write_cards_ui_controller.h"
+#include "chrome/test/base/testing_browser_process.h"
 #include "chrome/test/base/testing_profile.h"
 #include "chromeos/ash/components/browser_context_helper/annotated_account_id.h"
 #include "chromeos/components/quick_answers/test/fake_quick_answers_state.h"
@@ -134,6 +136,9 @@
 ChromeQuickAnswersTestBase::CreateQuickAnswersControllerImpl(
     chromeos::ReadWriteCardsUiController& read_write_cards_ui_controller) {
   return std::make_unique<QuickAnswersControllerImpl>(
+      TestingBrowserProcess::GetGlobal()
+          ->GetFeatures()
+          ->application_locale_storage(),
       read_write_cards_ui_controller);
 }
 
diff --git a/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.cc b/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.cc
index f53d833..6be2569 100644
--- a/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.cc
+++ b/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.cc
@@ -14,7 +14,6 @@
 #include "base/notreached.h"
 #include "base/strings/stringprintf.h"
 #include "base/strings/utf_string_conversions.h"
-#include "chrome/browser/browser_process.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/editor_menu/utils/focus_search.h"
 #include "chrome/browser/ui/ash/editor_menu/utils/pre_target_handler.h"
@@ -209,15 +208,16 @@
 
 void SetResultTo(ResultView* result_view,
                  TranslationResult* translation_result,
-                 Design design) {
+                 Design design,
+                 const std::string& application_locale) {
   result_view->SetFirstLineText(
       base::UTF8ToUTF16(translation_result->text_to_translate));
 
   if (design != Design::kCurrent) {
     std::u16string display_name_locale =
         l10n_util::GetDisplayNameForLocaleWithoutCountry(
-            translation_result->source_locale,
-            g_browser_process->GetApplicationLocale(), /*is_for_ui=*/true);
+            translation_result->source_locale, application_locale,
+            /*is_for_ui=*/true);
     if (!display_name_locale.empty()) {
       result_view->SetFirstLineSubText(display_name_locale);
     }
@@ -668,7 +668,8 @@
   return intent_;
 }
 
-void QuickAnswersView::SetResult(const StructuredResult& structured_result) {
+void QuickAnswersView::SetResult(const StructuredResult& structured_result,
+                                 const std::string& application_locale) {
   // Check if the view (or any of its children) had focus before resetting the
   // view, so it can be restored for the updated view.
   bool pane_already_had_focus = HasFocusInside();
@@ -683,7 +684,7 @@
     case ResultType::kTranslationResult:
       SetIntent(Intent::kTranslation);
       SetResultTo(result_view_, structured_result.translation_result.get(),
-                  design_);
+                  design_, application_locale);
       break;
     case ResultType::kUnitConversionResult:
       SetIntent(Intent::kUnitConversion);
diff --git a/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h b/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h
index 5f4ce57..19000c27 100644
--- a/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h
+++ b/chrome/browser/ui/ash/quick_answers/ui/quick_answers_view.h
@@ -6,6 +6,7 @@
 #define CHROME_BROWSER_UI_ASH_QUICK_ANSWERS_UI_QUICK_ANSWERS_VIEW_H_
 
 #include <optional>
+#include <string>
 #include <vector>
 
 #include "base/functional/callback_forward.h"
@@ -92,7 +93,8 @@
   void SetIntent(Intent intent);
   std::optional<Intent> GetIntent() const;
 
-  void SetResult(const StructuredResult& structured_result);
+  void SetResult(const StructuredResult& structured_result,
+                 const std::string& application_locale);
 
   void ShowRetryView();
 
diff --git a/chrome/browser/ui/ash/read_write_cards/BUILD.gn b/chrome/browser/ui/ash/read_write_cards/BUILD.gn
index 1502a26..8137a0f 100644
--- a/chrome/browser/ui/ash/read_write_cards/BUILD.gn
+++ b/chrome/browser/ui/ash/read_write_cards/BUILD.gn
@@ -60,6 +60,7 @@
     ":read_write_cards_manager",
     "//ash:test_support",
     "//base/test:test_support",
+    "//chrome/browser:global_features",
 
     # TODO(crbug.com/374896328): Remove crosapi use.
     "//chrome/browser/ash/crosapi",
diff --git a/chrome/browser/ui/ash/read_write_cards/DEPS b/chrome/browser/ui/ash/read_write_cards/DEPS
index 3812974..b704ca9 100644
--- a/chrome/browser/ui/ash/read_write_cards/DEPS
+++ b/chrome/browser/ui/ash/read_write_cards/DEPS
@@ -14,6 +14,7 @@
     # TODO(crbug.com/374896328): Remove references to croapi.
     "+chrome/browser/ash/crosapi",
     "+chrome/browser/ash/magic_boost",
+    "+chrome/browser/global_features.h",
     "+chrome/common/chrome_constants.h",
   ],
 }
diff --git a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc
index 4d36262..1db02085 100644
--- a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc
+++ b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.cc
@@ -36,9 +36,11 @@
 using OptInFeatures = crosapi::mojom::MagicBoostController::OptInFeatures;
 
 ReadWriteCardsManagerImpl::ReadWriteCardsManagerImpl(
+    ApplicationLocaleStorage* application_locale_storage,
     scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory)
-    : quick_answers_controller_(
-          std::make_unique<QuickAnswersControllerImpl>(ui_controller_)) {
+    : quick_answers_controller_(std::make_unique<QuickAnswersControllerImpl>(
+          application_locale_storage,
+          ui_controller_)) {
   quick_answers_controller_->SetClient(
       std::make_unique<quick_answers::QuickAnswersClient>(
           shared_url_loader_factory,
diff --git a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.h b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.h
index 680608f..80fdc1c8 100644
--- a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.h
+++ b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl.h
@@ -19,7 +19,9 @@
 #include "chromeos/ash/components/editor_menu/public/cpp/editor_context.h"
 #include "chromeos/ash/components/editor_menu/public/cpp/editor_mode.h"
 
+class ApplicationLocaleStorage;
 class QuickAnswersControllerImpl;
+class ReadWriteCardController;
 
 namespace content {
 class BrowserContext;
@@ -36,8 +38,6 @@
 class EditorMenuControllerImpl;
 }  // namespace editor_menu
 
-class ReadWriteCardController;
-
 using OptInFeatures = crosapi::mojom::MagicBoostController::OptInFeatures;
 
 // `ReadWriteCardsManagerImpl` provides supported UI controller to given context
@@ -45,9 +45,11 @@
 // EditorMenuController, or nullptr.
 class ReadWriteCardsManagerImpl : public ReadWriteCardsManager {
  public:
+  // `application_locale_storage` must not be null and must outlive `this`.
   // `shared_url_loader_factory` should be the instance associated with browser
   // process.
-  explicit ReadWriteCardsManagerImpl(
+  ReadWriteCardsManagerImpl(
+      ApplicationLocaleStorage* application_locale_storage,
       scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory);
   ReadWriteCardsManagerImpl(const ReadWriteCardsManagerImpl&) = delete;
   ReadWriteCardsManagerImpl& operator=(const ReadWriteCardsManagerImpl&) =
diff --git a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl_unittest.cc b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl_unittest.cc
index 6aae77c..afe36868 100644
--- a/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl_unittest.cc
+++ b/chrome/browser/ui/ash/read_write_cards/read_write_cards_manager_impl_unittest.cc
@@ -13,6 +13,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "chrome/browser/ash/magic_boost/magic_boost_controller_ash.h"
 #include "chrome/browser/ash/magic_boost/magic_boost_state_ash.h"
+#include "chrome/browser/global_features.h"
 #include "chrome/browser/ui/ash/editor_menu/editor_menu_card_context.h"
 #include "chrome/browser/ui/ash/editor_menu/editor_menu_controller_impl.h"
 #include "chrome/browser/ui/ash/magic_boost/magic_boost_card_controller.h"
@@ -82,6 +83,9 @@
     // indirectly. `QuickAnswersState` depends on `MagicBoostState`.
     magic_boost_state_ = std::make_unique<ash::MagicBoostStateAsh>();
     manager_ = std::make_unique<ReadWriteCardsManagerImpl>(
+        TestingBrowserProcess::GetGlobal()
+            ->GetFeatures()
+            ->application_locale_storage(),
         TestingBrowserProcess::GetGlobal()->shared_url_loader_factory());
   }
 
diff --git a/chrome/browser/ui/views/autofill/autofill_ai/save_or_update_autofill_ai_data_bubble_view.cc b/chrome/browser/ui/views/autofill/autofill_ai/save_or_update_autofill_ai_data_bubble_view.cc
index 6fc59ceb..1481be3 100644
--- a/chrome/browser/ui/views/autofill/autofill_ai/save_or_update_autofill_ai_data_bubble_view.cc
+++ b/chrome/browser/ui/views/autofill/autofill_ai/save_or_update_autofill_ai_data_bubble_view.cc
@@ -164,7 +164,9 @@
   DialogDelegate::SetButtonLabel(
       ui::mojom::DialogButton::kOk,
       l10n_util::GetStringUTF16(
-          IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_SAVE_BUTTON));
+          controller_->IsSavePrompt()
+              ? IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_SAVE_BUTTON
+              : IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_UPDATE_DIALOG_UPDATE_BUTTON));
   SetAcceptCallback(
       base::BindOnce(&SaveOrUpdateAutofillAiDataBubbleView::OnDialogAccepted,
                      base::Unretained(this)));
@@ -178,6 +180,11 @@
 SaveOrUpdateAutofillAiDataBubbleView::GetAttributeValueView(
     const SaveOrUpdateAutofillAiDataController::EntityAttributeUpdateDetails&
         detail) {
+  const bool existing_entity_added_or_updated_attribute =
+      !controller_->IsSavePrompt() &&
+      detail.update_type !=
+          SaveOrUpdateAutofillAiDataController::EntityAttributeUpdateType::
+              kNewEntityAttributeUnchanged;
   std::unique_ptr<views::BoxLayoutView> atribute_value_row_wrapper =
       GetEntityAttributeAndValueLayout(
           views::BoxLayout::CrossAxisAlignment::kEnd);
@@ -185,7 +192,9 @@
       views::Builder<views::Label>()
           .SetText(detail.attribute_value)
           .SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_RIGHT)
-          .SetTextStyle(views::style::STYLE_BODY_3_MEDIUM)
+          .SetTextStyle(existing_entity_added_or_updated_attribute
+                            ? views::style::STYLE_BODY_4_MEDIUM
+                            : views::style::STYLE_BODY_4)
           .SetAccessibleRole(ax::mojom::Role::kDefinition)
           .SetMultiLine(true)
           .SetAllowCharacterBreak(true)
@@ -194,11 +203,6 @@
   attribute_values_observation_.AddObservation(label.get());
 
   // Only update dialogs have a dot circle in front of added or updated values.
-  const bool existing_entity_added_or_updated_attribute =
-      !controller_->IsSavePrompt() &&
-      detail.update_type !=
-          SaveOrUpdateAutofillAiDataController::EntityAttributeUpdateType::
-              kNewEntityAttributeUnchanged;
   if (!existing_entity_added_or_updated_attribute) {
     atribute_value_row_wrapper->AddChildView(std::move(label));
     return atribute_value_row_wrapper;
diff --git a/chrome/browser/ui/views/certificate_selector.cc b/chrome/browser/ui/views/certificate_selector.cc
index ae47ff4..31e08da 100644
--- a/chrome/browser/ui/views/certificate_selector.cc
+++ b/chrome/browser/ui/views/certificate_selector.cc
@@ -50,13 +50,14 @@
 #include "chrome/browser/glic/widget/glic_window_controller.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_finder.h"
 #include "chrome/browser/ui/views/frame/browser_view.h"
 #endif
 
 #if BUILDFLAG(ENABLE_GLIC)
 namespace {
 
-// Checks that `contents` is for glic, and that glic is attached.
+// Checks that `contents` is for glic.
 bool IsForGlic(content::WebContents* contents) {
   content::WebContents* outer = contents->GetOutermostWebContents();
   glic::GlicKeyedService* glic_service =
@@ -64,8 +65,7 @@
           outer->GetBrowserContext());
   if (glic_service) {
     auto& window_controller = glic_service->window_controller();
-    return window_controller.attached_browser() &&
-           window_controller.GetWebContents() == outer;
+    return window_controller.GetWebContents() == outer;
   }
   return false;
 }
@@ -235,19 +235,18 @@
   // certificate picker on the glic window. This is not fully correct, but
   // satisfies the main dev use case with minimal overhead.
   if (UseGlicDevFlow(web_contents_)) {
-    glic::GlicKeyedService* glic_service =
-        glic::GlicKeyedServiceFactory::GetGlicKeyedService(
-            web_contents_->GetBrowserContext());
-    // Technically there can be a TOCTTOU bug, but this is a dev-only flow we
-    // want to error out quickly.
-    CHECK(glic_service);
-    auto& window_controller = glic_service->window_controller();
-    Browser* browser = window_controller.attached_browser();
-    CHECK(browser);
-    SetModalType(ui::mojom::ModalType::kWindow);
-    constrained_window::CreateBrowserModalDialogViews(
-        this, browser->GetBrowserView().GetNativeWindow())
-        ->Show();
+    Profile* profile =
+        Profile::FromBrowserContext(web_contents_->GetBrowserContext());
+    Browser* browser = chrome::FindLastActiveWithProfile(profile);
+    if (browser) {
+      SetModalType(ui::mojom::ModalType::kWindow);
+      constrained_window::CreateBrowserModalDialogViews(
+          this, browser->GetBrowserView().GetNativeWindow())
+          ->Show();
+    } else {
+      LOG(ERROR) << "Dev error. Make sure there's a browser window of the "
+                    "matching profile open.";
+    }
     return;
   }
 #endif
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.cc b/chrome/browser/ui/views/profiles/profile_menu_view.cc
index b20ce0f..a304b4f 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.cc
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.cc
@@ -103,12 +103,6 @@
 
 namespace {
 
-constexpr int kBusinessIconPadding = 4;
-constexpr int kBusinessIconSize =
-    ProfileMenuViewBase::kManagementBadgeSize - 2 * kBusinessIconPadding;
-
-// Helpers --------------------------------------------------------------------
-
 std::u16string GetSyncErrorButtonText(AvatarSyncErrorType error) {
   switch (error) {
     case AvatarSyncErrorType::kSyncPaused:
@@ -154,8 +148,6 @@
 
 }  // namespace
 
-// ProfileMenuView ---------------------------------------------------------
-
 // static
 bool ProfileMenuView::close_on_deactivate_for_testing_ = true;
 
@@ -171,28 +163,15 @@
   if (profile->IsGuestSession()) {
     BuildGuestIdentity();
     MaybeBuildCloseBrowsersButton();
-    if (base::FeatureList::IsEnabled(
-            switches::kEnableImprovedGuestProfileMenu)) {
-      AddBottomMargin();
-    }
+    AddBottomMargin();
     return;
   }
 
   CHECK(!profile->IsOffTheRecord());
+  SetMenuTitleForAccessibility();
+  BuildIdentityWithCallToAction();
+
   const bool is_web_app = web_app::AppBrowserController::IsWebApp(browser());
-  if (switches::IsImprovedSigninUIOnDesktopEnabled()) {
-    SetMenuTitleForAccessibility();
-    BuildIdentityWithCallToAction();
-  } else {
-    BuildIdentity();
-
-    // Users should not be able to open chrome settings from WebApps.
-    if (!is_web_app) {
-      BuildSyncInfo();
-      BuildAutofillButtons();
-    }
-  }
-
   if (is_web_app) {
     browser()->window()->NotifyFeaturePromoFeatureUsed(
         feature_engagement::kIPHPasswordsWebAppProfileSwitchFeature,
@@ -205,16 +184,13 @@
   }
 
   std::vector<ProfileAttributesEntry*> available_profiles;
-  bool show_guest_in_other_profiles_section = false;
-  GetProfilesForOtherProfilesSection(available_profiles,
-                                     show_guest_in_other_profiles_section);
+  GetProfilesForOtherProfilesSection(available_profiles);
 
-  if (!available_profiles.empty() || show_guest_in_other_profiles_section) {
+  if (!available_profiles.empty()) {
     SetProfileManagementHeading(
         l10n_util::GetStringUTF16(IDS_PROFILE_MENU_PROFILES_LIST_TITLE));
   }
-  BuildOtherProfilesSection(available_profiles,
-                            show_guest_in_other_profiles_section);
+  BuildOtherProfilesSection(available_profiles);
   base::UmaHistogramBoolean("ProfileChooser.HasProfilesShown",
                             !available_profiles.empty());
 
@@ -392,15 +368,11 @@
           browser(), syncer::TrustedVaultUserActionTriggerForUMA::kProfileMenu);
       break;
     case AvatarSyncErrorType::kPassphraseError:
-      if (base::FeatureList::IsEnabled(switches::kImprovedSigninUIOnDesktop)) {
-        ShowSyncPassphraseDialog(
-            *browser(), base::BindRepeating(
-                            &SyncPassphraseDialogDecryptData,
-                            base::Unretained(SyncServiceFactory::GetForProfile(
-                                browser()->profile()))));
-      } else {
-        chrome::ShowSettingsSubPage(browser(), chrome::kSyncSetupSubPage);
-      }
+      ShowSyncPassphraseDialog(
+          *browser(), base::BindRepeating(
+                          &SyncPassphraseDialogDecryptData,
+                          base::Unretained(SyncServiceFactory::GetForProfile(
+                              browser()->profile()))));
       break;
     case AvatarSyncErrorType::kSettingsUnconfirmedError:
       chrome::ShowSettingsSubPage(browser(), chrome::kSyncSetupSubPage);
@@ -537,7 +509,6 @@
 }
 
 void ProfileMenuView::SetMenuTitleForAccessibility() {
-  CHECK(switches::IsImprovedSigninUIOnDesktopEnabled());
   Profile* profile = browser()->profile();
   const signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
@@ -580,109 +551,6 @@
   }
 }
 
-void ProfileMenuView::BuildIdentity() {
-  // TODO(crbug.com/370473765): Delete this function after
-  // `switches::IsImprovedSigninUIOnDesktopEnabled()` is launched.
-  CHECK(!switches::IsImprovedSigninUIOnDesktopEnabled());
-
-  Profile* profile = browser()->profile();
-  signin::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile);
-  CoreAccountInfo account =
-      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
-  AccountInfo account_info = identity_manager->FindExtendedAccountInfo(account);
-  ProfileAttributesEntry* profile_attributes =
-      g_browser_process->profile_manager()
-          ->GetProfileAttributesStorage()
-          .GetProfileAttributesWithPath(profile->GetPath());
-  if (!profile_attributes) {
-    // May happen if the profile is being deleted. https://crbug.com/1040079
-    return;
-  }
-
-  std::u16string profile_name;
-  std::optional<EditButtonParams> edit_button_params;
-  profile_name = profile_attributes->GetLocalProfileName();
-
-  SkColor background_color =
-      profile_attributes->GetProfileThemeColors().profile_highlight_color;
-  if (!account_info.IsEmpty()) {
-    menu_title_ = base::UTF8ToUTF16(account_info.full_name);
-    menu_subtitle_ =
-        IsSyncPaused(profile)
-            ? l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE)
-            : base::UTF8ToUTF16(account_info.email);
-    auto account_manager = GetAccountManagerIdentity(profile);
-    std::u16string management_label;
-    ui::ImageModel badge_image_model;
-
-    if (enterprise_util::CanShowEnterpriseBadgingForMenu(
-            browser()->profile())) {
-      management_label =
-          account_manager
-              ? l10n_util::GetStringFUTF16(IDS_PROFILES_MANAGED_BY,
-                                           base::UTF8ToUTF16(*account_manager))
-              : std::u16string();
-      if (auto* icon = policy::ManagementServiceFactory::GetForProfile(profile)
-                           ->GetManagementIconForProfile()) {
-        badge_image_model = *icon;
-      } else {
-        gfx::ImageSkia sized_icon = gfx::CreateVectorIcon(gfx::IconDescription(
-            vector_icons::kBusinessIcon, kBusinessIconSize,
-            browser()->window()->GetColorProvider()->GetColor(
-                ui::kColorMenuIcon)));
-        badge_image_model =
-            ui::ImageModel::FromImageSkia(gfx::CanvasImageSource::CreatePadded(
-                sized_icon, gfx::Insets(kBusinessIconPadding)));
-      }
-    }
-
-    SetProfileIdentityInfo(
-        profile_name, background_color, edit_button_params,
-        ui::ImageModel::FromImage(
-            profile_attributes->GetProfileManagementOidcTokens()
-                    .id_token.empty()
-                ? account_info.account_image
-                : profile_attributes->GetAvatarIcon(kIdentityImageSize)),
-        badge_image_model, menu_title_, menu_subtitle_, management_label);
-  } else {
-    std::string profile_user_display_name, profile_user_email;
-#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
-    profile_user_display_name = profile->GetPrefs()->GetString(
-        enterprise_signin::prefs::kProfileUserDisplayName);
-    profile_user_email = profile->GetPrefs()->GetString(
-        enterprise_signin::prefs::kProfileUserEmail);
-#endif
-    menu_title_ =
-        profile_user_display_name.empty()
-            ? l10n_util::GetStringUTF16(IDS_PROFILES_LOCAL_PROFILE_STATE)
-            : base::UTF8ToUTF16(profile_user_display_name);
-    // The email may be empty.
-    menu_subtitle_ = base::UTF8ToUTF16(
-        profile_user_email.empty() ? account_info.email : profile_user_email);
-
-    std::u16string management_label;
-    SetProfileIdentityInfo(
-        profile_name, background_color, edit_button_params,
-        ui::ImageModel::FromImage(
-            // If the user is in the web-only signed-in state in the
-            // experimental version of the UNO model, use the account image in
-            // the profile menu header.
-            // If the account does not have an image or it's not available yet,
-            // a grey silhouette will be used.
-            // If UNO is disabled or enabled in the full version, or there is no
-            // account, use the profile icon.
-            !account_info.IsEmpty()
-                ? account_info.account_image
-                : profile_attributes->GetAvatarIcon(kIdentityImageSize)),
-        ui::ImageModel(), menu_title_, menu_subtitle_, management_label);
-  }
-
-  if (GetWidget()) {
-    GetWidget()->UpdateAccessibleNameForRootView();
-  }
-}
-
 void ProfileMenuView::BuildGuestIdentity() {
   menu_title_ = l10n_util::GetStringUTF16(IDS_GUEST_PROFILE_NAME);
   menu_subtitle_ = std::u16string();
@@ -714,149 +582,6 @@
   }
 }
 
-void ProfileMenuView::BuildAutofillButtons() {
-  // TODO(crbug.com/370473765): Delete this function after
-  // `switches::IsImprovedSigninUIOnDesktopEnabled()` is launched.
-  CHECK(!switches::IsImprovedSigninUIOnDesktopEnabled());
-
-  AddShortcutFeatureButton(
-      vector_icons::kPasswordManagerIcon,
-      l10n_util::GetStringUTF16(
-          IDS_PASSWORD_BUBBLES_PASSWORD_MANAGER_LINK_TEXT_SAVING_ON_DEVICE),
-      base::BindRepeating(&ProfileMenuView::OnPasswordsButtonClicked,
-                          base::Unretained(this)));
-
-  AddShortcutFeatureButton(
-      kCreditCardChromeRefreshIcon,
-      l10n_util::GetStringUTF16(IDS_PROFILES_CREDIT_CARDS_LINK),
-      base::BindRepeating(&ProfileMenuView::OnCreditCardsButtonClicked,
-                          base::Unretained(this)));
-
-  AddShortcutFeatureButton(
-      vector_icons::kLocationOnChromeRefreshIcon,
-      l10n_util::GetStringUTF16(IDS_PROFILES_ADDRESSES_LINK),
-      base::BindRepeating(&ProfileMenuView::OnAddressesButtonClicked,
-                          base::Unretained(this)));
-}
-
-void ProfileMenuView::BuildSyncInfo() {
-  // TODO(crbug.com/370473765): Delete this function after
-  // `switches::IsImprovedSigninUIOnDesktopEnabled()` is launched.
-  CHECK(!switches::IsImprovedSigninUIOnDesktopEnabled());
-
-  Profile* profile = browser()->profile();
-  if (!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)) {
-    return;
-  }
-
-  if (!SyncServiceFactory::IsSyncAllowed(profile)) {
-    return;
-  }
-
-  signin::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile);
-  bool is_sync_feature_enabled =
-      identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync);
-  // First, check for sync errors. They may exist even if sync-the-feature is
-  // disabled and only sync-the-transport is running.
-  const std::optional<AvatarSyncErrorType> error =
-      GetAvatarSyncErrorType(profile);
-  if (error) {
-    std::u16string error_description = GetAvatarSyncErrorDescription(
-        *error, is_sync_feature_enabled,
-        identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin)
-            .email);
-    BuildSyncInfoWithCallToAction(
-        std::move(error_description), GetSyncErrorButtonText(*error),
-        base::BindRepeating(&ProfileMenuView::OnSyncErrorButtonClicked,
-                            base::Unretained(this), *error),
-        /*show_sync_badge=*/is_sync_feature_enabled);
-    return;
-  }
-
-  // If there's no error and sync-the-feature is enabled, the text says
-  // everything is fine and the button simply opens sync settings.
-  if (is_sync_feature_enabled) {
-    BuildSyncInfoWithoutCallToAction(
-        l10n_util::GetStringUTF16(IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON),
-        base::BindRepeating(&ProfileMenuView::OnSyncSettingsButtonClicked,
-                            base::Unretained(this)));
-    return;
-  }
-
-  // If there's no error and sync-the-feature is disabled, show a sync promo.
-  // For a signed-in user, the promo just opens the "turn on sync" dialog.
-  // For a web-only signed-in user in the UNO model, the promo signs the user on
-  // Chrome and opens the "turn on sync" dialog.
-  // For a signed-out user, it prompts for sign-in first.
-  CoreAccountInfo account_info =
-      identity_manager->GetPrimaryAccountInfo(signin::ConsentLevel::kSignin);
-  AccountInfo account_info_for_promos =
-      signin_ui_util::GetSingleAccountForPromos(identity_manager);
-  std::u16string description;
-  std::u16string button_text;
-  ActionableItem button_type = ActionableItem::kSigninAccountButton;
-  bool show_account_card = false;
-  signin_metrics::AccessPoint access_point =
-      signin_metrics::AccessPoint::kAvatarBubbleSignIn;
-
-  signin_metrics::PromoAction promo_action =
-      signin_metrics::PromoAction::PROMO_ACTION_NO_SIGNIN_PROMO;
-
-  if (!account_info.IsEmpty()) {
-    if (identity_manager->HasAccountWithRefreshTokenInPersistentErrorState(
-            account_info.account_id)) {
-      // Sign-in pending state.
-      button_type = ActionableItem::kSigninReauthButton;
-      description =
-          l10n_util::GetStringUTF16(IDS_SIGNIN_PAUSED_USER_MENU_VERIFY_MESSAGE);
-      button_text =
-          l10n_util::GetStringUTF16(IDS_PROFILES_VERIFY_ACCOUNT_BUTTON);
-    } else {
-      // Signed-in not-syncing state.
-      description = l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SYNC_PROMO);
-      button_text = l10n_util::GetStringUTF16(IDS_PROFILES_DICE_SIGNIN_BUTTON);
-    }
-  } else if (!account_info_for_promos.IsEmpty()) {
-    // Web-only signed-in state.
-    account_info = account_info_for_promos;
-    access_point =
-        signin_metrics::AccessPoint::kAvatarBubbleSignInWithSyncPromo;
-    description =
-        l10n_util::GetStringUTF16(IDS_PROFILE_MENU_SIGNIN_PROMO_DESCRIPTION);
-    button_text = l10n_util::GetStringFUTF16(
-        IDS_PROFILES_DICE_WEB_ONLY_SIGNIN_BUTTON,
-        base::UTF8ToUTF16(!account_info_for_promos.given_name.empty()
-                              ? account_info_for_promos.given_name
-                              : account_info_for_promos.email));
-    button_type = ActionableItem::kEnableSyncForWebOnlyAccountButton;
-    show_account_card = true;
-    promo_action = signin_metrics::PromoAction::PROMO_ACTION_WITH_DEFAULT;
-  } else {
-    // Not signed in state.
-    access_point =
-        signin_metrics::AccessPoint::kAvatarBubbleSignInWithSyncPromo;
-    description =
-        l10n_util::GetStringUTF16(IDS_PROFILE_MENU_SIGNIN_PROMO_DESCRIPTION);
-    button_text =
-        l10n_util::GetStringUTF16(IDS_PROFILE_MENU_SIGNIN_PROMO_BUTTON);
-    button_type = ActionableItem::kSigninButton;
-    promo_action = signin_metrics::PromoAction::
-        PROMO_ACTION_NEW_ACCOUNT_NO_EXISTING_ACCOUNT;
-  }
-  signin_metrics::LogSignInOffered(access_point, promo_action);
-
-  CHECK(!description.empty());
-  CHECK(!button_text.empty());
-  BuildSyncInfoWithCallToAction(
-      description, button_text,
-      base::BindRepeating(&ProfileMenuView::OnSigninButtonClicked,
-                          base::Unretained(this), account_info, button_type,
-                          access_point),
-      /*show_sync_badge=*/false,
-      show_account_card ? account_info_for_promos : AccountInfo());
-}
-
 ProfileMenuViewBase::IdentitySectionParams
 ProfileMenuView::GetIdentitySectionParams(const ProfileAttributesEntry& entry) {
   CHECK(switches::IsImprovedSigninUIOnDesktopEnabled());
@@ -1061,33 +786,23 @@
     return;
   }
 
-  // Show the settings button when signed in to Chrome or to the web.
-  bool should_show_settings_button =
+  // Show the settings button when signed in to Chrome or to the web, or if
+  // signin is disallowed.
+  const bool should_show_settings_button =
       !identity_manager->GetExtendedAccountInfoForAccountsWithRefreshToken()
-           .empty();
+           .empty() ||
+      !profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed);
+  if (!should_show_settings_button) {
+    return;
+  }
 
   int message_id = IDS_PROFILE_MENU_OPEN_ACCOUNT_SETTINGS;
   const gfx::VectorIcon* icon = &vector_icons::kSettingsChromeRefreshIcon;
-  if (switches::IsImprovedSigninUIOnDesktopEnabled()) {
-    if (!profile->GetPrefs()->GetBoolean(prefs::kSigninAllowed)) {
-      should_show_settings_button = true;
-    }
-    if (signin_util::GetSignedInState(identity_manager) ==
-        signin_util::SignedInState::kSyncing) {
-      // Indicates clearly that Sync is ON.
-      message_id = IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON;
-      icon = &kSyncChromeRefreshIcon;
-    }
-  } else {
-    if (identity_manager->HasPrimaryAccount(signin::ConsentLevel::kSync)) {
-      // Do not show if sync is enabled with the legacy design, because there is
-      // already a similar button in the sync info card.
-      should_show_settings_button = false;
-    }
-  }
-
-  if (!should_show_settings_button) {
-    return;
+  if (signin_util::GetSignedInState(identity_manager) ==
+      signin_util::SignedInState::kSyncing) {
+    // Indicates clearly that Sync is ON.
+    message_id = IDS_PROFILES_OPEN_SYNC_SETTINGS_BUTTON;
+    icon = &kSyncChromeRefreshIcon;
   }
 
   AddFeatureButton(
@@ -1110,10 +825,6 @@
   bool show_button = true;
   switch (signin_util::GetSignedInState(identity_manager)) {
     case signin_util::SignedInState::kSignInPending:
-      if (switches::IsImprovedSigninUIOnDesktopEnabled()) {
-        show_button = false;
-      }
-      break;
     case signin_util::SignedInState::kSyncPaused:
     case signin_util::SignedInState::kSignedOut:
     case signin_util::SignedInState::kWebOnlySignedIn:
@@ -1157,7 +868,7 @@
         base::FeatureList::IsEnabled(switches::kEnableImprovedGuestProfileMenu)
             ? IDS_GUEST_PROFILE_MENU_CLOSE_X_WINDOWS_BUTTON
             : IDS_GUEST_PROFILE_MENU_CLOSE_BUTTON;
-  } else if (switches::IsImprovedSigninUIOnDesktopEnabled()) {
+  } else {
     // Show the button only if the current profile has multiple windows open.
     if (window_count <= 1) {
       return;
@@ -1217,33 +928,21 @@
   AddFeatureButton(signout_button_text,
                    base::BindRepeating(&ProfileMenuView::OnSignoutButtonClicked,
                                        base::Unretained(this)),
-                   switches::IsImprovedSigninUIOnDesktopEnabled()
-                       ? kLogoutIcon
-                       : kSignOutIcon);
+                   kLogoutIcon);
 }
 
 void ProfileMenuView::BuildFeatureButtons() {
   CHECK(!browser()->profile()->IsGuestSession());
-  if (switches::IsImprovedSigninUIOnDesktopEnabled()) {
-    BuildAutofillSettingsButton();
-    MaybeBuildManageGoogleAccountButton();
-    BuildCustomizeProfileButton();
-    MaybeBuildChromeAccountSettingsButton();
-    MaybeBuildCloseBrowsersButton();
-    MaybeBuildSignoutButton();
-    return;
-  }
-
+  BuildAutofillSettingsButton();
+  MaybeBuildManageGoogleAccountButton();
   BuildCustomizeProfileButton();
   MaybeBuildChromeAccountSettingsButton();
-  MaybeBuildManageGoogleAccountButton();
   MaybeBuildCloseBrowsersButton();
   MaybeBuildSignoutButton();
 }
 
 void ProfileMenuView::GetProfilesForOtherProfilesSection(
-    std::vector<ProfileAttributesEntry*>& available_profiles,
-    bool& show_guest_in_other_profiles_section) const {
+    std::vector<ProfileAttributesEntry*>& available_profiles) const {
   CHECK(!browser()->profile()->IsGuestSession());
 #if BUILDFLAG(IS_MAC)
   const bool is_regular_web_app =
@@ -1278,22 +977,14 @@
 
     available_profiles.push_back(profile_entry);
   }
-
-  show_guest_in_other_profiles_section =
-      profiles::IsGuestModeEnabled(*browser()->profile()) &&
-      !web_app::AppBrowserController::IsWebApp(browser()) &&
-      !switches::IsImprovedSigninUIOnDesktopEnabled();
 }
 
 void ProfileMenuView::BuildOtherProfilesSection(
-    const std::vector<ProfileAttributesEntry*>& available_profiles,
-    bool show_guest_in_other_profiles_section) {
+    const std::vector<ProfileAttributesEntry*>& available_profiles) {
   for (ProfileAttributesEntry* profile_entry : available_profiles) {
     AddAvailableProfile(
         ui::ImageModel::FromImage(profile_entry->GetAvatarIcon(
-            switches::IsImprovedSigninUIOnDesktopEnabled()
-                ? kOtherProfileImageSize
-                : kDeprecatedOtherProfileImageSize,
+            kOtherProfileImageSize,
             /*use_high_res_file=*/true,
             GetPlaceholderAvatarIconParamsVisibleAgainstColor(
                 browser()->window()->GetColorProvider()->GetColor(
@@ -1303,15 +994,6 @@
         base::BindRepeating(&ProfileMenuView::OnOtherProfileSelected,
                             base::Unretained(this), profile_entry->GetPath()));
   }
-
-  if (show_guest_in_other_profiles_section) {
-    AddAvailableProfile(
-        profiles::GetGuestAvatar(),
-        l10n_util::GetStringUTF16(IDS_PROFILE_MENU_OPEN_GUEST_PROFILE),
-        /*is_guest=*/true,
-        base::BindRepeating(&ProfileMenuView::OnGuestProfileButtonClicked,
-                            base::Unretained(this)));
-  }
 }
 
 void ProfileMenuView::BuildProfileManagementFeatureButtons() {
@@ -1322,15 +1004,12 @@
   if (profiles::IsProfileCreationAllowed()) {
     AddProfileManagementFeatureButton(
         kAccountAddChromeRefreshIcon,
-        l10n_util::GetStringUTF16(switches::IsImprovedSigninUIOnDesktopEnabled()
-                                      ? IDS_PROFILE_MENU_ADD_PROFILE
-                                      : IDS_PROFILE_MENU_ADD_NEW_PROFILE),
+        l10n_util::GetStringUTF16(IDS_PROFILE_MENU_ADD_PROFILE),
         base::BindRepeating(&ProfileMenuView::OnAddNewProfileButtonClicked,
                             base::Unretained(this)));
   }
 
-  if (switches::IsImprovedSigninUIOnDesktopEnabled() &&
-      profiles::IsGuestModeEnabled(*browser()->profile()) &&
+  if (profiles::IsGuestModeEnabled(*browser()->profile()) &&
       !web_app::AppBrowserController::IsWebApp(browser())) {
     AddProfileManagementFeatureButton(
         kAccountBoxIcon,
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view.h b/chrome/browser/ui/views/profiles/profile_menu_view.h
index ffc3c30..cb8e6f0 100644
--- a/chrome/browser/ui/views/profiles/profile_menu_view.h
+++ b/chrome/browser/ui/views/profiles/profile_menu_view.h
@@ -100,23 +100,12 @@
       const ProfileAttributesEntry& entry);
   void BuildIdentityWithCallToAction();
 
-  // TODO(crbug.com/370473765): Delete these functions after
-  // `switches::IsImprovedSigninUIOnDesktopEnabled()` is launched.
-  void BuildIdentity();
-  void BuildAutofillButtons();
-  void BuildSyncInfo();
-
   // Gets the profiles to be displayed in the "Other profiles" section. Does not
   // include the current profile.
-  // When `switches::IsImprovedSigninUIOnDesktopEnabled()` returns true, the
-  // guest profile is never shown in this section. It is shown in the profile
-  // management section instead.
   void GetProfilesForOtherProfilesSection(
-      std::vector<ProfileAttributesEntry*>& available_profiles,
-      bool& show_guest_in_other_profiles_section) const;
+      std::vector<ProfileAttributesEntry*>& available_profiles) const;
   void BuildOtherProfilesSection(
-      const std::vector<ProfileAttributesEntry*>& available_profiles,
-      bool show_guest_in_other_profiles_section);
+      const std::vector<ProfileAttributesEntry*>& available_profiles);
 
   void BuildProfileManagementFeatureButtons();
 
diff --git a/chrome/browser/ui/webui/ash/DEPS b/chrome/browser/ui/webui/ash/DEPS
index 8170a81..df0d158 100644
--- a/chrome/browser/ui/webui/ash/DEPS
+++ b/chrome/browser/ui/webui/ash/DEPS
@@ -9,4 +9,9 @@
   # ChromeOS should not depend on //chrome. See //docs/chromeos/code.md for
   # details.
   "-chrome",
+
+  # Browser abstraction for use by ChromeOS feature code. Will eventually be
+  # moved out of chrome/.
+  "+chrome/browser/ash/browser_delegate/browser_controller.h",
+  "+chrome/browser/ash/browser_delegate/browser_delegate.h",
 ]
diff --git a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc
index 39e6204..b8c4767 100644
--- a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc
+++ b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.cc
@@ -11,6 +11,7 @@
 #include "base/functional/bind.h"
 #include "base/memory/ref_counted.h"
 #include "base/values.h"
+#include "chrome/browser/prefs/incognito_mode_prefs.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/profiles/profile_key.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
@@ -33,7 +34,6 @@
 #include "content/public/browser/web_ui.h"
 #include "google_apis/gaia/gaia_id.h"
 
-
 namespace {
 
 using content::BrowserThread;
@@ -182,6 +182,11 @@
       base::BindRepeating(&FamilyLinkUserInternalsMessageHandler::
                               HandleChangeSearchContentFilters,
                           base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
+      "changeBrowserContentFilters",
+      base::BindRepeating(&FamilyLinkUserInternalsMessageHandler::
+                              HandleChangeBrowserContentFilters,
+                          base::Unretained(this)));
 }
 
 void FamilyLinkUserInternalsMessageHandler::OnJavascriptDisallowed() {
@@ -291,19 +296,29 @@
 
 void FamilyLinkUserInternalsMessageHandler::ConfigureSearchContentFilters() {
   Profile* profile = Profile::FromWebUI(web_ui());
-  supervised_user::GoogleSafeSearchStateStatus status;
   switch (search_content_filtering_status_) {
     case WebContentFilters::kDisabled:
-      status = supervised_user::GoogleSafeSearchStateStatus::kDisabled;
+      supervised_user::DisableSearchContentFilters(*profile->GetPrefs());
       break;
     case WebContentFilters::kEnabled:
-      status = supervised_user::GoogleSafeSearchStateStatus::kEnforced;
+      supervised_user::EnableSearchContentFilters(*profile->GetPrefs());
       break;
     default:
       NOTREACHED();
   }
-
-  supervised_user::SetGoogleSafeSearch(*profile->GetPrefs(), status);
+}
+void FamilyLinkUserInternalsMessageHandler::ConfigureBrowserContentFilters() {
+  Profile* profile = Profile::FromWebUI(web_ui());
+  switch (browser_content_filtering_status_) {
+    case WebContentFilters::kDisabled:
+      supervised_user::DisableBrowserContentFilters(*profile->GetPrefs());
+      break;
+    case WebContentFilters::kEnabled:
+      supervised_user::EnableBrowserContentFilters(*profile->GetPrefs());
+      break;
+    default:
+      NOTREACHED();
+  }
 }
 
 void FamilyLinkUserInternalsMessageHandler::HandleChangeSearchContentFilters(
@@ -325,6 +340,25 @@
   ConfigureSearchContentFilters();
 }
 
+void FamilyLinkUserInternalsMessageHandler::HandleChangeBrowserContentFilters(
+    const base::Value::List& args) {
+  Profile* profile = Profile::FromWebUI(web_ui());
+  if (IsSubjectToFamilyLinkParentalControls(
+          IdentityManagerFactory::GetForProfile(profile))) {
+    // Feature not available for the Family Link supervised users.
+    return;
+  }
+
+  DCHECK_EQ(1u, args.size());
+  if (!args[0].is_string()) {
+    return;
+  }
+
+  browser_content_filtering_status_ =
+      ToggleToWebContentFilters(args[0].GetString());
+  ConfigureBrowserContentFilters();
+}
+
 void FamilyLinkUserInternalsMessageHandler::SendBasicInfo() {
   base::Value::List section_list;
   Profile* profile = Profile::FromWebUI(web_ui());
@@ -348,6 +382,11 @@
       section_search, "Safe search enforced",
       supervised_user::IsGoogleSafeSearchEnforced(*profile->GetPrefs()));
 
+  base::Value::List* section_browser =
+      AddSection(&section_list, "Browser and web");
+  AddSectionEntry(section_browser, "Incognito mode allowed",
+                  IncognitoModePrefs::IsIncognitoAllowed(profile));
+
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
   // |identity_manager| is null in incognito and guest profiles.
@@ -403,6 +442,8 @@
                           IdentityManagerFactory::GetForProfile(profile)));
   info.Set("search_content_filtering",
            WebContentFiltersToToggle(search_content_filtering_status_));
+  info.Set("browser_content_filtering",
+           WebContentFiltersToToggle(browser_content_filtering_status_));
   FireWebUIListener("web-content-filters-info-received", info);
 }
 
diff --git a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h
index af7a160..d4742ba 100644
--- a/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h
+++ b/chrome/browser/ui/webui/family_link_user_internals/family_link_user_internals_message_handler.h
@@ -70,10 +70,12 @@
   void HandleGetBasicInfo(const base::Value::List& args);
   void HandleTryURL(const base::Value::List& args);
   void HandleChangeSearchContentFilters(const base::Value::List& args);
+  void HandleChangeBrowserContentFilters(const base::Value::List& args);
 
-  // Sets the browser's state of search content filtering as indicated in this
-  // UI.
+  // Sets the browser's state of search and browser content filtering as
+  // indicated in this UI.
   void ConfigureSearchContentFilters();
+  void ConfigureBrowserContentFilters();
 
   void SendBasicInfo();
   void SendFamilyLinkUserSettings(const base::Value::Dict& settings);
@@ -86,12 +88,14 @@
   void OnURLChecked(supervised_user::SupervisedUserURLFilter::Result
                         filtering_result) override;
 
-  // Emulates device-level setting that manipulates search content filtering.
-  // Available only to non-supervised profiles. Note: if multiple chrome://
-  // pages are open simultaneously, they might override each other. This is
-  // safe, but will render web-ui off-sync.
+  // Emulates device-level setting that manipulates search or browser content
+  // filtering. Available only to non-supervised profiles. Note: if multiple
+  // chrome:// pages are open simultaneously, they might override each other.
+  // This is safe, but will render web-ui off-sync.
   WebContentFilters search_content_filtering_status_{
       WebContentFilters::kDisabled};
+  WebContentFilters browser_content_filtering_status_{
+      WebContentFilters::kDisabled};
 
   base::CallbackListSubscription user_settings_subscription_;
 
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index c40a0ca..2bc7bbdb 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1744070359-d61eb98387bb823904715ba9d499cb07dafad4c1-b20a7e9f55ac394455e41a818f9912c54fe4ae63.profdata
+chrome-android32-main-1744091764-72a66516b480086e36c3f791977b5737b6cfa377-a7ca0a342c874b15f0ce95c60fa0a3eaead4875c.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 3058bcf..65ad5d5 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1744063392-751694ce8f2e794563e119030df1ac7dc5dc0ab3-a8784ddce1e0407aacaf37cad4c204243a9b85b2.profdata
+chrome-android64-main-1744106729-65fb503cce96570249768d86eceeb1ef83d0f64a-630e2149d6b27bc505cf121b165caba1e88b4d64.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index c4481f0..5c366ac4 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1744048751-a2f2a3f5d6f3867ca7c38f1474a0f80fd330650f-4c01c407f87e60a9c0d41f6372df70364a780128.profdata
+chrome-linux-main-1744091764-530b3e4ecaff56ec6540b3dbab21e00b9ed04060-a7ca0a342c874b15f0ce95c60fa0a3eaead4875c.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 4f97b1dc..fadd09e1 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1744070359-85b0de046d5a337edc3691044abdabec8e229e44-b20a7e9f55ac394455e41a818f9912c54fe4ae63.profdata
+chrome-mac-arm-main-1744105985-249e79c35d8cbe19f59b1ac87554173c059fa07e-f93d3b774afe7bba982e93e028c5a589082fc097.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index c500f75..be8df32 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1744048751-effec5453030ec23c37b47cefcea87f61155b712-4c01c407f87e60a9c0d41f6372df70364a780128.profdata
+chrome-mac-main-1744091764-1026ef69eb485b37f1efd4e528b0a6d179d42406-a7ca0a342c874b15f0ce95c60fa0a3eaead4875c.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index dfe43265..7352647 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1744070359-01f1d962b8f10272345aa899f907f19d0cad815e-b20a7e9f55ac394455e41a818f9912c54fe4ae63.profdata
+chrome-win-arm64-main-1744091764-87eeb612dccf78a71ddb38fc0f0a261f91b8ab1a-a7ca0a342c874b15f0ce95c60fa0a3eaead4875c.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 049b051..5715e9fe 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1744037890-0b88e3f4059a0f88ac12b512b3651e48aa3041d4-2f82cfff06d4e917915d3840a892876b2ed1d161.profdata
+chrome-win32-main-1744081126-489c02d216a9196d520b330eed6f0116dab88977-6a164fbd10b1dce352c3c49995ce3e90a4878e73.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 9d4aa17..fcc17cf7 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1744037890-836cb9f51431689a0e2a741f2d96dbb4e9c0319f-2f82cfff06d4e917915d3840a892876b2ed1d161.profdata
+chrome-win64-main-1744081126-b529895978742e1686254afa7883b95034eb2640-6a164fbd10b1dce352c3c49995ce3e90a4878e73.profdata
diff --git a/chrome/release_scripts b/chrome/release_scripts
index a8b04e9..96fcca5e 160000
--- a/chrome/release_scripts
+++ b/chrome/release_scripts
@@ -1 +1 @@
-Subproject commit a8b04e95dc407615a7d2bdc70903376809093548
+Subproject commit 96fcca5edf9bb94f04fb2fc487aaf332ae1eff0d
diff --git a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
index 11aee947..49d0e1f 100644
--- a/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
+++ b/chrome/renderer/autofill/password_autofill_agent_browsertest.cc
@@ -1094,15 +1094,11 @@
   // The username and password should have been autocompleted.
   CheckTextFieldsDOMState(kAliceUsername, true, kAlicePassword, true);
 
-  histogram_tester_.ExpectUniqueSample(
-      "PasswordManager.PrefilledUsernameFillOutcome",
-      PrefilledUsernameFillOutcome::kPrefilledPlaceholderUsernameOverridden, 1);
-
   CheckFirstFillingResult(FillingResult::kSuccess);
 }
 
 // Tests that if filling is invoked twice for the same autofill agent the
-// prefilled username and first filling metrics are only logged once.
+// first filling metrics are only logged once.
 TEST_F(PasswordAutofillAgentTest, MetricsOnlyLoggedOnce) {
   // Set the username element to a value from the prefilled values list.
   // Comparison should be insensitive to leading and trailing whitespaces.
@@ -1113,10 +1109,6 @@
   SimulateOnFillPasswordForm(fill_data_);
   SimulateOnFillPasswordForm(fill_data_);
 
-  histogram_tester_.ExpectUniqueSample(
-      "PasswordManager.PrefilledUsernameFillOutcome",
-      PrefilledUsernameFillOutcome::kPrefilledPlaceholderUsernameOverridden, 1);
-
   CheckFirstFillingResult(FillingResult::kSuccess);
 }
 
@@ -1233,11 +1225,6 @@
   CheckTextFieldsSuggestedState("", false, std::string(), false);
   CheckUsernameDOMStatePasswordSuggestedState("ali", false, std::string(),
                                               false);
-
-  histogram_tester_.ExpectUniqueSample(
-      "PasswordManager.PrefilledUsernameFillOutcome",
-      autofill::PrefilledUsernameFillOutcome::kPrefilledUsernameNotOverridden,
-      1);
 }
 
 // Tests that having a matching username precludes the autofill.
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6cca268..1d582fd 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -10331,6 +10331,7 @@
 
     deps += [
       "//ash:test_support",
+      "//chrome/browser:global_features",
       "//chrome/browser/ash/login/users:test_support",
       "//chrome/browser/ui/ash/quick_answers",
       "//chrome/browser/ui/ash/read_write_cards",
diff --git a/chrome/test/data/prerender/prerender_with_tags.html b/chrome/test/data/prerender/prerender_with_tags.html
new file mode 100644
index 0000000..fd6a73d
--- /dev/null
+++ b/chrome/test/data/prerender/prerender_with_tags.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <script type="speculationrules">
+    {
+      "prerender": [{
+        "source": "list",
+        "urls": ["empty.html"],
+        "tag": "tag1"
+      }]
+    }
+  </script>
+<title>Prerender Test</title>
+</head>
+</html>
\ No newline at end of file
diff --git a/chrome/test/data/webui/glic/api_test.ts b/chrome/test/data/webui/glic/api_test.ts
index facb5f0..c8125d2 100644
--- a/chrome/test/data/webui/glic/api_test.ts
+++ b/chrome/test/data/webui/glic/api_test.ts
@@ -171,6 +171,31 @@
     assertEquals(data.url, url);
   }
 
+  async testCreateTabFailsWithUnsupportedScheme() {
+    assertTrue(!!this.host.createTab);
+
+    this.assertCreateTabWithUnsupportedSchemeFails('chrome://settings');
+    this.assertCreateTabWithUnsupportedSchemeFails('ftps://www.google.com');
+    this.assertCreateTabWithUnsupportedSchemeFails(
+        'chrome-extension://www.google.com');
+    this.assertCreateTabWithUnsupportedSchemeFails('mailto:user@google.com');
+    this.assertCreateTabWithUnsupportedSchemeFails(
+        'data:text/html;charset=utf-8,<html>Hello World</html>');
+    this.assertCreateTabWithUnsupportedSchemeFails('file:///tmp/test.html');
+  }
+
+  async testCreateTabInBackground() {
+    assertTrue(!!this.host.createTab);
+
+    await this.host.createTab(
+        location.href + '#foreground', {openInBackground: false});
+
+    await this.advanceToNextStep();
+
+    await this.host.createTab(
+        location.href + '#background', {openInBackground: true});
+  }
+
   async testOpenGlicSettingsPage() {
     assertTrue(!!this.host.openGlicSettingsPage);
     this.host.openGlicSettingsPage();
@@ -550,6 +575,15 @@
     await observeSequence(this.host.getPanelState())
         .waitFor(s => s.kind === kind);
   }
+
+  private async assertCreateTabWithUnsupportedSchemeFails(url: string) {
+    assertTrue(!!this.host.createTab);
+    try {
+      await this.host.createTab(url, {openInBackground: false});
+    } catch (e) {
+      assertEquals('createTab: failed', (e as Error).message);
+    }
+  }
 }
 
 // Tests which do not wait for the panel to open before starting.
diff --git a/chromeos/CHROMEOS_LKGM b/chromeos/CHROMEOS_LKGM
index 31cfd97..9034ff4 100644
--- a/chromeos/CHROMEOS_LKGM
+++ b/chromeos/CHROMEOS_LKGM
@@ -1 +1 @@
-16241.0.0-1067920
\ No newline at end of file
+16246.0.0-1068048
\ No newline at end of file
diff --git a/chromeos/ash/components/boca/boca_session_manager.cc b/chromeos/ash/components/boca/boca_session_manager.cc
index a026e42..ac00f204 100644
--- a/chromeos/ash/components/boca/boca_session_manager.cc
+++ b/chromeos/ash/components/boca/boca_session_manager.cc
@@ -34,6 +34,17 @@
 
 namespace ash::boca {
 
+namespace {
+const net::BackoffEntry::Policy kStudentHeartbeatBackoffPolicy = {
+    .num_errors_to_ignore = 0,
+    .initial_delay_ms = base::Seconds(30).InMilliseconds(),
+    .multiply_factor = 1.2,
+    .jitter_factor = 0.2,
+    .maximum_backoff_ms = base::Seconds(90).InMilliseconds(),
+    .entry_lifetime_ms = -1,
+    .always_use_initial_delay = false};
+}  // namespace
+
 BocaSessionManager::BocaSessionManager(SessionClientImpl* session_client_impl,
                                        const PrefService* pref_service,
                                        AccountId account_id,
@@ -41,7 +52,8 @@
     : is_producer_(is_producer),
       account_id_(std::move(account_id)),
       pref_service_(pref_service),
-      session_client_impl_(std::move(session_client_impl)) {
+      session_client_impl_(std::move(session_client_impl)),
+      student_heartbeat_retry_backoff_{&kStudentHeartbeatBackoffPolicy} {
   in_session_polling_interval_ =
       features::IsBocaCustomPollingEnabled()
           ? ash::features::kBocaInSessionPeriodicJobIntervalInSeconds.Get()
@@ -457,7 +469,7 @@
   }
 
   if (IsSessionActive(current_session_.get())) {
-    StartSendingStudentHeartbeatRequests();
+    StartSendingStudentHeartbeatRequests(student_heartbeat_interval_);
   } else {
     StopSendingStudentHeartbeatRequests();
   }
@@ -640,22 +652,19 @@
           .captions_enabled());
 }
 
-void BocaSessionManager::StartSendingStudentHeartbeatRequests() {
+void BocaSessionManager::StartSendingStudentHeartbeatRequests(
+    base::TimeDelta student_heartbeat_interval) {
   if (!features::IsBocaStudentHeartbeatEnabled() || is_producer_ ||
-      student_heartbeat_interval_ == base::Seconds(0)) {
+      student_heartbeat_interval == base::Seconds(0)) {
     return;
   }
-  if (!student_heartbeat_timer_.IsRunning()) {
-    student_heartbeat_timer_.Start(
-        FROM_HERE, student_heartbeat_interval_, this,
-        &BocaSessionManager::SendStudentHeartbeatRequest);
-  }
+  student_heartbeat_timer_.Start(
+      FROM_HERE, student_heartbeat_interval, this,
+      &BocaSessionManager::SendStudentHeartbeatRequest);
 }
 
 void BocaSessionManager::StopSendingStudentHeartbeatRequests() {
-  if (student_heartbeat_timer_.IsRunning()) {
-    student_heartbeat_timer_.Stop();
-  }
+  student_heartbeat_timer_.Stop();
 }
 
 void BocaSessionManager::SendStudentHeartbeatRequest() {
@@ -668,16 +677,30 @@
       session_client_impl_->sender(),
       BocaAppClient::Get()->GetSchoolToolsServerBaseUrl(), session_id, gaia_id,
       device_id, student_group_id,
-      base::BindOnce(
-          [](base::expected<bool, google_apis::ApiErrorCode> result) {
-            if (!result.has_value()) {
-              // TODO: crbug.com/366316261 - Add metrics for update failure.
-              DVLOG(1) << "[Boca]Failed to call student heartbeat.";
-            }
-          }));
+      base::BindOnce(&BocaSessionManager::OnStudentHeartbeat,
+                     weak_factory_.GetWeakPtr()));
   session_client_impl_->StudentHeartbeat(std::move(request));
 }
 
+void BocaSessionManager::OnStudentHeartbeat(
+    base::expected<bool, google_apis::ApiErrorCode> result) {
+  if (!result.has_value()) {
+    // TODO: crbug.com/366316261 - Add metrics for update failure.
+    LOG(WARNING) << "[Boca]Failed to call student heartbeat with error code: ."
+                 << result.error();
+    if ((result.error() >= 500 && result.error() < 600) ||
+        result.error() == 429) {
+      student_heartbeat_retry_backoff_.InformOfRequest(/*succeeded=*/false);
+      // Reset the timer to use the new backoff interval.
+      StartSendingStudentHeartbeatRequests(
+          student_heartbeat_retry_backoff_.GetTimeUntilRelease());
+    }
+    return;
+  }
+  student_heartbeat_retry_backoff_.Reset();
+  StartSendingStudentHeartbeatRequests(student_heartbeat_interval_);
+}
+
 void BocaSessionManager::UpdateNetworkRestriction(
     chromeos::network_config::mojom::NetworkStatePropertiesPtr network_state) {
   bool should_disable_on_non_managed_network =
diff --git a/chromeos/ash/components/boca/boca_session_manager.h b/chromeos/ash/components/boca/boca_session_manager.h
index 3c2de618..e6e2db33 100644
--- a/chromeos/ash/components/boca/boca_session_manager.h
+++ b/chromeos/ash/components/boca/boca_session_manager.h
@@ -26,6 +26,7 @@
 #include "google_apis/common/api_error_codes.h"
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "net/base/backoff_entry.h"
 
 namespace boca {
 class UserIdentity;
@@ -51,7 +52,7 @@
   inline static constexpr char kHomePageTitle[] = "School Tools Home page";
   inline static constexpr int kDefaultPollingIntervalInSeconds = 60;
   inline static constexpr int kLocalSessionTrackerBufferInSeconds = 60;
-  inline static constexpr int kDefaultStudentHeartbeatIntervalInSeconds = 60;
+  inline static constexpr int kDefaultStudentHeartbeatIntervalInSeconds = 30;
   inline static constexpr int kSkipPollingBufferInSeconds = 2;
   inline static constexpr char kPollingResultHistName[] =
       "Ash.Boca.PollingResult";
@@ -170,6 +171,8 @@
   void ParseSessionResponse(bool from_polling,
                             base::expected<std::unique_ptr<::boca::Session>,
                                            google_apis::ApiErrorCode> result);
+  void OnStudentHeartbeat(
+      base::expected<bool, google_apis::ApiErrorCode> result);
 
   virtual void UpdateCurrentSession(std::unique_ptr<::boca::Session> session,
                                     bool dispatch_event);
@@ -236,7 +239,8 @@
                            std::unique_ptr<::boca::Session> current_session,
                            bool dispatch_event);
   void UpdateLocalSessionDurationTracker();
-  void StartSendingStudentHeartbeatRequests();
+  void StartSendingStudentHeartbeatRequests(
+      base::TimeDelta student_heartbeat_interval);
   void StopSendingStudentHeartbeatRequests();
   void SendStudentHeartbeatRequest();
   void HandleCaptionNotification();
@@ -285,6 +289,7 @@
   raw_ptr<signin::IdentityManager> identity_manager_;
   bool is_local_caption_enabled_ = false;
   SessionCaptionInitializer session_caption_initializer_;
+  net::BackoffEntry student_heartbeat_retry_backoff_;
   base::OnceCallback<void(bool)> on_app_status_toggled_cb_for_test_;
   base::WeakPtrFactory<BocaSessionManager> weak_factory_{this};
 };
diff --git a/chromeos/ash/components/boca/boca_session_manager_unittest.cc b/chromeos/ash/components/boca/boca_session_manager_unittest.cc
index 0456406..36b8dbc 100644
--- a/chromeos/ash/components/boca/boca_session_manager_unittest.cc
+++ b/chromeos/ash/components/boca/boca_session_manager_unittest.cc
@@ -204,7 +204,7 @@
 
   const base::TimeDelta kDefaultInSessionPollingInterval = base::Seconds(60);
   const base::TimeDelta kDefaultIndefinitePollingInterval = base::Seconds(60);
-  const base::TimeDelta kDefaultStudentHeartbeatInterval = base::Seconds(60);
+  const base::TimeDelta kDefaultStudentHeartbeatInterval = base::Seconds(30);
 
  protected:
   void ToggleOnline() {
@@ -1456,7 +1456,7 @@
   boca_session_manager()->UpdateCurrentSession(
       std::make_unique<::boca::Session>(session), false);
 
-  task_environment()->FastForwardBy(kDefaultStudentHeartbeatInterval);
+  task_environment()->FastForwardBy(kDefaultInSessionPollingInterval);
 }
 
 TEST_F(BocaSessionManagerTest, InitializerSetSuccess) {
@@ -1760,6 +1760,32 @@
                                     base::Seconds(1));
 }
 
+TEST_F(BocaSessionManagerStudentHeartbeatTest,
+       StudentHeartbeatCalledWithRetryBackoff) {
+  ::boca::Session session_1;
+  session_1.set_session_id(kInitialSessionId);
+  session_1.set_session_state(::boca::Session::ACTIVE);
+  session_1.mutable_duration()->set_seconds(kInitialSessionDurationInSecs);
+  session_1.mutable_start_time()->set_seconds(
+      base::Time::Now().InMillisecondsSinceUnixEpoch() / 1000);
+
+  EXPECT_CALL(*session_client_impl(), StudentHeartbeat(_))
+      .Times(3)
+      .WillRepeatedly(testing::InvokeWithoutArgs([&]() {
+        boca_session_manager()->OnStudentHeartbeat(
+            base::unexpected<google_apis::ApiErrorCode>(
+                google_apis::ApiErrorCode::HTTP_INTERNAL_SERVER_ERROR));
+      }));
+
+  boca_session_manager()->UpdateCurrentSession(
+      std::make_unique<::boca::Session>(session_1), /*dispatch_event=*/true);
+
+  task_environment()->FastForwardBy(
+      kDefaultStudentHeartbeatInterval +
+      base::Seconds(30) +        // Initial backoff delay.
+      base::Seconds(30 * 1.2));  // Second backoff delay.
+}
+
 class BocaSessionManagerStudentHeartbeatCustomPollingTest
     : public BocaSessionManagerTestBase {
  protected:
diff --git a/chromeos/constants/chromeos_features.cc b/chromeos/constants/chromeos_features.cc
index 77b07aeb..ff12fb8 100644
--- a/chromeos/constants/chromeos_features.cc
+++ b/chromeos/constants/chromeos_features.cc
@@ -80,9 +80,6 @@
              "DisableSystemBlur",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-// Enables the desk profiles feature.
-BASE_FEATURE(kDeskProfiles, "DeskProfiles", base::FEATURE_DISABLED_BY_DEFAULT);
-
 // Disable idle sockets closing on memory pressure for NetworkContexts that
 // belong to Profiles. It only applies to Profiles because the goal is to
 // improve perceived performance of web browsing within the ChromeOS user
@@ -398,10 +395,6 @@
   return base::FeatureList::IsEnabled(kDataMigration);
 }
 
-bool IsDeskProfilesEnabled() {
-  return base::FeatureList::IsEnabled(kDeskProfiles);
-}
-
 bool IsEssentialSearchEnabled() {
   return base::FeatureList::IsEnabled(kEssentialSearch);
 }
diff --git a/chromeos/constants/chromeos_features.h b/chromeos/constants/chromeos_features.h
index 0057b50..0c7cf97 100644
--- a/chromeos/constants/chromeos_features.h
+++ b/chromeos/constants/chromeos_features.h
@@ -32,7 +32,6 @@
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosComponents);
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosMall);
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kCrosMallManaged);
-COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kDeskProfiles);
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 BASE_DECLARE_FEATURE(kDataControlsFileAccessDefaultDeny);
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) BASE_DECLARE_FEATURE(kDataMigration);
@@ -136,7 +135,6 @@
 bool IsDataControlsFileAccessDefaultDenyEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsDataMigrationEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
-bool IsDeskProfilesEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS) bool IsEssentialSearchEnabled();
 COMPONENT_EXPORT(CHROMEOS_CONSTANTS)
 bool IsFileSystemProviderCloudFileSystemEnabled();
diff --git a/clank b/clank
index 599d780..6ff6012 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 599d7806ce1185408289232b25620f00947b7c6a
+Subproject commit 6ff60127a2e8b147f1b62098202caf2b6110928f
diff --git a/components/autofill/content/renderer/password_autofill_agent.cc b/components/autofill/content/renderer/password_autofill_agent.cc
index cc89386..e08175a 100644
--- a/components/autofill/content/renderer/password_autofill_agent.cc
+++ b/components/autofill/content/renderer/password_autofill_agent.cc
@@ -2008,9 +2008,6 @@
   if (password.empty() && !is_single_username_fill) {
     if (username_element && !username_element.Value().IsEmpty() &&
         !prefilled_placeholder_username) {
-      LogPrefilledUsernameFillOutcome(
-          PrefilledUsernameFillOutcome::kPrefilledUsernameNotOverridden);
-
       LogMessage(logger, Logger::STRING_FAILED_TO_FILL_PREFILLED_USERNAME);
       LogFirstFillingResult(
           fill_data, FillingResult::kUsernamePrefilledWithIncompatibleValue);
@@ -2035,11 +2032,6 @@
          username_element.GetAutofillState() != WebAutofillState::kNotFilled ||
          prefilled_placeholder_username)) {
       FillFieldAutomatically(username, username_element);
-      if (prefilled_placeholder_username) {
-        LogPrefilledUsernameFillOutcome(
-            PrefilledUsernameFillOutcome::
-                kPrefilledPlaceholderUsernameOverridden);
-      }
     }
     if (logger)
       logger->LogElementName(Logger::STRING_USERNAME_FILLED, username_element);
@@ -2062,15 +2054,6 @@
   return true;
 }
 
-void PasswordAutofillAgent::LogPrefilledUsernameFillOutcome(
-    PrefilledUsernameFillOutcome outcome) {
-  if (prefilled_username_metrics_logged_)
-    return;
-  prefilled_username_metrics_logged_ = true;
-  UMA_HISTOGRAM_ENUMERATION("PasswordManager.PrefilledUsernameFillOutcome",
-                            outcome);
-}
-
 void PasswordAutofillAgent::FireHostSubmitEvent(
     FormRendererId form_id,
     base::optional_ref<const FormData> submitted_form,
diff --git a/components/autofill/content/renderer/password_autofill_agent.h b/components/autofill/content/renderer/password_autofill_agent.h
index 88a6fa10..c5b60056 100644
--- a/components/autofill/content/renderer/password_autofill_agent.h
+++ b/components/autofill/content/renderer/password_autofill_agent.h
@@ -48,27 +48,6 @@
 }
 
 namespace autofill {
-// Used in UMA histograms, please do NOT reorder.
-// Metric: "PasswordManager.PrefilledUsernameFillOutcome".
-enum class PrefilledUsernameFillOutcome {
-  // This value is reported if all of the following three conditions are met:
-  // 1) the page has a username input element whose value was prefilled by the
-  //    website itself.
-  // 2) the prefilled value was found in a list of known placeholder values
-  //    (e.g. "username or email").
-  // 3) the user had a credential stored and the field content was overridden
-  //    with the username of this credential due to 2).
-  kPrefilledPlaceholderUsernameOverridden = 0,
-  // This value is reported if all of the following conditions are met:
-  // 1) as above.
-  // 2) the prefilled value was NOT found in the list of known placeholder
-  //    values.
-  // 3) the user had a credential stored for this site but the field content
-  //    was NOT overridden due to 2).
-  kPrefilledUsernameNotOverridden = 1,
-  kMaxValue = kPrefilledUsernameNotOverridden,
-};
-
 // Used in UMA histogram, please do NOT reorder.
 // Metric: "PasswordManager.FirstRendererFillingResult".
 // This metric records whether the PasswordAutofillAgent succeeded in filling
@@ -546,11 +525,6 @@
                                     RendererSavePasswordProgressLogger* logger,
                                     bool notify_browser_of_successful_filling);
 
-  // Logs whether a username value that was prefilled by the website was
-  // overridden when trying to fill with an existing credential. This logs
-  // only one value per `PasswordAutofillAgent` instance.
-  void LogPrefilledUsernameFillOutcome(PrefilledUsernameFillOutcome outcome);
-
   void HidePopup();
 
   // Returns pair(username_element, password_element) based on renderer ids from
@@ -678,8 +652,6 @@
 
   mojo::AssociatedReceiver<mojom::PasswordAutofillAgent> receiver_{this};
 
-  bool prefilled_username_metrics_logged_ = false;
-
   // Keeps autofilled values for the form elements until a user gesture
   // is observed. At that point, the map is cleared.
   std::map<FieldRendererId, blink::WebString> autofilled_elements_cache_;
diff --git a/components/autofill/core/browser/form_import/form_data_importer.cc b/components/autofill/core/browser/form_import/form_data_importer.cc
index 8124b5d..4ef1fec 100644
--- a/components/autofill/core/browser/form_import/form_data_importer.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer.cc
@@ -1091,6 +1091,18 @@
                 field.Type().GetStorableType());
       result.card.SetInfoForMonthInputType(value);
     } else {
+      // If the credit card number offset is within the range of the old value,
+      // replace the portion of the old value with the value from the current
+      // field. For example:
+      // old value: '1234', offset: 4, new value:'5678', result: '12345678'
+      // old value: '12345678', offset: 4, new value:'0000', result: '12340000'
+      if (field.credit_card_number_offset() > 0 &&
+          field.credit_card_number_offset() <= old_value.size() &&
+          base::FeatureList::IsEnabled(
+              features::kAutofillFixSplitCreditCardImport)) {
+        value = old_value.replace(field.credit_card_number_offset(),
+                                  value.size(), value);
+      }
       bool saved = result.card.SetInfo(field.Type(), value, app_locale);
       if (!saved && field.IsSelectElement()) {
         // Saving with the option text (here `value`) may fail for the
@@ -1104,9 +1116,17 @@
         }
       }
     }
+
     std::u16string new_value = result.card.GetInfo(field.Type(), app_locale);
+    // Skip duplicate field check if the field is a split credit card
+    // number field.
+    bool skip_duplication_check =
+        field.Type().GetStorableType() == FieldType::CREDIT_CARD_NUMBER &&
+        field.credit_card_number_offset() > 0 &&
+        base::FeatureList::IsEnabled(
+            features::kAutofillFixSplitCreditCardImport);
     result.has_duplicate_credit_card_field_type |=
-        !old_value.empty() && old_value != new_value;
+        !skip_duplication_check && !old_value.empty() && old_value != new_value;
   };
 
   // Populates `result` from `fields` that satisfy `pred`, and erases those
diff --git a/components/autofill/core/browser/form_import/form_data_importer_unittest.cc b/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
index cf759fa8..d1b40253 100644
--- a/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
+++ b/components/autofill/core/browser/form_import/form_data_importer_unittest.cc
@@ -4124,15 +4124,21 @@
 
   void PushField(FieldType field_type,
                  std::u16string value,
-                 Mode mode = Mode::kDefaultValue) {
+                 Mode mode = Mode::kDefaultValue,
+                 size_t offset = 0) {
     AutofillField& f = test_api(form_).PushField();
     f.set_server_predictions({test::CreateFieldPrediction(field_type)});
     f.set_value(std::move(value));
     f.set_is_autofilled(mode == Mode::kAutofilled);
     f.set_is_user_edited(mode == Mode::kUserEdited);
+    f.set_credit_card_number_offset(offset);
   }
 
   FormStructure form_{/*form=*/{}};
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      features::kAutofillFixSplitCreditCardImport};
 };
 
 // Tests that inconsistent values from different priority classes do not prevent
@@ -4227,6 +4233,118 @@
   EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
 }
 
+// Tests that split credit card number extraction works in the same priority
+// class (user-edited fields).
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       ExtractSplitCreditCardNumber) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"2222", Mode::kUserEdited, 8);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1111", Mode::kUserEdited, 12);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NAME_FULL, kLocale),
+            u"Joe Biden");
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale),
+            u"4444333322221111");
+  EXPECT_EQ(
+      r.card.GetInfo(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, kLocale),
+      u"01/2021");
+  EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
+}
+
+// Tests that card extraction works when there are both split credit card
+// fields and full credit card fields and the card numbers match.
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       SplitCardAndFullCardFieldsMatch) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"2222", Mode::kUserEdited, 8);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1111", Mode::kUserEdited, 12);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322221111",
+            Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale),
+            u"4444333322221111");
+  EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
+}
+
+// Tests that split credit card number extraction is blocked when there are both
+// split credit card fields and full credit card fields and the numbers do not
+// match.
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       SplitCardAndFullCardFieldsDoNotMatch) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"2222", Mode::kUserEdited, 8);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1111", Mode::kUserEdited, 12);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444333322220000",
+            Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_TRUE(r.has_duplicate_credit_card_field_type);
+}
+
+// Tests that split credit card number extraction extracts the last value if any
+// of the field is invalid or missing.
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       ExtractsLastFieldIfHasInvalidOrMIssingFields) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1", Mode::kUserEdited, 12);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale), u"1");
+  EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
+}
+
+// Tests that user edited fields take priority and autofilled fields are ignored
+// when in conflict.
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       IgnoreDuplicatedFieldsFromDifferentPriorityClasses) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1234", Mode::kAutofilled, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"2222", Mode::kUserEdited, 8);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"1111", Mode::kUserEdited, 12);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale),
+            u"4444333322221111");
+  EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
+}
+
+// Tests split credit card number fields in a lower priority class are ignored.
+TEST_F(FormDataImporterTest_ExtractCreditCardFromForm,
+       IgnoreFieldsFromLowerPriorityClass) {
+  PushField(FieldType::CREDIT_CARD_NAME_FULL, u"Joe Biden", Mode::kAutofilled);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"4444", Mode::kUserEdited, 0);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"3333", Mode::kUserEdited, 4);
+  PushField(FieldType::CREDIT_CARD_NUMBER, u"2222", Mode::kAutofilled, 8);
+  PushField(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, u"01/2021",
+            Mode::kUserEdited);
+  auto r = form_data_importer().ExtractCreditCardFromForm(form_);
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NAME_FULL, kLocale),
+            u"Joe Biden");
+  EXPECT_EQ(r.card.GetInfo(FieldType::CREDIT_CARD_NUMBER, kLocale),
+            u"44443333");
+  EXPECT_EQ(
+      r.card.GetInfo(FieldType::CREDIT_CARD_EXP_DATE_4_DIGIT_YEAR, kLocale),
+      u"01/2021");
+  EXPECT_FALSE(r.has_duplicate_credit_card_field_type);
+}
+
 // Test fixture with flag "AutofillRelaxAddressImport" enabled.
 class FormDataImporterTest_RelaxAddressImport : public FormDataImporterTest {
  private:
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc
index d4e4953e..f9b5aa4 100644
--- a/components/autofill/core/browser/form_structure.cc
+++ b/components/autofill/core/browser/form_structure.cc
@@ -657,12 +657,8 @@
         field->set_ml_supported_types(cached_ml_types.value());
       }
       field->SetHtmlType(cached_field->html_type(), cached_field->html_mode());
-      if (reason == RetrieveFromCacheReason::kFormCacheUpdateWithoutParsing) {
-        // TODO: crbug.com/392179445 - Also do this for `kFormImport`, i.e.,
-        // remove the `if` condition.
-        field->set_credit_card_number_offset(
-            cached_field->credit_card_number_offset());
-      }
+      field->set_credit_card_number_offset(
+          cached_field->credit_card_number_offset());
       field->set_section(cached_field->section());
       field->set_only_fill_when_focused(cached_field->only_fill_when_focused());
 
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
index 25b7229..1fb1fbb 100644
--- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
+++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.cc
@@ -17,10 +17,12 @@
 #include "components/autofill/core/browser/data_manager/payments/payments_data_manager.h"
 #include "components/autofill/core/browser/form_import/form_data_importer.h"
 #include "components/autofill/core/browser/foundations/browser_autofill_manager.h"
+#include "components/autofill/core/browser/integrators/optimization_guide/autofill_optimization_guide.h"
 #include "components/autofill/core/browser/logging/log_manager.h"
 #include "components/autofill/core/browser/metrics/autofill_metrics_utils.h"
 #include "components/autofill/core/browser/metrics/form_events/form_events.h"
 #include "components/autofill/core/browser/metrics/form_interactions_ukm_logger.h"
+#include "components/autofill/core/browser/metrics/payments/bnpl_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/card_info_retrieval_enrolled_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/card_unmask_flow_metrics.h"
 #include "components/autofill/core/browser/metrics/payments/virtual_card_standalone_cvc_suggestion_metrics.h"
@@ -138,6 +140,37 @@
     }
     has_logged_suggestion_for_card_info_retrieval_enrolled_shown_ = true;
   }
+
+  if (!has_logged_suggestions_shown_on_bnpl_eligible_merchant_ &&
+      IsEligibleForBnpl(
+          owner_->client().GetLastCommittedPrimaryMainFrameURL())) {
+    LogBnplFormEvent(BnplFormEvent::kSuggestionsShownOnce);
+    has_logged_suggestions_shown_on_bnpl_eligible_merchant_ = true;
+  }
+}
+
+bool CreditCardFormEventLogger::IsEligibleForBnpl(GURL url) {
+  AutofillClient& autofill_client = owner_->client();
+  AutofillOptimizationGuide* autofill_optimization_guide =
+      autofill_client.GetAutofillOptimizationGuide();
+  if (!autofill_optimization_guide) {
+    return false;
+  }
+
+  payments::PaymentsAutofillClient* payments_autofill_client =
+      autofill_client.GetPaymentsAutofillClient();
+  if (!payments_autofill_client) {
+    return false;
+  }
+
+  const auto& bnpl_issuers =
+      payments_autofill_client->GetPaymentsDataManager().GetBnplIssuers();
+  return std::any_of(bnpl_issuers.begin(), bnpl_issuers.end(),
+                     [&](const auto& issuer) {
+                       return autofill_optimization_guide
+                           ->IsUrlEligibleForCheckoutAmountSearchForIssuerId(
+                               issuer.issuer_id(), url);
+                     });
 }
 
 void CreditCardFormEventLogger::OnDidSelectCardSuggestion(
diff --git a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
index 5fcc3abd..3e058be 100644
--- a/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
+++ b/components/autofill/core/browser/metrics/form_events/credit_card_form_event_logger.h
@@ -161,6 +161,9 @@
   bool DoesCardHaveOffer(const CreditCard& credit_card);
   // Returns whether the shown suggestions included a virtual credit card.
   bool DoSuggestionsIncludeVirtualCard();
+  // Checks whether the current website is relevant for BNPL for any known BNPL
+  // provider, according to the optimization guide.
+  bool IsEligibleForBnpl(GURL url);
 
   size_t server_record_type_count_ = 0;
   size_t local_record_type_count_ = 0;
@@ -208,6 +211,9 @@
   // If true, one of the cards in the suggestions fetched card info retrieval
   // enrolled.
   bool suggestion_contains_card_info_retrieval_enrolled_card_ = false;
+  // If true, the suggestions shown on BNPL eligible merchant is logged and
+  // should not be logged again.
+  bool has_logged_suggestions_shown_on_bnpl_eligible_merchant_ = false;
 
   CardMetadataLoggingContext metadata_logging_context_;
 
diff --git a/components/autofill/core/browser/metrics/payments/bnpl_metrics.cc b/components/autofill/core/browser/metrics/payments/bnpl_metrics.cc
index 511c443..a440573e 100644
--- a/components/autofill/core/browser/metrics/payments/bnpl_metrics.cc
+++ b/components/autofill/core/browser/metrics/payments/bnpl_metrics.cc
@@ -66,4 +66,8 @@
   base::UmaHistogramEnumeration(histogram_name, result);
 }
 
+void LogBnplFormEvent(BnplFormEvent event) {
+  base::UmaHistogramEnumeration("Autofill.FormEvents.CreditCard.Bnpl", event);
+}
+
 }  // namespace autofill::autofill_metrics
diff --git a/components/autofill/core/browser/metrics/payments/bnpl_metrics.h b/components/autofill/core/browser/metrics/payments/bnpl_metrics.h
index af762ac1..3e41fd62 100644
--- a/components/autofill/core/browser/metrics/payments/bnpl_metrics.h
+++ b/components/autofill/core/browser/metrics/payments/bnpl_metrics.h
@@ -14,6 +14,9 @@
 using BnplFlowResult = payments::PaymentsWindowManager::BnplFlowResult;
 
 // The reason why a BNPL suggestion was not shown on the page.
+//
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
 enum class BnplSuggestionNotShownReason {
   // The checkout amount could not be extracted from the page. This value is
   // necessary to determine BNPL eligibility for the purchase.
@@ -42,6 +45,17 @@
 // Returns the histogram suffix corresponding to the given issuer_id.
 std::string GetHistogramSuffixFromIssuerId(std::string_view issuer_id);
 
+// LINT.IfChange(BnplFormEvent)
+
+enum class BnplFormEvent {
+  // Payments autofill suggestions were shown on a BNPL-eligible merchant.
+  kSuggestionsShownOnce = 0,
+
+  kMaxValue = kSuggestionsShownOnce,
+};
+
+// LINT.ThenChange(/tools/metrics/histograms/metadata/autofill/enums.xml:BnplFormEvent)
+
 // Logs if the buy-now-pay-later preference is changed by the user through the
 // pay-over-time toggle in the payment methods settings page. Records true when
 // the user switches on buy-now-pay-later. Records false when the user switches
@@ -68,6 +82,10 @@
 void LogBnplPopupWindowResult(std::string_view issuer_id,
                               BnplFlowResult result);
 
+// Logs BNPL form events. Please refer to `BnplFormEvent` for the possible
+// enumerations that can be logged.
+void LogBnplFormEvent(BnplFormEvent event);
+
 }  // namespace autofill::autofill_metrics
 
 #endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_METRICS_PAYMENTS_BNPL_METRICS_H_
diff --git a/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc b/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc
index 9ee7578..1d160f81 100644
--- a/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc
+++ b/components/autofill/core/browser/metrics/payments/bnpl_metrics_unittest.cc
@@ -186,6 +186,78 @@
                                          kBnplZipIssuerId,
                                          kBnplAfterpayIssuerId));
 
+class BnplFormEventsMetricsTest : public AutofillMetricsBaseTest,
+                                  public testing::Test {
+ public:
+  BnplFormEventsMetricsTest() = default;
+  FormData form() { return form_; }
+
+  void SetUp() override {
+    SetUpHelper();
+
+    form_ =
+        GetAndAddSeenForm({.description_for_logging = "Bnpl",
+                           .fields = {{.role = CREDIT_CARD_NAME_FULL},
+                                      {.role = CREDIT_CARD_NUMBER},
+                                      {.role = CREDIT_CARD_EXP_MONTH},
+                                      {.role = CREDIT_CARD_EXP_2_DIGIT_YEAR}},
+                           .action = ""});
+
+    personal_data().test_payments_data_manager().AddBnplIssuer(
+        test::GetTestLinkedBnplIssuer());
+  }
+
+  void TearDown() override { TearDownHelper(); }
+
+ private:
+  base::test::ScopedFeatureList scoped_feature_list_{
+      features::kAutofillEnableBuyNowPayLaterSyncing};
+  FormData form_;
+};
+
+TEST_F(BnplFormEventsMetricsTest, SuggestionsShownOnBnplEligibleMerchant) {
+  base::HistogramTester histogram_tester;
+
+  autofill_manager().OnAskForValuesToFillTest(
+      form(), form().fields().back().global_id());
+
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_manager().client().GetAutofillOptimizationGuide()),
+          IsUrlEligibleForCheckoutAmountSearchForIssuerId)
+      .WillByDefault(testing::Return(true));
+
+  DidShowAutofillSuggestions(form(), /*field_index=*/form().fields().size() - 1,
+                             SuggestionType::kCreditCardEntry);
+
+  histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard.Bnpl",
+                                     BnplFormEvent::kSuggestionsShownOnce, 1);
+
+  // To ensure the metrics logs only once per page.
+  DidShowAutofillSuggestions(form(), /*field_index=*/form().fields().size() - 1,
+                             SuggestionType::kCreditCardEntry);
+
+  histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard.Bnpl",
+                                     BnplFormEvent::kSuggestionsShownOnce, 1);
+}
+
+TEST_F(BnplFormEventsMetricsTest, BnplSuggestionsNotShownDueToUrl) {
+  base::HistogramTester histogram_tester;
+
+  autofill_manager().OnAskForValuesToFillTest(
+      form(), form().fields().back().global_id());
+
+  ON_CALL(*static_cast<MockAutofillOptimizationGuide*>(
+              autofill_manager().client().GetAutofillOptimizationGuide()),
+          IsUrlEligibleForCheckoutAmountSearchForIssuerId)
+      .WillByDefault(testing::Return(false));
+
+  DidShowAutofillSuggestions(form(), /*field_index=*/form().fields().size() - 1,
+                             SuggestionType::kCreditCardEntry);
+
+  histogram_tester.ExpectBucketCount("Autofill.FormEvents.CreditCard.Bnpl",
+                                     BnplFormEvent::kSuggestionsShownOnce, 0);
+}
+
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) ||
         // BUILDFLAG(IS_CHROMEOS)
 
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index d1d75ec..a2ba50d7b 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -335,6 +335,12 @@
              "AutofillFixCurrentValueInImport",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
+// If enabled, credit cards that are split into different fields are imported.
+// TODO: crbug.com/392179445 - Clean up when launched.
+BASE_FEATURE(kAutofillFixSplitCreditCardImport,
+             "AutofillFixSplitCreditCardImport",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 // When enabled, focusing on a credit card number field that was traditionally
 // autofilled will yield all credit card suggestions.
 // TODO(crbug.com/354175563): Remove when launched.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index 9dea4fb..3780d74 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -118,6 +118,8 @@
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillFixCurrentValueInImport);
 COMPONENT_EXPORT(AUTOFILL)
+BASE_DECLARE_FEATURE(kAutofillFixSplitCreditCardImport);
+COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillPaymentsFieldSwapping);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillRecordCorrectionOfSelectElements);
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc
index 092da75..8386c43 100644
--- a/components/autofill/core/common/save_password_progress_logger.cc
+++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -473,6 +473,9 @@
     case STRING_RESOURCE_FAILED_LOADING_LOGIN_FAILED:
       return "POST error with 400-403 status is detected, considering "
              "current submission failed";
+    case STRING_NO_SUBMITTED_MANAGER_AVAILABLE:
+      return "OnLoginSuccessful was invoked but no there is no submitted "
+             "manager";
     case SavePasswordProgressLogger::STRING_INVALID:
       return "INVALID";
       // Intentionally no default: clause here -- all IDs need to get covered.
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h
index 88b22f0..3bcfb0b 100644
--- a/components/autofill/core/common/save_password_progress_logger.h
+++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -168,6 +168,7 @@
     STRING_RESOURCE_FAILED_LOADING_FOR_WRONG_FRAME,
     STRING_RESOURCE_FAILED_LOADING_FOR_WRONG_ORIGIN,
     STRING_RESOURCE_FAILED_LOADING_LOGIN_FAILED,
+    STRING_NO_SUBMITTED_MANAGER_AVAILABLE,
     STRING_INVALID,  // Represents a string returned in a case of an error.
     STRING_MAX = STRING_INVALID
   };
diff --git a/components/autofill_prediction_improvements_strings.grdp b/components/autofill_prediction_improvements_strings.grdp
index 10ad57d1..a333610 100644
--- a/components/autofill_prediction_improvements_strings.grdp
+++ b/components/autofill_prediction_improvements_strings.grdp
@@ -107,12 +107,15 @@
   </message>
 
   <!-- Save/Update prompt -->
-  <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_NO_THANKS_BUTTON" desc="Text displayed on the decline/cancel button of the save dialog.">
+  <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_NO_THANKS_BUTTON" desc="Text displayed on the decline/cancel button of the save/update dialog.">
     No thanks
   </message>
   <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_SAVE_BUTTON" desc="Text displayed on the accept/save button of the save dialog.">
     Save
   </message>
+  <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_UPDATE_DIALOG_UPDATE_BUTTON" desc="Text displayed on the accept/save button of the update dialog.">
+    Update
+  </message>
   <message name="IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_SAVE_DIALOG_FOOTER_DETAILS" desc="Text displayed on the footer of the save dialog giving users details about how Autofill with AI data is saved.">
     Saved info and the page from <ph name="WEBSITE">$1<ex>airline.com</ex></ph> are sent to Google and may be seen by human reviewers to improve this feature.
   </message>
diff --git a/components/autofill_prediction_improvements_strings_grdp/IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_UPDATE_DIALOG_UPDATE_BUTTON.png.sha1 b/components/autofill_prediction_improvements_strings_grdp/IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_UPDATE_DIALOG_UPDATE_BUTTON.png.sha1
new file mode 100644
index 0000000..45fede6
--- /dev/null
+++ b/components/autofill_prediction_improvements_strings_grdp/IDS_AUTOFILL_PREDICTION_IMPROVEMENTS_UPDATE_DIALOG_UPDATE_BUTTON.png.sha1
@@ -0,0 +1 @@
+0c5cb910622a2ffa16552c96aff8fcfe5c3d1c10
\ No newline at end of file
diff --git a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
index 08a207c..a6f9d38 100644
--- a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
+++ b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
@@ -51,7 +51,7 @@
 
     /** Returns the semantic color value that corresponds to default_icon_color_on_accent1. */
     public static @ColorInt int getDefaultIconColorOnAccent1(Context context) {
-        return resolve(R.attr.colorOnPrimary, context);
+        return getColorOnPrimary(context);
     }
 
     /**
@@ -63,7 +63,7 @@
 
     /** Returns the semantic color value that corresponds to default_text_color_on_accent1. */
     public static @ColorInt int getDefaultTextColorOnAccent1(Context context) {
-        return resolve(R.attr.colorOnPrimary, context);
+        return getColorOnPrimary(context);
     }
 
     /** Returns the semantic color value that corresponds to default_text_color_secondary. */
@@ -189,6 +189,11 @@
         return resolve(R.attr.colorPrimaryContainer, context);
     }
 
+    /** Returns the semantic color values that correspond to colorOnPrimary. */
+    public static @ColorInt int getColorOnPrimary(Context context) {
+        return resolve(R.attr.colorOnPrimary, context);
+    }
+
     /** Returns the semantic color values that correspond to colorOnSurfaceInverse. */
     public static @ColorInt int getColorOnSurfaceInverse(Context context) {
         return resolve(R.attr.colorOnSurfaceInverse, context);
diff --git a/components/omnibox/browser/autocomplete_result_unittest.cc b/components/omnibox/browser/autocomplete_result_unittest.cc
index b271ec49..8de86122 100644
--- a/components/omnibox/browser/autocomplete_result_unittest.cc
+++ b/components/omnibox/browser/autocomplete_result_unittest.cc
@@ -3230,34 +3230,22 @@
                                TestSchemeClassifier());
   zero_input.set_focus_type(metrics::OmniboxFocusType::INTERACTION_FOCUS);
 
-  {
-    SCOPED_TRACE("Trend suggestions are only available on iPhones");
-    base::test::ScopedFeatureList feature_list;
-    AutocompleteResult result;
-    result.MergeSuggestionGroupsMap(suggestion_groups_map);
-    result.AppendMatches(matches);
-    result.SortAndCull(zero_input, &template_url_service(),
-                       triggered_feature_service());
+  base::test::ScopedFeatureList feature_list;
+  AutocompleteResult result;
+  result.MergeSuggestionGroupsMap(suggestion_groups_map);
+  result.AppendMatches(matches);
+  result.SortAndCull(zero_input, &template_url_service(),
+                     triggered_feature_service());
 
-    if (ui::GetDeviceFormFactor() == ui::DEVICE_FORM_FACTOR_TABLET) {
-      // Ipads should keep the default config.
-      const std::array<TestData, 3> expected_data{{
-          {0, 1, 500, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-          {1, 1, 490, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-          {2, 1, 480, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-      }};
-      AssertResultMatches(result, expected_data);
-    } else {
-      const std::array<TestData, 5> expected_data{{
-          {0, 1, 500, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-          {1, 1, 490, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-          {2, 1, 480, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
-          {3, 1, 470, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group2},
-          {4, 1, 460, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group2},
-      }};
-      AssertResultMatches(result, expected_data);
-    }
-  }
+  const std::array<TestData, 5> expected_data{{
+      {0, 1, 500, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
+      {1, 1, 490, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
+      {2, 1, 480, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group1},
+      {3, 1, 470, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group2},
+      {4, 1, 460, false, {}, AutocompleteMatchType::SEARCH_SUGGEST, group2},
+  }};
+
+  AssertResultMatches(result, expected_data);
 }
 #endif
 
diff --git a/components/omnibox/browser/omnibox_field_trial.h b/components/omnibox/browser/omnibox_field_trial.h
index 8761bc9..2bd1e7c 100644
--- a/components/omnibox/browser/omnibox_field_trial.h
+++ b/components/omnibox/browser/omnibox_field_trial.h
@@ -689,12 +689,12 @@
 constexpr base::FeatureParam<int> kIpadAdditionalTrendingQueries(
     &omnibox::kIpadZeroSuggestMatches,
     "IpadAdditionalTrendingQueries",
-    0);
+    5);
 
 constexpr base::FeatureParam<int> kIpadZPSLimit(
     &omnibox::kIpadZeroSuggestMatches,
     "IpadZPSSuggestionsLimit",
-    10);
+    20);
 
 // <- Ipad suggestions limit
 // ---------------------------------------------------------
diff --git a/components/omnibox/common/omnibox_features.cc b/components/omnibox/common/omnibox_features.cc
index a07037a..88ce2c37 100644
--- a/components/omnibox/common/omnibox_features.cc
+++ b/components/omnibox/common/omnibox_features.cc
@@ -355,7 +355,9 @@
 BASE_FEATURE(kOmniboxShortcutsAndroid, "OmniboxShortcutsAndroid", ENABLED);
 
 // When enabled, it increases ipad's zps matches limit on web,srp and ntp.
-BASE_FEATURE(kIpadZeroSuggestMatches, "IpadZeroSuggestMatches", DISABLED);
+BASE_FEATURE(kIpadZeroSuggestMatches,
+             "IpadZeroSuggestMatches",
+             enable_if(IS_IOS));
 
 // The features below allow tuning number of suggestions offered to users in
 // specific contexts. These features are default enabled and are used to control
diff --git a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
index 880e0bb..170ca665 100644
--- a/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
+++ b/components/page_load_metrics/google/browser/gws_page_load_metrics_observer.cc
@@ -57,6 +57,8 @@
     HISTOGRAM_PREFIX "NavigationTiming.NavigationStartToOnComplete";
 const char kHistogramGWSCreateStreamDelay[] =
     HISTOGRAM_PREFIX "NavigationTiming.CreateStreamDelay";
+const char kHistogramGWSConnectedCallbackDelay[] =
+    HISTOGRAM_PREFIX "NavigationTiming.ConnectedCallbackDelay";
 const char kHistogramGWSInitializeStreamDelay[] =
     HISTOGRAM_PREFIX "NavigationTiming.InitializeStreamDelay";
 
@@ -414,6 +416,8 @@
       timing.final_request_ssl_delay);
   PAGE_LOAD_SHORT_HISTOGRAM(internal::kHistogramGWSCreateStreamDelay,
                             timing.create_stream_delay);
+  PAGE_LOAD_SHORT_HISTOGRAM(internal::kHistogramGWSConnectedCallbackDelay,
+                            timing.connected_callback_delay);
   PAGE_LOAD_SHORT_HISTOGRAM(internal::kHistogramGWSInitializeStreamDelay,
                             timing.initialize_stream_delay);
 
diff --git a/components/password_manager/core/browser/features/password_features.cc b/components/password_manager/core/browser/features/password_features.cc
index 85cff4a9..7a1be16 100644
--- a/components/password_manager/core/browser/features/password_features.cc
+++ b/components/password_manager/core/browser/features/password_features.cc
@@ -51,6 +51,10 @@
              "FailedLoginDetectionBasedOnResourceLoadingErrors",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kFailedLoginDetectionBasedOnFormClearEvent,
+             "FailedLoginDetectionBasedOnFormClearEvent",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 #if BUILDFLAG(IS_ANDROID)
 BASE_FEATURE(kFetchGaiaHashOnSignIn,
              "FetchGaiaHashOnSignIn",
@@ -112,6 +116,10 @@
              "PasswordManualFallbackAvailable",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kPostponeOnLoginSuccessful,
+             "PostponeOnLoginSuccessful",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kReuseDetectionBasedOnPasswordHashes,
              "ReuseDetectionBasedOnPasswordHashes",
              base::FEATURE_ENABLED_BY_DEFAULT);
@@ -173,11 +181,11 @@
 
 BASE_FEATURE(kUseNewEncryptionMethod,
              "UseNewEncryptionMethod",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kEncryptAllPasswordsWithOSCryptAsync,
              "EncryptAllPasswordsWithOSCryptAsync",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kMarkAllCredentialsAsLeaked,
              "MarkAllCredentialsAsLeaked",
diff --git a/components/password_manager/core/browser/features/password_features.h b/components/password_manager/core/browser/features/password_features.h
index 8964738..5900ee26 100644
--- a/components/password_manager/core/browser/features/password_features.h
+++ b/components/password_manager/core/browser/features/password_features.h
@@ -48,6 +48,10 @@
 // same iframe with 400-403 status code.
 BASE_DECLARE_FEATURE(kFailedLoginDetectionBasedOnResourceLoadingErrors);
 
+// Marks form submission as failed whenever a password field is cleared for the
+// sign-in forms.
+BASE_DECLARE_FEATURE(kFailedLoginDetectionBasedOnFormClearEvent);
+
 #if BUILDFLAG(IS_ANDROID)
 // Enables reading credentials from SharedPreferences.
 BASE_DECLARE_FEATURE(kFetchGaiaHashOnSignIn);
@@ -109,6 +113,10 @@
 // Enables triggering password suggestions through the context menu.
 BASE_DECLARE_FEATURE(kPasswordManualFallbackAvailable);
 
+// Enables postponing detecting a successful submission and showing the
+// save/update UI by a fixed time.
+BASE_DECLARE_FEATURE(kPostponeOnLoginSuccessful);
+
 // Detects password reuse based on hashed password values.
 BASE_DECLARE_FEATURE(kReuseDetectionBasedOnPasswordHashes);
 
diff --git a/components/password_manager/core/browser/password_manager.cc b/components/password_manager/core/browser/password_manager.cc
index d5cbee0..5467e8ee 100644
--- a/components/password_manager/core/browser/password_manager.cc
+++ b/components/password_manager/core/browser/password_manager.cc
@@ -666,7 +666,8 @@
     possible_usernames_.Clear();
   }
 
-  if (form_may_be_submitted) {
+  if (form_may_be_submitted ||
+      !on_successful_submission_closure_.IsCancelled()) {
     std::unique_ptr<PasswordFormManager> submitted_manager =
         password_form_cache_.MoveOwnedSubmittedManager();
     if (submitted_manager) {
@@ -789,46 +790,53 @@
   submitted_manager->UpdateSubmissionIndicatorEvent(event);
 
   if (IsAutomaticSavePromptAvailable()) {
-    OnLoginSuccessful();
+    ScheduleOnLoginsSuccessful();
   }
 }
 
 void PasswordManager::OnPasswordFormCleared(
     PasswordManagerDriver* driver,
     const autofill::FormData& form_data) {
-  if (auto logger = GetLoggerIfAvailable(client_)) {
+  auto logger = GetLoggerIfAvailable(client_);
+  if (logger) {
     logger->LogMessage(Logger::STRING_ON_PASSWORD_FORM_CLEARED);
   }
   PasswordFormManager* manager =
       GetMatchedManagerForForm(driver, form_data.renderer_id());
-  if (!manager || !IsAutomaticSavePromptAvailable(manager) ||
-      !manager->HasLikelyChangeOrResetFormSubmitted()) {
+  if (!manager || !IsAutomaticSavePromptAvailable(manager)) {
     return;
   }
-  // If a password form was cleared, login is successful.
-  if (!form_data.renderer_id().is_null()) {
-    manager->UpdateSubmissionIndicatorEvent(
-        SubmissionIndicatorEvent::CHANGE_PASSWORD_FORM_CLEARED);
 
+  auto relevant_field_cleared = [&form_data](FieldRendererId field) {
+    // Return immediately if the whole form was cleared.
+    if (!form_data.renderer_id().is_null()) {
+      return true;
+    }
+    auto it = std::ranges::find(form_data.fields(), field,
+                                &autofill::FormFieldData::renderer_id);
+    return it != form_data.fields().end() && it->value().empty();
+  };
+
+  if (manager->HasLikelyChangeOrResetFormSubmitted()) {
+    if (relevant_field_cleared(
+            manager->GetSubmittedForm()->new_password_element_renderer_id)) {
+      manager->UpdateSubmissionIndicatorEvent(
+          SubmissionIndicatorEvent::CHANGE_PASSWORD_FORM_CLEARED);
 #if BUILDFLAG(IS_ANDROID)
-    SignalFormSubmissionIfEligibleForSaving(manager, client_);
+      SignalFormSubmissionIfEligibleForSaving(manager, client_);
 #endif
-    OnLoginSuccessful();
+      ScheduleOnLoginsSuccessful();
+    }
     return;
   }
-  // If password fields outside the <form> tag were cleared, it should be
-  // verified that fields are relevant.
-  FieldRendererId new_password_field_id =
-      manager->GetSubmittedForm()->new_password_element_renderer_id;
-  auto it = std::ranges::find(form_data.fields(), new_password_field_id,
-                              &autofill::FormFieldData::renderer_id);
-  if (it != form_data.fields().end() && it->value().empty()) {
-    manager->UpdateSubmissionIndicatorEvent(
-        SubmissionIndicatorEvent::CHANGE_PASSWORD_FORM_CLEARED);
-#if BUILDFLAG(IS_ANDROID)
-    SignalFormSubmissionIfEligibleForSaving(manager, client_);
-#endif
-    OnLoginSuccessful();
+
+  // If it's neither change or reset form it must be a sign-in or a sign-up
+  // form. Check if login should be considered failed in this case.
+  if (relevant_field_cleared(
+          manager->GetSubmittedForm()->password_element_renderer_id) &&
+      base::FeatureList::IsEnabled(
+          features::kFailedLoginDetectionBasedOnFormClearEvent)) {
+    OnLoginFailed(logger.get());
   }
 }
 
@@ -842,7 +850,7 @@
   ProvisionallySaveForm(form_data, driver, false);
 
   if (IsAutomaticSavePromptAvailable()) {
-    OnLoginSuccessful();
+    ScheduleOnLoginsSuccessful();
   }
 }
 #endif  // BUILDFLAG(IS_IOS)
@@ -1435,7 +1443,23 @@
   // automatically save the login data. We prompt when the user hasn't
   // already given consent, either through previously accepting the infobar
   // or by having the browser generate the password.
-  OnLoginSuccessful();
+  ScheduleOnLoginsSuccessful();
+}
+
+void PasswordManager::ScheduleOnLoginsSuccessful() {
+  if (!base::FeatureList::IsEnabled(features::kPostponeOnLoginSuccessful)) {
+    OnLoginSuccessful();
+    return;
+  }
+  if (!on_successful_submission_closure_.IsCancelled()) {
+    // If successful submission already scheduled, no need to do anything.
+    return;
+  }
+  on_successful_submission_closure_.Reset(base::BindOnce(
+      &PasswordManager::OnLoginSuccessful, weak_ptr_factory_.GetWeakPtr()));
+  base::SequencedTaskRunner::GetCurrentDefault()->PostDelayedTask(
+      FROM_HERE, on_successful_submission_closure_.callback(),
+      kDelayBeforeSuccessfulLogin);
 }
 
 void PasswordManager::OnLoginSuccessful() {
@@ -1446,9 +1470,13 @@
   }
 
   PasswordFormManager* submitted_manager = GetSubmittedManager();
-  CHECK(submitted_manager);
+
+  if (!submitted_manager || !submitted_manager->GetSubmittedForm()) {
+    logger->LogMessage(Logger::STRING_NO_SUBMITTED_MANAGER_AVAILABLE);
+    return;
+  }
+
   const PasswordForm* submitted_form = submitted_manager->GetSubmittedForm();
-  CHECK(submitted_form);
 
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
   MaybeTriggerHatsSurvey(*submitted_manager);
@@ -1571,6 +1599,7 @@
   if (logger) {
     logger->LogMessage(Logger::STRING_DECISION_DROP);
   }
+  on_successful_submission_closure_.Cancel();
 
   PasswordFormManager* submitted_manager = GetSubmittedManager();
   DCHECK(submitted_manager);
@@ -1885,7 +1914,7 @@
   // If the manager was set to be submitted, either prior to this function call
   // or on provisional save above, consider submission successful.
   if (IsAutomaticSavePromptAvailable(form_manager)) {
-    OnLoginSuccessful();
+    ScheduleOnLoginsSuccessful();
     return true;
   }
   return false;
diff --git a/components/password_manager/core/browser/password_manager.h b/components/password_manager/core/browser/password_manager.h
index eb2cf2b..cfe9be4 100644
--- a/components/password_manager/core/browser/password_manager.h
+++ b/components/password_manager/core/browser/password_manager.h
@@ -80,6 +80,9 @@
                                            static_cast<int>(rhs));
 }
 
+inline constexpr base::TimeDelta kDelayBeforeSuccessfulLogin =
+    base::Milliseconds(500);
+
 // Per-tab password manager. Handles creation and management of UI elements,
 // receiving password form data from the renderer and managing the password
 // database through the PasswordStore.
@@ -298,10 +301,13 @@
   bool ShouldBlockPasswordForSameOriginButDifferentScheme(
       const GURL& origin) const;
 
-  // Called when the login was deemed successful. It handles the special case
-  // when the provisionally saved password is a sync credential, and otherwise
-  // asks the user about saving the password or saves it directly, as
-  // appropriate.
+  // ScheduleOnLoginsSuccessful is called when the login was deemed successful.
+  // It post OnLoginSuccessful with a delayed. The delay allows to catch failed
+  // logins (e.g. based on failed POST requests) more effectively as a sequence
+  // of events isn't guaranteed. OnLoginSuccessful handles the special case when
+  // the provisionally saved password is a sync credential, and otherwise asks
+  // the user about saving the password or saves it directly, as appropriate.
+  void ScheduleOnLoginsSuccessful();
   void OnLoginSuccessful();
 
   // Called when the login was considered unsuccessful. Takes care of logging
@@ -481,6 +487,11 @@
       possible_usernames_ =
           base::LRUCache<PossibleUsernameFieldIdentifier, PossibleUsernameData>(
               kMaxSingleUsernameFieldsToStore);
+
+  // Closure holding a scheduled call to OnLoginSuccessful().
+  base::CancelableOnceClosure on_successful_submission_closure_;
+
+  base::WeakPtrFactory<PasswordManager> weak_ptr_factory_{this};
 };
 
 }  // namespace password_manager
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc
index 151b511..029b507 100644
--- a/components/password_manager/core/browser/password_manager_unittest.cc
+++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -6637,6 +6637,154 @@
   EXPECT_TRUE(manager()->GetSubmittedManagerForTest());
 }
 
+TEST_P(PasswordManagerTest, NotifyOnSuccessfulLoginIsDelayed) {
+  base::test::ScopedFeatureList feature_list(
+      features::kPostponeOnLoginSuccessful);
+
+  PasswordForm form(MakeSimpleForm());
+  std::vector<FormData> observed = {form.form_data};
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+  ASSERT_TRUE(manager()->form_managers().front());
+
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
+      .WillRepeatedly(Return(true));
+  OnPasswordFormSubmitted(form.form_data);
+
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin(form.username_value)).Times(0);
+
+  observed.clear();
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+
+  // After the kDelayBeforeSuccessfulLogin NotifyOnSuccessfulLogin is invoked.
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin(form.username_value));
+  task_environment_.FastForwardBy(kDelayBeforeSuccessfulLogin);
+}
+
+TEST_P(PasswordManagerTest,
+       DelayedNotifyOnSuccessfulLoginWorksEvenAfterNavigation) {
+  base::test::ScopedFeatureList feature_list(
+      features::kPostponeOnLoginSuccessful);
+
+  PasswordForm form(MakeSimpleForm());
+  std::vector<FormData> observed = {form.form_data};
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+  ASSERT_TRUE(manager()->form_managers().front());
+
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
+      .WillRepeatedly(Return(true));
+  OnPasswordFormSubmitted(form.form_data);
+
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin(form.username_value)).Times(0);
+
+  observed.clear();
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+
+  // Now navigate to a second page.
+  manager()->DidNavigateMainFrame(false);
+
+  // After the kDelayBeforeSuccessfulLogin NotifyOnSuccessfulLogin is invoked.
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin(form.username_value));
+  task_environment_.FastForwardBy(kDelayBeforeSuccessfulLogin);
+}
+
+TEST_P(PasswordManagerTest, NotifyOnSuccessfulLoginInvokedOnce) {
+  base::test::ScopedFeatureList feature_list(
+      features::kPostponeOnLoginSuccessful);
+
+  PasswordForm form(MakeSimpleForm());
+  std::vector<FormData> observed = {form.form_data};
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+  ASSERT_TRUE(manager()->form_managers().front());
+
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
+      .WillRepeatedly(Return(true));
+  OnPasswordFormSubmitted(form.form_data);
+
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin).Times(0);
+
+  observed.clear();
+  for (int i = 0; i < 10; i++) {
+    manager()->OnPasswordFormsParsed(&driver_, observed);
+    manager()->OnPasswordFormsRendered(&driver_, observed);
+    task_environment_.RunUntilIdle();
+  }
+
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin(form.username_value)).Times(1);
+  task_environment_.FastForwardBy(kDelayBeforeSuccessfulLogin * 2);
+}
+
+TEST_P(PasswordManagerTest, NotifyOnSuccessfulLoginIsNotInvokedAfterFailure) {
+  base::test::ScopedFeatureList feature_list(
+      features::kPostponeOnLoginSuccessful);
+
+  PasswordForm form(MakeSimpleForm());
+  std::vector<FormData> observed = {form.form_data};
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+  ASSERT_TRUE(manager()->form_managers().front());
+
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
+      .WillRepeatedly(Return(true));
+  OnPasswordFormSubmitted(form.form_data);
+
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin).Times(0);
+
+  // Emulate a navigation to a different page without a form, only for a form to
+  // appear shortly after. This will result into considering login failed.
+  manager()->OnPasswordFormsParsed(&driver_, std::vector<FormData>());
+  manager()->OnPasswordFormsRendered(&driver_, std::vector<FormData>());
+  task_environment_.RunUntilIdle();
+
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+
+  // After the kDelayBeforeSuccessfulLogin NotifyOnSuccessfulLogin does not get
+  // invoked.
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin).Times(0);
+  task_environment_.FastForwardBy(kDelayBeforeSuccessfulLogin * 2);
+}
+
+TEST_P(PasswordManagerTest, LoginFormClearingIsConsideredFailedLoginAttempt) {
+  base::test::ScopedFeatureList feature_list(
+      features::kFailedLoginDetectionBasedOnFormClearEvent);
+
+  PasswordForm form(MakeSimpleForm());
+  FormData form_data = form.form_data;
+  std::vector<FormData> observed = {form_data};
+
+  // Emulate page load.
+  manager()->OnPasswordFormsParsed(&driver_, observed);
+  manager()->OnPasswordFormsRendered(&driver_, observed);
+  task_environment_.RunUntilIdle();
+  EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.url))
+      .WillRepeatedly(Return(true));
+
+  OnPasswordFormSubmitted(form_data);
+
+  // Verify no successful submission is detected.
+  EXPECT_CALL(client_, NotifyOnSuccessfulLogin).Times(0);
+
+  test_api(form_data).field(0).set_value(u"");
+  test_api(form_data).field(1).set_value(u"");
+  manager()->OnPasswordFormCleared(&driver_, form.form_data);
+  task_environment_.RunUntilIdle();
+
+  // Verify submitted manager is reset.
+  EXPECT_FALSE(manager()->GetSubmittedManagerForTest());
+}
+
 INSTANTIATE_TEST_SUITE_P(, PasswordManagerTest, ::testing::Bool());
 
 enum class PredictionSource {
diff --git a/components/performance_manager/decorators/frame_input_state_decorator.cc b/components/performance_manager/decorators/frame_input_state_decorator.cc
index c6e20df8..13ce706 100644
--- a/components/performance_manager/decorators/frame_input_state_decorator.cc
+++ b/components/performance_manager/decorators/frame_input_state_decorator.cc
@@ -5,6 +5,7 @@
 #include "components/performance_manager/decorators/frame_input_state_decorator.h"
 
 #include "base/check_is_test.h"
+#include "base/metrics/histogram_macros.h"
 #include "components/performance_manager/graph/frame_node_impl.h"
 #include "components/performance_manager/public/performance_manager.h"
 #include "components/performance_manager/public/render_frame_host_proxy.h"
@@ -37,29 +38,25 @@
 
 void FrameInputStateDecorator::OnBeforeFrameNodeRemoved(
     const FrameNode* frame_node) {
-  switch (Data::Get(frame_node)->input_scenario()) {
-    case InputScenario::kNoInput:
-      break;
-    case InputScenario::kTyping:
-      UpdateInputScenario(frame_node, false);
-      break;
-  }
+  UpdateInputScenario(frame_node, InputScenario::kNoInput,
+                      InputScenarioUpdateReason::kNodeRemoved);
   Data::Destroy(frame_node);
 }
 
-void FrameInputStateDecorator::UpdateInputScenario(const FrameNode* frame_node,
-                                                   bool typing) {
-  InputScenario new_scenario =
-      typing ? InputScenario::kTyping : InputScenario::kNoInput;
-
+void FrameInputStateDecorator::UpdateInputScenario(
+    const FrameNode* frame_node,
+    InputScenario input_scenario,
+    InputScenarioUpdateReason update_reason) {
   auto* data = Data::Get(frame_node);
-  if (!data || data->input_scenario() == new_scenario) {
+  if (!data || data->input_scenario() == input_scenario) {
     return;
   }
 
-  data->set_input_scenario(new_scenario);
+  data->set_input_scenario(input_scenario);
   observers_.Notify(&FrameInputStateObserver::OnInputScenarioChanged,
                     frame_node);
+  UMA_HISTOGRAM_ENUMERATION("PerformanceManager.InputScenarioChanged",
+                            update_reason);
 }
 
 void FrameInputStateDecorator::AddObserver(FrameInputStateObserver* observer) {
@@ -92,14 +89,16 @@
  private:
   void OnInputInactiveTimer();
   void OnKeyEvent(const blink::WebInputEvent& event);
+  void OnScrollEvent(const blink::WebInputEvent& event);
+  void OnTapEvent(const blink::WebInputEvent& event);
 
   raw_ptr<FrameInputStateDecorator> decorator_;
   raw_ptr<const FrameNode> frame_node_;
   base::OneShotTimer timer_;
 
-  // Typing detection:
+  // Input detection.
   base::TimeTicks last_key_event_time_;
-  bool typing_ = false;
+  InputScenario input_scenario_ = InputScenario::kNoInput;
 
   base::ScopedObservation<content::RenderWidgetHost,
                           content::RenderWidgetHost::InputEventObserver>
@@ -138,9 +137,45 @@
 void FrameInputStateDecorator::InputObserver::OnInputEvent(
     const content::RenderWidgetHost& rwh,
     const blink::WebInputEvent& event) {
-  // Currently we only care about key down events.
-  if (event.GetType() == blink::WebInputEvent::Type::kRawKeyDown) {
-    OnKeyEvent(event);
+  switch (event.GetType()) {
+    case blink::WebInputEvent::Type::kRawKeyDown:
+      OnKeyEvent(event);
+      return;
+    // Pinches and flings are classified as scrolls.
+    // Based on
+    // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/common/input/web_gesture_event.h;l=258;drc=317c59e45d1ed2656fdfd6bfecccfdf6ee8e588e
+    case blink::WebInputEvent::Type::kGestureScrollBegin:
+    case blink::WebInputEvent::Type::kGestureScrollEnd:
+    case blink::WebInputEvent::Type::kGestureScrollUpdate:
+    case blink::WebInputEvent::Type::kGestureFlingStart:
+    case blink::WebInputEvent::Type::kGestureFlingCancel:
+    case blink::WebInputEvent::Type::kGesturePinchBegin:
+    case blink::WebInputEvent::Type::kGesturePinchEnd:
+    case blink::WebInputEvent::Type::kGesturePinchUpdate:
+      OnScrollEvent(event);
+      return;
+    // This is based on input event types defined here:
+    // https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/public/mojom/input/input_event.mojom;l=86;drc=5be39635e5385132d645d2810e14614642291981
+    case blink::WebInputEvent::Type::kGestureTapDown:
+    case blink::WebInputEvent::Type::kGestureTapUnconfirmed:
+      // Ignored - let's wait until they're resolved into a more specific
+      // gesture.
+      return;
+    case blink::WebInputEvent::Type::kGestureTapCancel:
+      // Ignored because it means that we didn't get any GestureTap event.
+      return;
+    case blink::WebInputEvent::Type::kGestureShowPress:
+    case blink::WebInputEvent::Type::kGestureTap:
+    case blink::WebInputEvent::Type::kGestureShortPress:
+    case blink::WebInputEvent::Type::kGestureLongPress:
+    case blink::WebInputEvent::Type::kGestureLongTap:
+    case blink::WebInputEvent::Type::kGestureTwoFingerTap:
+    case blink::WebInputEvent::Type::kGestureDoubleTap:
+      OnTapEvent(event);
+      return;
+    default:
+      // We intentionally ignore other input types.
+      return;
   }
 }
 
@@ -157,9 +192,10 @@
 }
 
 void FrameInputStateDecorator::InputObserver::OnInputInactiveTimer() {
-  DCHECK(typing_);
-  typing_ = false;
-  decorator_->UpdateInputScenario(frame_node_, typing_);
+  DCHECK(input_scenario_ != InputScenario::kNoInput);
+  input_scenario_ = InputScenario::kNoInput;
+  decorator_->UpdateInputScenario(frame_node_, input_scenario_,
+                                  InputScenarioUpdateReason::kTimeout);
 }
 
 void FrameInputStateDecorator::InputObserver::OnKeyEvent(
@@ -167,11 +203,13 @@
   base::TimeTicks now = base::TimeTicks::Now();
   // Only consider continuous key events (>2 in 1 second) as typing to avoid
   // noise from single key press.
-  if (!typing_ && now - last_key_event_time_ < base::Seconds(1)) {
-    typing_ = true;
-    decorator_->UpdateInputScenario(frame_node_, typing_);
+  if (input_scenario_ == InputScenario::kNoInput &&
+      now - last_key_event_time_ < base::Seconds(1)) {
+    input_scenario_ = InputScenario::kTyping;
+    decorator_->UpdateInputScenario(frame_node_, input_scenario_,
+                                    InputScenarioUpdateReason::kKeyEvent);
   }
-  if (typing_) {
+  if (input_scenario_ == InputScenario::kTyping) {
     // While typing, every key event pushes the deadline to exit the
     // typing scenario.
     timer_.Start(FROM_HERE, kInactivityTimeoutForTyping,
@@ -181,4 +219,54 @@
   last_key_event_time_ = now;
 }
 
+void FrameInputStateDecorator::InputObserver::OnScrollEvent(
+    const blink::WebInputEvent& event) {
+  switch (event.GetType()) {
+    case blink::WebInputEvent::Type::kGestureScrollBegin:
+    case blink::WebInputEvent::Type::kGestureScrollUpdate:
+    case blink::WebInputEvent::Type::kGestureFlingStart:
+    case blink::WebInputEvent::Type::kGesturePinchBegin:
+    case blink::WebInputEvent::Type::kGesturePinchUpdate:
+      input_scenario_ = InputScenario::kScroll;
+      break;
+    case blink::WebInputEvent::Type::kGestureScrollEnd:
+    case blink::WebInputEvent::Type::kGestureFlingCancel:
+    case blink::WebInputEvent::Type::kGesturePinchEnd:
+      input_scenario_ = InputScenario::kNoInput;
+      timer_.Stop();
+      break;
+    default:
+      NOTREACHED();
+  }
+  decorator_->UpdateInputScenario(
+      frame_node_, input_scenario_,
+      input_scenario_ == InputScenario::kScroll
+          ? InputScenarioUpdateReason::kScrollStartEvent
+          : InputScenarioUpdateReason::kScrollEndEvent);
+  if (input_scenario_ == InputScenario::kScroll) {
+    // While scrolling, every scroll event pushes the deadline to exit the
+    // scrolling scenario. Note: this is just a fail safe if the end/cancel
+    // event goes missing.
+    timer_.Start(FROM_HERE, kInactivityTimeoutForScroll,
+                 base::BindOnce(&InputObserver::OnInputInactiveTimer,
+                                base::Unretained(this)));
+  }
+}
+
+void FrameInputStateDecorator::InputObserver::OnTapEvent(
+    const blink::WebInputEvent& event) {
+  if (input_scenario_ == InputScenario::kScroll) {
+    return;
+  }
+  if (input_scenario_ != InputScenario::kTap) {
+    input_scenario_ = InputScenario::kTap;
+    decorator_->UpdateInputScenario(frame_node_, input_scenario_,
+                                    InputScenarioUpdateReason::kTapEvent);
+  }
+  // Every tap event pushes the deadline to exit the tap scenario.
+  timer_.Start(FROM_HERE, kInactivityTimeoutForTap,
+               base::BindOnce(&InputObserver::OnInputInactiveTimer,
+                              base::Unretained(this)));
+}
+
 }  // namespace performance_manager
diff --git a/components/performance_manager/decorators/frame_input_state_decorator.h b/components/performance_manager/decorators/frame_input_state_decorator.h
index 1101569..771071e 100644
--- a/components/performance_manager/decorators/frame_input_state_decorator.h
+++ b/components/performance_manager/decorators/frame_input_state_decorator.h
@@ -28,8 +28,26 @@
     : public FrameNodeObserver,
       public GraphOwnedAndRegistered<FrameInputStateDecorator> {
  public:
+  // These values are persisted to logs. Entries should not be renumbered and
+  // numeric values should never be reused.
+  enum class InputScenarioUpdateReason {
+    kKeyEvent = 0,
+    kTapEvent = 1,
+    kScrollStartEvent = 2,
+    kScrollEndEvent = 3,
+    kTimeout = 4,
+    kNodeRemoved = 5,
+    kMaxValue = kNodeRemoved,
+  };
+
   static constexpr base::TimeDelta kInactivityTimeoutForTyping =
       base::Seconds(3);
+  static constexpr base::TimeDelta kInactivityTimeoutForTap =
+      base::Milliseconds(500);
+  // Normally all scrolls have an explicit end event. This is to avoid being
+  // incorrectly stuck in a scrolling state if the end event goes missing.
+  static constexpr base::TimeDelta kInactivityTimeoutForScroll =
+      base::Seconds(3);
 
   FrameInputStateDecorator();
   FrameInputStateDecorator(const FrameInputStateDecorator&) = delete;
@@ -44,7 +62,9 @@
   void OnPassedToGraph(Graph* graph) override;
   void OnTakenFromGraph(Graph* graph) override;
 
-  void UpdateInputScenario(const FrameNode* frame_node, bool typing);
+  void UpdateInputScenario(const FrameNode* frame_node,
+                           InputScenario input_scenario,
+                           InputScenarioUpdateReason update_reason);
 
   void AddObserver(FrameInputStateObserver* observer);
   void RemoveObserver(FrameInputStateObserver* observer);
diff --git a/components/performance_manager/decorators/frame_input_state_decorator_unittest.cc b/components/performance_manager/decorators/frame_input_state_decorator_unittest.cc
index 15ed166..43e3046 100644
--- a/components/performance_manager/decorators/frame_input_state_decorator_unittest.cc
+++ b/components/performance_manager/decorators/frame_input_state_decorator_unittest.cc
@@ -62,6 +62,42 @@
   rwh->WasHidden();
 }
 
+void SimulateTap(content::TestRenderWidgetHost* rwh) {
+  blink::WebGestureEvent gesture_tap(
+      blink::WebGestureEvent::Type::kGestureTap,
+      blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  gesture_tap.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
+  rwh->ForwardGestureEvent(gesture_tap);
+}
+
+void SimulateScrollBegin(content::TestRenderWidgetHost* rwh) {
+  blink::WebGestureEvent gesture_scroll_begin(
+      blink::WebGestureEvent::Type::kGestureScrollBegin,
+      blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  gesture_scroll_begin.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
+  rwh->ForwardGestureEvent(gesture_scroll_begin);
+}
+
+void SimulateScrollUpdate(content::TestRenderWidgetHost* rwh) {
+  blink::WebGestureEvent gesture_scroll_update(
+      blink::WebGestureEvent::Type::kGestureScrollUpdate,
+      blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  gesture_scroll_update.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
+  rwh->ForwardGestureEvent(gesture_scroll_update);
+}
+
+void SimulateScrollEnd(content::TestRenderWidgetHost* rwh) {
+  blink::WebGestureEvent gesture_scroll_end(
+      blink::WebGestureEvent::Type::kGestureScrollEnd,
+      blink::WebInputEvent::kNoModifiers,
+      blink::WebInputEvent::GetStaticTimeStampForTests());
+  gesture_scroll_end.SetSourceDevice(blink::WebGestureDevice::kTouchscreen);
+  rwh->ForwardGestureEvent(gesture_scroll_end);
+}
+
 }  // namespace
 
 class FrameInputStateDecoratorTest : public PerformanceManagerTestHarness {
@@ -116,7 +152,7 @@
       scoped_observation_{&observer_};
 };
 
-TEST_F(FrameInputStateDecoratorTest, InputEvent) {
+TEST_F(FrameInputStateDecoratorTest, TypingEvent) {
   ASSERT_TRUE(main_render_widget_host());
   ASSERT_TRUE(main_frame_node());
 
@@ -153,6 +189,95 @@
   ::testing::Mock::VerifyAndClearExpectations(&observer());
 }
 
+TEST_F(FrameInputStateDecoratorTest, TapEvent) {
+  ASSERT_TRUE(main_render_widget_host());
+  ASSERT_TRUE(main_frame_node());
+
+  // A tap immediately changes the input state to tap.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kTap>);
+  SimulateTap(main_render_widget_host());
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // Another tap before the inactivity timeout maintains the tap state.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(_)).Times(0);
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForTap / 2);
+  SimulateTap(main_render_widget_host());
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForTap / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kNoInput>);
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForTap / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+}
+
+TEST_F(FrameInputStateDecoratorTest, ScrollEvent) {
+  ASSERT_TRUE(main_render_widget_host());
+  ASSERT_TRUE(main_frame_node());
+
+  // A scroll begin immediately changes the input state to scroll.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kScroll>);
+  SimulateScrollBegin(main_render_widget_host());
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // Another scroll event before the inactivity timeout maintains the tap state.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(_)).Times(0);
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForScroll / 2);
+  SimulateScrollUpdate(main_render_widget_host());
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForScroll / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // A scroll end event immediately changes the state to no input.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kNoInput>);
+  SimulateScrollEnd(main_render_widget_host());
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+}
+
+TEST_F(FrameInputStateDecoratorTest, MixedInput) {
+  ASSERT_TRUE(main_render_widget_host());
+  ASSERT_TRUE(main_frame_node());
+
+  // Two keypresses start typing.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kTyping>);
+  SimulateKeyPress(main_render_widget_host());
+  task_environment()->FastForwardBy(base::Milliseconds(100));
+  SimulateKeyPress(main_render_widget_host());
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // A tap immediately changes the input state to tap.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kTap>);
+  SimulateTap(main_render_widget_host());
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForTap / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // A scroll begin immediately changes the input state to scroll.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kScroll>);
+  SimulateScrollBegin(main_render_widget_host());
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForScroll / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+
+  // A scroll times out - the state should go to no input despite the missing
+  // explicit scroll end event.
+  EXPECT_CALL(observer(), OnInputScenarioChanged(main_frame_node().get()))
+      .WillOnce(ExpectFrameInputScenario<InputScenario::kNoInput>);
+  task_environment()->FastForwardBy(
+      FrameInputStateDecorator::kInactivityTimeoutForScroll / 2);
+  ::testing::Mock::VerifyAndClearExpectations(&observer());
+}
+
 TEST_F(FrameInputStateDecoratorTest, FrameDestroyed) {
   ASSERT_TRUE(main_render_widget_host());
   base::WeakPtr<FrameNode> frame_node = main_frame_node();
diff --git a/components/performance_manager/scenario_api/performance_scenarios.h b/components/performance_manager/scenario_api/performance_scenarios.h
index 5757305..cb5d41f 100644
--- a/components/performance_manager/scenario_api/performance_scenarios.h
+++ b/components/performance_manager/scenario_api/performance_scenarios.h
@@ -47,12 +47,18 @@
 enum class InputScenario {
   // No input was detected.
   kNoInput = 0,
-  // The user is typing in the focused page.
+  // The user is typing in a focused page. There were no recent taps or scrolls.
   kTyping,
+  // The user tapped a focused page. There may be recent typing, but not
+  // scrolls.
+  kTap,
+  // The user is scrolling in a focused page. There may also be recent typing or
+  // taps.
+  kScroll,
 };
 using InputScenarios = base::EnumSet<InputScenario,
                                      /*Min=*/InputScenario::kNoInput,
-                                     /*Max=*/InputScenario::kTyping>;
+                                     /*Max=*/InputScenario::kScroll>;
 
 // The scope that a scenario covers.
 enum class ScenarioScope {
diff --git a/components/performance_manager/scenario_api/performance_scenarios_unittest.cc b/components/performance_manager/scenario_api/performance_scenarios_unittest.cc
index b9ceb47..e21906df 100644
--- a/components/performance_manager/scenario_api/performance_scenarios_unittest.cc
+++ b/components/performance_manager/scenario_api/performance_scenarios_unittest.cc
@@ -37,6 +37,10 @@
       return os << "NoInput";
     case InputScenario::kTyping:
       return os << "TypingInput";
+    case InputScenario::kTap:
+      return os << "Tap";
+    case InputScenario::kScroll:
+      return os << "Scroll";
   }
 }
 
@@ -168,9 +172,13 @@
                              kEmptyScenarioPattern));
   EXPECT_TRUE(ScenariosMatch(GetParam(), InputScenario::kTyping,
                              kEmptyScenarioPattern));
+  EXPECT_TRUE(
+      ScenariosMatch(GetParam(), InputScenario::kTap, kEmptyScenarioPattern));
+  EXPECT_TRUE(ScenariosMatch(GetParam(), InputScenario::kScroll,
+                             kEmptyScenarioPattern));
 }
 
-TEST_P(PerformanceScenariosAllLoadingScenariosTest, InputScenarioPattern) {
+TEST_P(PerformanceScenariosAllLoadingScenariosTest, NoInputScenarioPattern) {
   // kNoInput matches the pattern, loading scenarios are ignored.
   static ScenarioPattern kInputScenarioPattern{
       .input = {InputScenario::kNoInput},
@@ -179,6 +187,26 @@
                              kInputScenarioPattern));
   EXPECT_FALSE(ScenariosMatch(GetParam(), InputScenario::kTyping,
                               kInputScenarioPattern));
+  EXPECT_FALSE(
+      ScenariosMatch(GetParam(), InputScenario::kTap, kInputScenarioPattern));
+  EXPECT_FALSE(ScenariosMatch(GetParam(), InputScenario::kScroll,
+                              kInputScenarioPattern));
+}
+
+TEST_P(PerformanceScenariosAllLoadingScenariosTest, InputScenarioPattern) {
+  // All except kNoInput matches the pattern, loading scenarios are ignored.
+  static ScenarioPattern kInputScenarioPattern{
+      .input = {InputScenario::kTyping, InputScenario::kTap,
+                InputScenario::kScroll},
+  };
+  EXPECT_FALSE(ScenariosMatch(GetParam(), InputScenario::kNoInput,
+                              kInputScenarioPattern));
+  EXPECT_TRUE(ScenariosMatch(GetParam(), InputScenario::kTyping,
+                             kInputScenarioPattern));
+  EXPECT_TRUE(
+      ScenariosMatch(GetParam(), InputScenario::kTap, kInputScenarioPattern));
+  EXPECT_TRUE(ScenariosMatch(GetParam(), InputScenario::kScroll,
+                             kInputScenarioPattern));
 }
 
 TEST_P(PerformanceScenariosAllInputScenariosTest, LoadingScenarioPattern) {
diff --git a/components/performance_manager/scenarios/browser_performance_scenarios.cc b/components/performance_manager/scenarios/browser_performance_scenarios.cc
index 5fc7bb9..5bb3b91 100644
--- a/components/performance_manager/scenarios/browser_performance_scenarios.cc
+++ b/components/performance_manager/scenarios/browser_performance_scenarios.cc
@@ -118,15 +118,19 @@
         return 0;
       case InputScenario::kTyping:
         return 1;
+      case InputScenario::kTap:
+        return 2;
+      case InputScenario::kScroll:
+        return 3;
     }
     NOTREACHED();
   }
 
   void MaybeRecordTraceEvent(InputScenario old_scenario,
                              InputScenario new_scenario) const {
-    MaybeEmitNestingChangeEvent(state_ptr->input_tracing_track(),
-                                NestingLevel(old_scenario),
-                                NestingLevel(new_scenario), {"Typing"});
+    MaybeEmitNestingChangeEvent(
+        state_ptr->input_tracing_track(), NestingLevel(old_scenario),
+        NestingLevel(new_scenario), {"AnyInput", "TapOrScroll", "Scroll"});
   }
 
   raw_ptr<PerformanceScenarioData> state_ptr;
diff --git a/components/performance_manager/scenarios/input_scenario_observer_unittest.cc b/components/performance_manager/scenarios/input_scenario_observer_unittest.cc
index c77f078..6a45cb5 100644
--- a/components/performance_manager/scenarios/input_scenario_observer_unittest.cc
+++ b/components/performance_manager/scenarios/input_scenario_observer_unittest.cc
@@ -68,20 +68,28 @@
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kNoInput);
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kNoInput);
 
-  frame_input_state().UpdateInputScenario(mock_graph.frame.get(), true);
+  frame_input_state().UpdateInputScenario(
+      mock_graph.frame.get(), InputScenario::kTyping,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kKeyEvent);
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kTyping);
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kTyping);
 
-  frame_input_state().UpdateInputScenario(mock_graph.child_frame.get(), true);
+  frame_input_state().UpdateInputScenario(
+      mock_graph.child_frame.get(), InputScenario::kTyping,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kKeyEvent);
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kTyping);
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kTyping);
 
-  frame_input_state().UpdateInputScenario(mock_graph.frame.get(), false);
+  frame_input_state().UpdateInputScenario(
+      mock_graph.frame.get(), InputScenario::kNoInput,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kTimeout);
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kTyping);
   // Only `child_frame`, which is hosted in `other_process`, still has input.
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kNoInput);
 
-  frame_input_state().UpdateInputScenario(mock_graph.child_frame.get(), false);
+  frame_input_state().UpdateInputScenario(
+      mock_graph.child_frame.get(), InputScenario::kNoInput,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kTimeout);
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kNoInput);
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kNoInput);
 }
@@ -105,15 +113,19 @@
   EXPECT_EQ(GlobalInputScenario(), InputScenario::kNoInput);
   EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kNoInput);
 
-  frame_input_state().UpdateInputScenario(new_frame1.get(), true);
-  frame_input_state().UpdateInputScenario(new_frame2.get(), true);
-  EXPECT_EQ(GlobalInputScenario(), InputScenario::kTyping);
-  EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kTyping);
+  frame_input_state().UpdateInputScenario(
+      new_frame1.get(), InputScenario::kScroll,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kScrollStartEvent);
+  frame_input_state().UpdateInputScenario(
+      new_frame2.get(), InputScenario::kScroll,
+      FrameInputStateDecorator::InputScenarioUpdateReason::kScrollStartEvent);
+  EXPECT_EQ(GlobalInputScenario(), InputScenario::kScroll);
+  EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kScroll);
 
   // Delete a frame receiving input. Another frame is still receiving input.
   new_frame1.reset();
-  EXPECT_EQ(GlobalInputScenario(), InputScenario::kTyping);
-  EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kTyping);
+  EXPECT_EQ(GlobalInputScenario(), InputScenario::kScroll);
+  EXPECT_EQ(CurrentProcessInputScenario(), InputScenario::kScroll);
 
   // Delete the last frame receiving input.
   new_frame2.reset();
diff --git a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc
index f1dadfe..9571eca8 100644
--- a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc
+++ b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.cc
@@ -26,7 +26,9 @@
 FakeTabGroupSyncService::~FakeTabGroupSyncService() = default;
 
 void FakeTabGroupSyncService::SetTabGroupSyncDelegate(
-    std::unique_ptr<TabGroupSyncDelegate> delegate) {}
+    std::unique_ptr<TabGroupSyncDelegate> delegate) {
+  delegate_ = std::move(delegate);
+}
 
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 void FakeTabGroupSyncService::SaveGroup(SavedTabGroup group) {
diff --git a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h
index 02315ea..5013444 100644
--- a/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h
+++ b/components/saved_tab_groups/test_support/fake_tab_group_sync_service.h
@@ -124,6 +124,8 @@
   // Notifies observers when `group` is shared.
   void NotifyObserversOfTabGroupShared(SavedTabGroup& group);
 
+  std::unique_ptr<TabGroupSyncDelegate> delegate_;
+
   base::ObserverList<TabGroupSyncService::Observer> observers_;
   std::vector<SavedTabGroup> groups_;
 };
diff --git a/components/supervised_user/core/browser/supervised_user_preferences.cc b/components/supervised_user/core/browser/supervised_user_preferences.cc
index 19bc1654..fd6da30 100644
--- a/components/supervised_user/core/browser/supervised_user_preferences.cc
+++ b/components/supervised_user/core/browser/supervised_user_preferences.cc
@@ -192,11 +192,40 @@
 bool IsGoogleSafeSearchEnforced(const PrefService& pref_service) {
   return pref_service.GetBoolean(policy::policy_prefs::kForceGoogleSafeSearch);
 }
-
 void SetGoogleSafeSearch(PrefService& pref_service,
                          GoogleSafeSearchStateStatus status) {
   pref_service.SetBoolean(policy::policy_prefs::kForceGoogleSafeSearch,
                           static_cast<bool>(status));
 }
 
+namespace {
+void CheckEligibilityForContentFilters(PrefService& pref_service) {
+  CHECK(!IsSubjectToParentalControls(pref_service))
+      << "Users who are subject to Family Link parental controls cannot "
+         "disable browser content filters";
+}
+}  // namespace
+
+void EnableBrowserContentFilters(PrefService& pref_service) {
+  CheckEligibilityForContentFilters(pref_service);
+  pref_service.SetInteger(
+      policy::policy_prefs::kIncognitoModeAvailability,
+      static_cast<int>(policy::IncognitoModeAvailability::kDisabled));
+  // TODO(http://crbug.com/405419755): Enable safe sites to classify navigation.
+}
+void DisableBrowserContentFilters(PrefService& pref_service) {
+  CheckEligibilityForContentFilters(pref_service);
+  // Reset the setting to default.
+  pref_service.ClearPref(policy::policy_prefs::kIncognitoModeAvailability);
+}
+void EnableSearchContentFilters(PrefService& pref_service) {
+  CheckEligibilityForContentFilters(pref_service);
+  pref_service.SetBoolean(policy::policy_prefs::kForceGoogleSafeSearch, true);
+}
+void DisableSearchContentFilters(PrefService& pref_service) {
+  CheckEligibilityForContentFilters(pref_service);
+  // Reset the setting to default.
+  pref_service.ClearPref(policy::policy_prefs::kForceGoogleSafeSearch);
+}
+
 }  // namespace supervised_user
diff --git a/components/supervised_user/core/browser/supervised_user_preferences.h b/components/supervised_user/core/browser/supervised_user_preferences.h
index 93899c6..fe3fa78c 100644
--- a/components/supervised_user/core/browser/supervised_user_preferences.h
+++ b/components/supervised_user/core/browser/supervised_user_preferences.h
@@ -48,6 +48,14 @@
 bool IsGoogleSafeSearchEnforced(const PrefService& pref_service);
 void SetGoogleSafeSearch(PrefService& pref_service,
                          GoogleSafeSearchStateStatus status);
+
+// A set of modifiers of supervision state without associated account.
+// Changes are written to user prefs.
+void EnableBrowserContentFilters(PrefService& pref_service);
+void DisableBrowserContentFilters(PrefService& pref_service);
+void EnableSearchContentFilters(PrefService& pref_service);
+void DisableSearchContentFilters(PrefService& pref_service);
+
 }  // namespace supervised_user
 
 #endif  // COMPONENTS_SUPERVISED_USER_CORE_BROWSER_SUPERVISED_USER_PREFERENCES_H_
diff --git a/components/supervised_user/core/browser/supervised_user_service.cc b/components/supervised_user/core/browser/supervised_user_service.cc
index f5c81196..04db734 100644
--- a/components/supervised_user/core/browser/supervised_user_service.cc
+++ b/components/supervised_user/core/browser/supervised_user_service.cc
@@ -22,6 +22,7 @@
 #include "base/values.h"
 #include "base/version.h"
 #include "build/build_config.h"
+#include "components/policy/core/common/policy_pref_names.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/supervised_user/core/browser/kids_chrome_management_url_checker_client.h"
@@ -39,11 +40,13 @@
 #include "google_apis/gaia/gaia_id.h"
 #include "ui/base/l10n/l10n_util.h"
 
-using base::UserMetricsAction;
+namespace supervised_user {
 
 namespace {
+using base::UserMetricsAction;
+
 // Helper that extracts custodian data from given preferences.
-std::optional<supervised_user::Custodian> GetCustodianFromPrefs(
+std::optional<Custodian> GetCustodianFromPrefs(
     const PrefService& user_prefs,
     std::string_view email_address_pref,
     std::string_view name_pref,
@@ -58,13 +61,11 @@
       profile_image_url.empty()) {
     return std::nullopt;
   }
-  return supervised_user::Custodian((name.empty() ? email : name), email,
-                                    gaia_id, profile_image_url);
+  return Custodian((name.empty() ? email : name), email, gaia_id,
+                   profile_image_url);
 }
 }  // namespace
 
-namespace supervised_user {
-
 Custodian::Custodian(std::string_view name,
                      std::string_view email_address,
                      GaiaId obfuscated_gaia_id,
@@ -95,7 +96,12 @@
       prefs::kSupervisedUserId,
       base::BindRepeating(&SupervisedUserService::OnSupervisedUserIdChanged,
                           base::Unretained(this)));
-  SetActive(supervised_user::IsSubjectToParentalControls(user_prefs_.get()));
+  pref_change_registrar_.Add(
+      policy::policy_prefs::kIncognitoModeAvailability,
+      base::BindRepeating(
+          &SupervisedUserService::OnIncognitoModeAvailabilityChanged,
+          base::Unretained(this)));
+  SetActive(IsSubjectToParentalControls(user_prefs_.get()));
 }
 
 SupervisedUserURLFilter* SupervisedUserService::GetURLFilter() const {
@@ -250,22 +256,29 @@
 }
 
 void SupervisedUserService::OnSupervisedUserIdChanged() {
-  bool is_child =
-      supervised_user::IsSubjectToParentalControls(user_prefs_.get());
-  if (is_child) {
-    // When supervision is enabled, close any incognito windows/tabs that may
-    // be open for this profile. These windows cannot be created after the
-    // user is signed in, and closing existing ones avoids unexpected
-    // behavior due to baked-in assumptions in the SupervisedUser code.
+  SetActive(IsSubjectToParentalControls(user_prefs_.get()));
+}
+
+void SupervisedUserService::OnIncognitoModeAvailabilityChanged() {
+  // This is called in the following cases:
+  // 1) When kSupervisedUserId changes state and indicates child account, the
+  // `setings_service_`::SetActive(true) call notifies all subscribers that
+  // settings have changed. SupervisedUserPrefStore is one of these subscribers,
+  // and it unconditionally disables the incognito mode.
+  // 2) When incognito mode is explicitly disabled, regardless kSupervisedUserId
+  // status.
+  // 3) Backing policy pref is updated independently from supervised user
+  // features. Closing incognito tabs in this situation seems the right thing to
+  // do and closing incognito tabs is idempotent.
+  if (platform_delegate_->ShouldCloseIncognitoTabs()) {
     platform_delegate_->CloseIncognitoTabs();
   }
-  SetActive(is_child);
 }
 
 void SupervisedUserService::OnDefaultFilteringBehaviorChanged() {
   int behavior_value =
       user_prefs_->GetInteger(prefs::kDefaultSupervisedUserFilteringBehavior);
-  supervised_user::FilteringBehavior behavior =
+  FilteringBehavior behavior =
       SupervisedUserURLFilter::BehaviorFromInt(behavior_value);
   url_filter_->SetDefaultFilteringBehavior(behavior);
 
@@ -334,7 +347,7 @@
   }
   DCHECK(!did_shutdown_);
   did_shutdown_ = true;
-  if (supervised_user::IsSubjectToParentalControls(user_prefs_.get())) {
+  if (IsSubjectToParentalControls(user_prefs_.get())) {
     base::RecordAction(UserMetricsAction("ManagedUsers_QuitBrowser"));
   }
   SetActive(false);
diff --git a/components/supervised_user/core/browser/supervised_user_service.h b/components/supervised_user/core/browser/supervised_user_service.h
index 789e89e..9776d05 100644
--- a/components/supervised_user/core/browser/supervised_user_service.h
+++ b/components/supervised_user/core/browser/supervised_user_service.h
@@ -87,8 +87,12 @@
     // Returns the channel for the installation.
     virtual version_info::Channel GetChannel() const = 0;
 
-    // Close all incognito tabs for this service. Called the profile becomes
-    // supervised.
+    // Decides if incognito tabs should be closed. Tested when the supervision
+    // features are enabled.
+    virtual bool ShouldCloseIncognitoTabs() const = 0;
+
+    // Close all incognito tabs for this service. Called when the supervision
+    // features are enabled and require disabling of incognito mode.
     virtual void CloseIncognitoTabs() = 0;
   };
 
@@ -191,6 +195,8 @@
 
   void OnSafeSitesSettingChanged();
 
+  void OnIncognitoModeAvailabilityChanged();
+
   // Updates the manual overrides for hosts in the URL filters when the
   // corresponding preference is changed.
   void UpdateManualHosts();
diff --git a/components/supervised_user/test_support/supervised_user_url_filter_test_utils.cc b/components/supervised_user/test_support/supervised_user_url_filter_test_utils.cc
index 7610f941..7410db36 100644
--- a/components/supervised_user/test_support/supervised_user_url_filter_test_utils.cc
+++ b/components/supervised_user/test_support/supervised_user_url_filter_test_utils.cc
@@ -22,6 +22,12 @@
   return version_info::Channel::UNKNOWN;
 }
 
+// The fake should be used in supervised user context, true is a reasonable
+// return default.
+bool FakePlatformDelegate::ShouldCloseIncognitoTabs() const {
+  return true;
+}
+
 void FakePlatformDelegate::CloseIncognitoTabs() {
   return;
 }
diff --git a/components/supervised_user/test_support/supervised_user_url_filter_test_utils.h b/components/supervised_user/test_support/supervised_user_url_filter_test_utils.h
index ea6ff55..1e0dc6d 100644
--- a/components/supervised_user/test_support/supervised_user_url_filter_test_utils.h
+++ b/components/supervised_user/test_support/supervised_user_url_filter_test_utils.h
@@ -25,6 +25,7 @@
  public:
   std::string GetCountryCode() const override;
   version_info::Channel GetChannel() const override;
+  bool ShouldCloseIncognitoTabs() const override;
   void CloseIncognitoTabs() override;
 };
 
diff --git a/components/trusted_vault/BUILD.gn b/components/trusted_vault/BUILD.gn
index 49ae2ee2..c62acb32 100644
--- a/components/trusted_vault/BUILD.gn
+++ b/components/trusted_vault/BUILD.gn
@@ -85,6 +85,7 @@
     testonly = true
     sources = [
       "download_keys_response_handler_unittest.cc",
+      "physical_device_recovery_factor_unittest.cc",
       "proto_string_bytes_conversion_unittest.cc",
       "proto_time_conversion_unittest.cc",
       "recovery_key_store_connection_unittest.cc",
diff --git a/components/trusted_vault/physical_device_recovery_factor_unittest.cc b/components/trusted_vault/physical_device_recovery_factor_unittest.cc
new file mode 100644
index 0000000..68deee0f
--- /dev/null
+++ b/components/trusted_vault/physical_device_recovery_factor_unittest.cc
@@ -0,0 +1,579 @@
+// 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/trusted_vault/physical_device_recovery_factor.h"
+
+#include <optional>
+
+#include "base/functional/bind.h"
+#include "base/functional/callback_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/bind.h"
+#include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
+#include "components/signin/public/identity_manager/account_info.h"
+#include "components/trusted_vault/local_recovery_factor.h"
+#include "components/trusted_vault/proto_string_bytes_conversion.h"
+#include "components/trusted_vault/securebox.h"
+#include "components/trusted_vault/standalone_trusted_vault_storage.h"
+#include "components/trusted_vault/test/fake_file_access.h"
+#include "components/trusted_vault/test/mock_trusted_vault_throttling_connection.h"
+#include "components/trusted_vault/trusted_vault_connection.h"
+#include "components/trusted_vault/trusted_vault_histograms.h"
+#include "components/trusted_vault/trusted_vault_server_constants.h"
+#include "components/trusted_vault/trusted_vault_throttling_connection.h"
+#include "google_apis/gaia/gaia_id.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace trusted_vault {
+
+using testing::_;
+using testing::Eq;
+using testing::Mock;
+using testing::NiceMock;
+using testing::Return;
+
+namespace {
+
+const std::vector<uint8_t> kVaultKey = {1, 2, 3};
+constexpr int kLastKeyVersion = 1;
+
+MATCHER_P(MatchTrustedVaultKeyAndVersions, expected, "") {
+  const auto* trusted_vault_keys =
+      std::get_if<std::vector<TrustedVaultKeyAndVersion>>(&arg);
+  if (!trusted_vault_keys) {
+    *result_listener << "does not hold a vector of TrustedVaultKeyAndVersion";
+    return false;
+  }
+  return testing::ExplainMatchResult(*trusted_vault_keys, expected,
+                                     result_listener);
+}
+
+MATCHER_P2(TrustedVaultKeyAndVersionEq, expected_key, expected_version, "") {
+  const TrustedVaultKeyAndVersion& key_and_version = arg;
+  return key_and_version.key == expected_key &&
+         key_and_version.version == expected_version;
+}
+
+class PhysicalDeviceRecoveryFactorTest : public testing::Test {
+ public:
+  PhysicalDeviceRecoveryFactorTest() { ResetRecoveryFactor(account_info()); }
+  ~PhysicalDeviceRecoveryFactorTest() override = default;
+
+  void ResetRecoveryFactor(const std::optional<CoreAccountInfo> account_info) {
+    // Destroy `recovery_factor_`, otherwise it would hold a reference to
+    // `storage_` which is destroyed before `recovery_factor_` below.
+    recovery_factor_ = nullptr;
+
+    std::unique_ptr<FakeFileAccess> file_access =
+        std::make_unique<FakeFileAccess>();
+    if (file_access_) {
+      // We only want to reset the recovery factor, not the underlying storage.
+      file_access->SetStoredLocalTrustedVault(
+          file_access_->GetStoredLocalTrustedVault());
+    }
+    file_access_ = file_access.get();
+    storage_ =
+        StandaloneTrustedVaultStorage::CreateForTesting(std::move(file_access));
+    storage_->ReadDataFromDisk();
+    if (account_info &&
+        storage_->FindUserVault(account_info->gaia) == nullptr) {
+      storage_->AddUserVault(account_info->gaia);
+      storage_->WriteDataToDisk();
+    }
+
+    connection_ =
+        std::make_unique<NiceMock<MockTrustedVaultThrottlingConnection>>();
+
+    recovery_factor_ = std::make_unique<PhysicalDeviceRecoveryFactor>(
+        storage_.get(), account_info);
+  }
+
+  CoreAccountInfo account_info() {
+    CoreAccountInfo account_info;
+    account_info.gaia = GaiaId("user");
+    return account_info;
+  }
+
+  MockTrustedVaultThrottlingConnection* connection() {
+    return connection_.get();
+  }
+
+  StandaloneTrustedVaultStorage* storage() { return storage_.get(); }
+
+  FakeFileAccess* file_access() { return file_access_; }
+
+  PhysicalDeviceRecoveryFactor* recovery_factor() {
+    return recovery_factor_.get();
+  }
+
+  // Stores `vault_keys` in storage.
+  void StoreKeys(CoreAccountInfo account_info,
+                 const std::vector<std::vector<uint8_t>>& vault_keys,
+                 int last_vault_key_version) {
+    CHECK(!vault_keys.empty());
+    trusted_vault_pb::LocalTrustedVaultPerUser* per_user_vault =
+        storage_->FindUserVault(account_info.gaia);
+    CHECK(per_user_vault);
+    per_user_vault->set_last_vault_key_version(last_vault_key_version);
+    per_user_vault->set_keys_marked_as_stale_by_consumer(false);
+    per_user_vault->clear_vault_key();
+    for (const std::vector<uint8_t>& key : vault_keys) {
+      AssignBytesToProtoString(
+          key, per_user_vault->add_vault_key()->mutable_key_material());
+    }
+  }
+
+  // Stores `vault_keys` in storage and mimics successful device registration,
+  // returns private device key material.
+  std::vector<uint8_t> StoreKeysAndMimicDeviceRegistration(
+      CoreAccountInfo account_info,
+      const std::vector<std::vector<uint8_t>>& vault_keys,
+      int last_vault_key_version) {
+    StoreKeys(account_info, vault_keys, last_vault_key_version);
+
+    TrustedVaultConnection::RegisterAuthenticationFactorCallback
+        device_registration_callback;
+
+    EXPECT_CALL(
+        *connection(),
+        RegisterAuthenticationFactor(
+            Eq(account_info),
+            MatchTrustedVaultKeyAndVersions(GetTrustedVaultKeysWithVersions(
+                vault_keys, last_vault_key_version)),
+            _, Eq(AuthenticationFactorType(LocalPhysicalDevice())), _))
+        .WillOnce(
+            [&](const CoreAccountInfo&,
+                const MemberKeysSource& member_keys_source,
+                const SecureBoxPublicKey& device_public_key,
+                AuthenticationFactorType,
+                TrustedVaultConnection::RegisterAuthenticationFactorCallback
+                    callback) {
+              device_registration_callback = std::move(callback);
+              // Note: TrustedVaultConnection::Request doesn't support
+              // cancellation, so these tests don't cover the contract that
+              // caller should store Request object until it's completed or need
+              // to be cancelled.
+              return std::make_unique<TrustedVaultConnection::Request>();
+            });
+
+    recovery_factor_->MaybeRegister(connection(), base::DoNothing());
+    Mock::VerifyAndClearExpectations(connection());
+    EXPECT_FALSE(device_registration_callback.is_null());
+
+    // Pretend that the registration completed successfully.
+    std::move(device_registration_callback)
+        .Run(TrustedVaultRegistrationStatus::kSuccess,
+             /*key_version=*/last_vault_key_version);
+
+    std::string device_private_key_material =
+        GetDeviceRegistrationInfo(account_info)->private_key_material();
+    return std::vector<uint8_t>(device_private_key_material.begin(),
+                                device_private_key_material.end());
+  }
+
+  trusted_vault_pb::LocalDeviceRegistrationInfo* GetDeviceRegistrationInfo(
+      CoreAccountInfo account_info) {
+    trusted_vault_pb::LocalTrustedVaultPerUser* per_user_vault =
+        storage_->FindUserVault(account_info.gaia);
+    CHECK(per_user_vault);
+    return per_user_vault->mutable_local_device_registration_info();
+  }
+
+ private:
+  std::unique_ptr<StandaloneTrustedVaultStorage> storage_ = nullptr;
+  raw_ptr<FakeFileAccess> file_access_ = nullptr;
+  std::unique_ptr<NiceMock<MockTrustedVaultThrottlingConnection>> connection_ =
+      nullptr;
+  std::unique_ptr<PhysicalDeviceRecoveryFactor> recovery_factor_;
+};
+
+TEST_F(PhysicalDeviceRecoveryFactorTest, ShouldRegisterDevice) {
+  StoreKeys(account_info(), {kVaultKey}, kLastKeyVersion);
+
+  TrustedVaultConnection::RegisterAuthenticationFactorCallback
+      device_registration_callback;
+  std::vector<uint8_t> serialized_public_device_key;
+  EXPECT_CALL(
+      *connection(),
+      RegisterAuthenticationFactor(
+          Eq(account_info()),
+          MatchTrustedVaultKeyAndVersions(
+              GetTrustedVaultKeysWithVersions({kVaultKey}, kLastKeyVersion)),
+          _, Eq(AuthenticationFactorType(LocalPhysicalDevice())), _))
+      .WillOnce([&](const CoreAccountInfo&, const MemberKeysSource&,
+                    const SecureBoxPublicKey& device_public_key,
+                    AuthenticationFactorType,
+                    TrustedVaultConnection::RegisterAuthenticationFactorCallback
+                        callback) {
+        serialized_public_device_key = device_public_key.ExportToBytes();
+        device_registration_callback = std::move(callback);
+        return std::make_unique<TrustedVaultConnection::Request>();
+      });
+
+  // Register the device.
+  base::MockCallback<LocalRecoveryFactor::RegisterCallback> register_callback;
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), register_callback.Get());
+  EXPECT_EQ(status, TrustedVaultDeviceRegistrationStateForUMA::
+                        kAttemptingRegistrationWithNewKeyPair);
+  ASSERT_FALSE(device_registration_callback.is_null());
+
+  // Pretend that the registration completed successfully.
+  EXPECT_CALL(register_callback,
+              Run(TrustedVaultRegistrationStatus::kSuccess, _, _));
+  std::move(device_registration_callback)
+      .Run(TrustedVaultRegistrationStatus::kSuccess, kLastKeyVersion);
+
+  // Now the device should be registered.
+  trusted_vault_pb::LocalDeviceRegistrationInfo* registration_info =
+      GetDeviceRegistrationInfo(account_info());
+  EXPECT_TRUE(registration_info->device_registered());
+  EXPECT_TRUE(registration_info->has_private_key_material());
+
+  std::unique_ptr<SecureBoxKeyPair> key_pair =
+      SecureBoxKeyPair::CreateByPrivateKeyImport(
+          base::as_byte_span(registration_info->private_key_material()));
+  EXPECT_THAT(key_pair->public_key().ExportToBytes(),
+              Eq(serialized_public_device_key));
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest, ShouldNotRegisterIfAlreadyRegistered) {
+  std::vector<uint8_t> private_device_key = StoreKeysAndMimicDeviceRegistration(
+      account_info(), {kVaultKey}, kLastKeyVersion);
+  EXPECT_THAT(
+      GetDeviceRegistrationInfo(account_info())->device_registered_version(),
+      Eq(1));
+
+  // No registration attempt should be made, since device is already registered.
+  EXPECT_CALL(*connection(), RegisterAuthenticationFactor).Times(0);
+  EXPECT_CALL(*connection(), RegisterLocalDeviceWithoutKeys).Times(0);
+
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), base::DoNothing());
+  EXPECT_EQ(status,
+            TrustedVaultDeviceRegistrationStateForUMA::kAlreadyRegisteredV1);
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldNotRegisterAfterResetIfAlreadyRegistered) {
+  std::vector<uint8_t> private_device_key = StoreKeysAndMimicDeviceRegistration(
+      account_info(), {kVaultKey}, kLastKeyVersion);
+  ASSERT_THAT(
+      GetDeviceRegistrationInfo(account_info())->device_registered_version(),
+      Eq(1));
+
+  // Simulate restart.
+  ResetRecoveryFactor(account_info());
+
+  // No registration attempt should be made.
+  EXPECT_CALL(*connection(), RegisterAuthenticationFactor).Times(0);
+  EXPECT_CALL(*connection(), RegisterLocalDeviceWithoutKeys).Times(0);
+
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), base::DoNothing());
+  EXPECT_EQ(status,
+            TrustedVaultDeviceRegistrationStateForUMA::kAlreadyRegisteredV1);
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldHandleLocalDataObsoleteAndPersistState) {
+  StoreKeys(account_info(), {kVaultKey}, kLastKeyVersion);
+
+  TrustedVaultConnection::RegisterAuthenticationFactorCallback
+      device_registration_callback;
+  EXPECT_CALL(
+      *connection(),
+      RegisterAuthenticationFactor(
+          Eq(account_info()),
+          MatchTrustedVaultKeyAndVersions(
+              GetTrustedVaultKeysWithVersions({kVaultKey}, kLastKeyVersion)),
+          _, Eq(AuthenticationFactorType(LocalPhysicalDevice())), _))
+      .WillOnce([&](const CoreAccountInfo&,
+                    const MemberKeysSource& member_keys_source,
+                    const SecureBoxPublicKey& device_public_key,
+                    AuthenticationFactorType,
+                    TrustedVaultConnection::RegisterAuthenticationFactorCallback
+                        callback) {
+        device_registration_callback = std::move(callback);
+        return std::make_unique<TrustedVaultConnection::Request>();
+      });
+
+  // Register the device.
+  base::MockCallback<LocalRecoveryFactor::RegisterCallback> register_callback;
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), register_callback.Get());
+  EXPECT_EQ(status, TrustedVaultDeviceRegistrationStateForUMA::
+                        kAttemptingRegistrationWithNewKeyPair);
+  ASSERT_FALSE(device_registration_callback.is_null());
+
+  // Pretend that the registration failed with kLocalDataObsolete.
+  EXPECT_CALL(register_callback,
+              Run(TrustedVaultRegistrationStatus::kLocalDataObsolete, _, _));
+  std::move(device_registration_callback)
+      .Run(TrustedVaultRegistrationStatus::kLocalDataObsolete,
+           /*key_version=*/0);
+
+  // Verify persisted file state.
+  trusted_vault_pb::LocalTrustedVault proto =
+      file_access()->GetStoredLocalTrustedVault();
+  ASSERT_THAT(proto.user_size(), Eq(1));
+  // Ensure that the failure is remembered, so there are no retries. This is a
+  // regression test for crbug.com/1358015.
+  EXPECT_TRUE(proto.user(0)
+                  .local_device_registration_info()
+                  .last_registration_returned_local_data_obsolete());
+  // Additionally ensure that |local_device_registration_info| has correct
+  // state.
+  EXPECT_FALSE(
+      proto.user(0).local_device_registration_info().device_registered());
+  EXPECT_TRUE(proto.user(0)
+                  .local_device_registration_info()
+                  .has_private_key_material());
+  // Keys shouldn't be marked as stale: this is exclusively about upper layers
+  // invoking MarkLocalKeysAsStale().
+  EXPECT_FALSE(proto.user(0).keys_marked_as_stale_by_consumer());
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       MarkAsNotRegisteredShouldClearRegistrationData) {
+  // Mimic device previously registered with some keys.
+  StoreKeysAndMimicDeviceRegistration(account_info(), {kVaultKey},
+                                      kLastKeyVersion);
+
+  recovery_factor()->MarkAsNotRegistered();
+
+  // Now the device should no longer be registered.
+  trusted_vault_pb::LocalDeviceRegistrationInfo* registration_info =
+      GetDeviceRegistrationInfo(account_info());
+  EXPECT_FALSE(registration_info->device_registered());
+  EXPECT_FALSE(registration_info->has_device_registered_version());
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldNotTryToRegisterDeviceIfPreviousAttemptFailed) {
+  StoreKeys(account_info(), {kVaultKey}, kLastKeyVersion);
+  GetDeviceRegistrationInfo(account_info())
+      ->set_last_registration_returned_local_data_obsolete(true);
+
+  EXPECT_CALL(*connection(), RegisterAuthenticationFactor).Times(0);
+  EXPECT_CALL(*connection(), RegisterLocalDeviceWithoutKeys).Times(0);
+
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), base::DoNothing());
+
+  EXPECT_EQ(status,
+            TrustedVaultDeviceRegistrationStateForUMA::kLocalKeysAreStale);
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest, ShouldClearRegistrationAttemptInfo) {
+  GetDeviceRegistrationInfo(account_info())
+      ->set_last_registration_returned_local_data_obsolete(true);
+
+  recovery_factor()->ClearRegistrationAttemptInfo(account_info().gaia);
+
+  EXPECT_FALSE(GetDeviceRegistrationInfo(account_info())
+                   ->last_registration_returned_local_data_obsolete());
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldClearRegistrationAttemptInfoWithoutPrimaryAccount) {
+  ResetRecoveryFactor(std::nullopt);
+
+  GetDeviceRegistrationInfo(account_info())
+      ->set_last_registration_returned_local_data_obsolete(true);
+
+  // This should work even if the recovery factor was initialized without a
+  // primary account.
+  recovery_factor()->ClearRegistrationAttemptInfo(account_info().gaia);
+
+  EXPECT_FALSE(GetDeviceRegistrationInfo(account_info())
+                   ->last_registration_returned_local_data_obsolete());
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldNotAttemptDeviceRegistrationWhenThrottled) {
+  EXPECT_CALL(*connection(), AreRequestsThrottled).WillOnce(Return(true));
+  EXPECT_CALL(*connection(), RegisterAuthenticationFactor).Times(0);
+  EXPECT_CALL(*connection(), RegisterLocalDeviceWithoutKeys).Times(0);
+
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), base::DoNothing());
+
+  EXPECT_EQ(status,
+            TrustedVaultDeviceRegistrationStateForUMA::kThrottledClientSide);
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldNotAttemptKeyRecoveryWhenNotRegistered) {
+  base::test::SingleThreadTaskEnvironment environment;
+
+  EXPECT_CALL(*connection(), DownloadNewKeys).Times(0);
+
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryCallback>
+      recovery_callback;
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryFailureCallback>
+      recovery_failure_callback;
+  EXPECT_CALL(recovery_callback, Run).Times(0);
+  EXPECT_CALL(recovery_failure_callback,
+              Run(std::optional(
+                  TrustedVaultDownloadKeysStatusForUMA::kDeviceNotRegistered)));
+
+  base::RunLoop run_loop;
+  recovery_factor()->AttemptRecovery(
+      connection(), recovery_callback.Get(),
+      recovery_failure_callback.Get().Then(run_loop.QuitClosure()));
+  run_loop.Run();
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldNotAttemptKeyRecoveryWhenThrottled) {
+  base::test::SingleThreadTaskEnvironment environment;
+
+  // Mimic device previously registered with some keys.
+  StoreKeysAndMimicDeviceRegistration(account_info(), {kVaultKey},
+                                      kLastKeyVersion);
+
+  EXPECT_CALL(*connection(), AreRequestsThrottled).WillOnce(Return(true));
+  EXPECT_CALL(*connection(), DownloadNewKeys).Times(0);
+
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryCallback>
+      recovery_callback;
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryFailureCallback>
+      recovery_failure_callback;
+  EXPECT_CALL(recovery_callback, Run).Times(0);
+  EXPECT_CALL(recovery_failure_callback,
+              Run(std::optional(
+                  TrustedVaultDownloadKeysStatusForUMA::kThrottledClientSide)));
+
+  base::RunLoop run_loop;
+  recovery_factor()->AttemptRecovery(
+      connection(), recovery_callback.Get(),
+      recovery_failure_callback.Get().Then(run_loop.QuitClosure()));
+  run_loop.Run();
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest, ShouldDownloadNewKeys) {
+  const std::vector<std::vector<uint8_t>> kInitialVaultKeys = {{1, 2, 3}};
+  const int kInitialLastKeyVersion = 1;
+
+  // Mimic device previously registered with some key.
+  StoreKeysAndMimicDeviceRegistration(account_info(), kInitialVaultKeys,
+                                      kInitialLastKeyVersion);
+
+  TrustedVaultConnection::DownloadNewKeysCallback download_keys_callback;
+  ON_CALL(*connection(),
+          DownloadNewKeys(account_info(),
+                          TrustedVaultKeyAndVersionEq(kInitialVaultKeys.back(),
+                                                      kInitialLastKeyVersion),
+                          _, _))
+      .WillByDefault(
+          [&](const CoreAccountInfo&, const TrustedVaultKeyAndVersion&,
+              std::unique_ptr<SecureBoxKeyPair> key_pair,
+              TrustedVaultConnection::DownloadNewKeysCallback callback) {
+            download_keys_callback = std::move(callback);
+            return std::make_unique<TrustedVaultConnection::Request>();
+          });
+
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryCallback>
+      recovery_callback;
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryFailureCallback>
+      recovery_failure_callback;
+  recovery_factor()->AttemptRecovery(connection(), recovery_callback.Get(),
+                                     recovery_failure_callback.Get());
+
+  ASSERT_FALSE(download_keys_callback.is_null());
+
+  // Mimic successful key downloading, it should make fetch keys attempt
+  // completed.
+  const std::vector<std::vector<uint8_t>> kNewVaultKeys = {{1, 2, 3},
+                                                           {4, 5, 6}};
+  const int kServerLastKeyVersion = kInitialLastKeyVersion + 1;
+
+  EXPECT_CALL(recovery_callback, Run(TrustedVaultDownloadKeysStatus::kSuccess,
+                                     kNewVaultKeys, kServerLastKeyVersion));
+  EXPECT_CALL(recovery_failure_callback, Run).Times(0);
+  std::move(download_keys_callback)
+      .Run(TrustedVaultDownloadKeysStatus::kSuccess, kNewVaultKeys,
+           kServerLastKeyVersion);
+}
+
+TEST_F(PhysicalDeviceRecoveryFactorTest,
+       ShouldRegisterWithConstantKeyAndDownloadNewKeys) {
+  const int kInitialLastKeyVersion = 1;
+  // Perform pre-enrollment.
+  TrustedVaultConnection::RegisterAuthenticationFactorCallback
+      device_registration_callback;
+  std::vector<uint8_t> serialized_public_device_key;
+  EXPECT_CALL(*connection(),
+              RegisterLocalDeviceWithoutKeys(Eq(account_info()), _, _))
+      .WillOnce([&](const CoreAccountInfo& account_info,
+                    const SecureBoxPublicKey& device_public_key,
+                    TrustedVaultConnection::RegisterAuthenticationFactorCallback
+                        callback) {
+        serialized_public_device_key = device_public_key.ExportToBytes();
+        device_registration_callback = std::move(callback);
+        return std::make_unique<TrustedVaultConnection::Request>();
+      });
+
+  // Attempt device registration.
+  base::MockCallback<LocalRecoveryFactor::RegisterCallback> register_callback;
+  TrustedVaultDeviceRegistrationStateForUMA status =
+      recovery_factor()->MaybeRegister(connection(), register_callback.Get());
+  EXPECT_EQ(status, TrustedVaultDeviceRegistrationStateForUMA::
+                        kAttemptingRegistrationWithNewKeyPair);
+
+  // Mimic successful device registration and verify the state.
+  EXPECT_CALL(register_callback,
+              Run(TrustedVaultRegistrationStatus::kSuccess, _, _));
+  std::move(device_registration_callback)
+      .Run(TrustedVaultRegistrationStatus::kSuccess, kInitialLastKeyVersion);
+
+  // The logic using LocalRecoveryFactor is expected to store the pre-enrollment
+  // key. Mimic that behavior.
+  StoreKeys(account_info(), {GetConstantTrustedVaultKey()},
+            kInitialLastKeyVersion);
+
+  // Attempt recovery of new keys.
+  TrustedVaultConnection::DownloadNewKeysCallback download_keys_callback;
+  ON_CALL(*connection(), DownloadNewKeys(account_info(),
+                                         TrustedVaultKeyAndVersionEq(
+                                             GetConstantTrustedVaultKey(),
+                                             kInitialLastKeyVersion),
+                                         _, _))
+      .WillByDefault(
+          [&](const CoreAccountInfo&, const TrustedVaultKeyAndVersion&,
+              std::unique_ptr<SecureBoxKeyPair> key_pair,
+              TrustedVaultConnection::DownloadNewKeysCallback callback) {
+            download_keys_callback = std::move(callback);
+            return std::make_unique<TrustedVaultConnection::Request>();
+          });
+
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryCallback>
+      recovery_callback;
+  base::MockCallback<LocalRecoveryFactor::AttemptRecoveryFailureCallback>
+      recovery_failure_callback;
+  recovery_factor()->AttemptRecovery(connection(), recovery_callback.Get(),
+                                     recovery_failure_callback.Get());
+
+  ASSERT_FALSE(download_keys_callback.is_null());
+
+  // Mimic successful key downloading, it should make fetch keys attempt
+  // completed.
+  const std::vector<std::vector<uint8_t>> kNewVaultKeys = {
+      GetConstantTrustedVaultKey(), {4, 5, 6}};
+  const int kServerLastKeyVersion = kInitialLastKeyVersion + 1;
+
+  EXPECT_CALL(recovery_callback, Run(TrustedVaultDownloadKeysStatus::kSuccess,
+                                     kNewVaultKeys, kServerLastKeyVersion));
+  EXPECT_CALL(recovery_failure_callback, Run).Times(0);
+  std::move(download_keys_callback)
+      .Run(TrustedVaultDownloadKeysStatus::kSuccess, kNewVaultKeys,
+           kServerLastKeyVersion);
+}
+
+}  // namespace
+
+}  // namespace trusted_vault
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index f6a078d..badcc65 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -337,14 +337,13 @@
   ResourceId resource_id(104);
   gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
   gfx::Size texture_size(85, 32);
-  bool contents_premultiplied = true;
   bool nearest_neighbor = true;
   bool force_anti_aliasing_off = false;
   CREATE_SHARED_STATE();
 
   CREATE_QUAD_NEW(TileDrawQuad, visible_rect, blending, resource_id,
-                  tex_coord_rect, texture_size, contents_premultiplied,
-                  nearest_neighbor, force_anti_aliasing_off);
+                  tex_coord_rect, texture_size, nearest_neighbor,
+                  force_anti_aliasing_off);
   EXPECT_EQ(DrawQuad::Material::kTiledContent, copy_quad->material);
   EXPECT_EQ(visible_rect, copy_quad->visible_rect);
   EXPECT_EQ(blending, copy_quad->needs_blending);
@@ -354,8 +353,7 @@
   EXPECT_EQ(nearest_neighbor, copy_quad->nearest_neighbor);
 
   CREATE_QUAD_ALL(TileDrawQuad, resource_id, tex_coord_rect, texture_size,
-                  contents_premultiplied, nearest_neighbor,
-                  force_anti_aliasing_off);
+                  nearest_neighbor, force_anti_aliasing_off);
   EXPECT_EQ(DrawQuad::Material::kTiledContent, copy_quad->material);
   EXPECT_EQ(resource_id, copy_quad->resource_id);
   EXPECT_EQ(tex_coord_rect, copy_quad->tex_coord_rect);
@@ -503,14 +501,13 @@
   ResourceId resource_id(104);
   gfx::RectF tex_coord_rect(31.f, 12.f, 54.f, 20.f);
   gfx::Size texture_size(85, 32);
-  bool contents_premultiplied = true;
   bool nearest_neighbor = true;
   bool force_anti_aliasing_off = false;
 
   CREATE_SHARED_STATE();
   CREATE_QUAD_NEW(TileDrawQuad, visible_rect, needs_blending, resource_id,
-                  tex_coord_rect, texture_size, contents_premultiplied,
-                  nearest_neighbor, force_anti_aliasing_off);
+                  tex_coord_rect, texture_size, nearest_neighbor,
+                  force_anti_aliasing_off);
   EXPECT_EQ(resource_id, quad_new->resource_id);
 }
 
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index 7e6d952..e6df5c83 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -1493,8 +1493,7 @@
   draw_quad->SetAll(
       common.shared_quad_state, common.rect, common.visible_rect,
       common.needs_blending, resource_id, content_common->tex_coord_rect,
-      content_common->texture_size, content_common->is_premultiplied,
-      content_common->nearest_neighbor,
+      content_common->texture_size, content_common->nearest_neighbor,
       content_common->force_anti_aliasing_off);
   return true;
 }
diff --git a/components/viz/common/quads/render_pass_io_unittest.cc b/components/viz/common/quads/render_pass_io_unittest.cc
index b950935..a3cd2d98 100644
--- a/components/viz/common/quads/render_pass_io_unittest.cc
+++ b/components/viz/common/quads/render_pass_io_unittest.cc
@@ -275,7 +275,7 @@
       quad->SetAll(render_pass0->shared_quad_state_list.ElementAt(sqs_index),
                    gfx::Rect(0, 0, 256, 512), gfx::Rect(2, 2, 250, 500), true,
                    ResourceId(512u), gfx::RectF(0.0f, 0.0f, 0.9f, 0.8f),
-                   gfx::Size(256, 512), true, true, true);
+                   gfx::Size(256, 512), true, true);
       ++quad_count;
     }
     {
diff --git a/components/viz/common/quads/tile_draw_quad.cc b/components/viz/common/quads/tile_draw_quad.cc
index 31f78b7..6bb3898c 100644
--- a/components/viz/common/quads/tile_draw_quad.cc
+++ b/components/viz/common/quads/tile_draw_quad.cc
@@ -21,13 +21,12 @@
                           ResourceId resource,
                           const gfx::RectF& tex_coord_rect,
                           const gfx::Size& texture_size,
-                          bool is_premultiplied,
                           bool nearest_neighbor,
                           bool force_anti_aliasing_off) {
   CHECK_NE(resource, kInvalidResourceId);
   ContentDrawQuadBase::SetNew(
       shared_quad_state, DrawQuad::Material::kTiledContent, rect, visible_rect,
-      needs_blending, tex_coord_rect, texture_size, is_premultiplied,
+      needs_blending, tex_coord_rect, texture_size, /*premultiplied=*/true,
       nearest_neighbor, force_anti_aliasing_off);
   resource_id = resource;
 }
@@ -39,13 +38,12 @@
                           ResourceId resource,
                           const gfx::RectF& tex_coord_rect,
                           const gfx::Size& texture_size,
-                          bool is_premultiplied,
                           bool nearest_neighbor,
                           bool force_anti_aliasing_off) {
   CHECK_NE(resource, kInvalidResourceId);
   ContentDrawQuadBase::SetAll(
       shared_quad_state, DrawQuad::Material::kTiledContent, rect, visible_rect,
-      needs_blending, tex_coord_rect, texture_size, is_premultiplied,
+      needs_blending, tex_coord_rect, texture_size, /*premultiplied=*/true,
       nearest_neighbor, force_anti_aliasing_off);
   resource_id = resource;
 }
diff --git a/components/viz/common/quads/tile_draw_quad.h b/components/viz/common/quads/tile_draw_quad.h
index 2fd91e6..8e86a88 100644
--- a/components/viz/common/quads/tile_draw_quad.h
+++ b/components/viz/common/quads/tile_draw_quad.h
@@ -30,7 +30,6 @@
               // coordinates consistent across all quad types: crbug.com/487370
               const gfx::RectF& tex_coord_rect,
               const gfx::Size& texture_size,
-              bool is_premultiplied,
               bool nearest_neighbor,
               bool force_anti_aliasing_off);
 
@@ -44,7 +43,6 @@
               // coordinates consistent across all quad types: crbug.com/487370
               const gfx::RectF& tex_coord_rect,
               const gfx::Size& texture_size,
-              bool is_premultiplied,
               bool nearest_neighbor,
               bool force_anti_aliasing_off);
 
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index 1329dfc..720a171 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -884,7 +884,6 @@
       AggregatedRenderPass* render_pass,
       const gfx::Rect& rect) {
     bool needs_blending = false;
-    bool premultiplied_alpha = false;
     bool force_anti_aliasing_off = false;
     bool nearest_neighbor = false;
     bool is_overlay_candidate = true;
@@ -899,8 +898,7 @@
     auto* overlay_quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
     overlay_quad->SetNew(shared_quad_state, rect, rect, needs_blending,
                          resource_id, gfx::RectF(0, 0, 1, 1), rect.size(),
-                         premultiplied_alpha, nearest_neighbor,
-                         force_anti_aliasing_off);
+                         nearest_neighbor, force_anti_aliasing_off);
 
     return overlay_quad;
   }
diff --git a/components/viz/service/display/readback_pixeltest.cc b/components/viz/service/display/readback_pixeltest.cc
index 8960d98..5a878ab 100644
--- a/components/viz/service/display/readback_pixeltest.cc
+++ b/components/viz/service/display/readback_pixeltest.cc
@@ -485,7 +485,7 @@
     auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
     quad->SetNew(sqs, output_rect, output_rect, /*needs_blending=*/false,
                  mapped_resource_id, gfx::RectF(output_rect), source_size,
-                 /*is_premultiplied=*/true, /*nearest_neighbor=*/true,
+                 /*nearest_neighbor=*/true,
                  /*force_anti_aliasing_off=*/false);
     return pass;
   }
diff --git a/components/viz/service/display/renderer_perftest.cc b/components/viz/service/display/renderer_perftest.cc
index dd1d166..b7f06af 100644
--- a/components/viz/service/display/renderer_perftest.cc
+++ b/components/viz/service/display/renderer_perftest.cc
@@ -212,7 +212,6 @@
 void CreateTestTileDrawQuad(ResourceId resource_id,
                             const gfx::Rect& rect,
                             const gfx::Size& texture_size,
-                            bool premultiplied_alpha,
                             const SharedQuadState* shared_state,
                             CompositorRenderPass* render_pass) {
   // TileDrawQuads are non-normalized texture coords, so assume it's 1-1 with
@@ -223,8 +222,8 @@
   const bool force_anti_aliasing_off = false;
   auto* quad = render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   quad->SetNew(shared_state, rect, rect, needs_blending, resource_id,
-               tex_coord_rect, texture_size, premultiplied_alpha,
-               nearest_neighbor, force_anti_aliasing_off);
+               tex_coord_rect, texture_size, nearest_neighbor,
+               force_anti_aliasing_off);
 }
 
 }  // namespace
@@ -545,8 +544,7 @@
         ResourceId resource_id =
             share_resources ? resource_list_[0].id : resource_list_[i].id;
         CreateTestTileDrawQuad(resource_id, gfx::Rect(kTileSize), kTextureSize,
-                               /*premultiplied_alpha=*/false, shared_state,
-                               pass.get());
+                               shared_state, pass.get());
 
         current_transform.PostConcat(transform_step);
       }
diff --git a/components/viz/service/display/renderer_pixeltest.cc b/components/viz/service/display/renderer_pixeltest.cc
index 9de588f..1c359926 100644
--- a/components/viz/service/display/renderer_pixeltest.cc
+++ b/components/viz/service/display/renderer_pixeltest.cc
@@ -4295,7 +4295,6 @@
   auto pass = CreateTestRenderPass(id, rect, transform_to_root);
   pass->has_transparent_background = false;
 
-  bool contents_premultiplied = true;
   bool needs_blending = false;
   bool nearest_neighbor = true;
   bool force_anti_aliasing_off = true;
@@ -4308,8 +4307,7 @@
                                 gfx::MaskFilterInfo());
   TileDrawQuad* hole = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   hole->SetNew(hole_shared_state, rect, rect, needs_blending, mapped_resource,
-               gfx::RectF(gfx::Rect(tile_size)), tile_size,
-               contents_premultiplied, nearest_neighbor,
+               gfx::RectF(gfx::Rect(tile_size)), tile_size, nearest_neighbor,
                force_anti_aliasing_off);
 
   gfx::Transform green_quad_to_target_transform;
@@ -4791,7 +4789,6 @@
 // This disables filtering by setting |nearest_neighbor| on the
 // TileDrawQuad.
 TEST_P(RendererPixelTest, TileDrawQuadNearestNeighbor) {
-  constexpr bool contents_premultiplied = true;
   constexpr bool needs_blending = true;
   constexpr bool nearest_neighbor = true;
   constexpr bool force_anti_aliasing_off = false;
@@ -4840,8 +4837,7 @@
   auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   quad->SetNew(shared_state, viewport, viewport, needs_blending,
                mapped_resource, gfx::RectF(gfx::Rect(tile_size)), tile_size,
-               contents_premultiplied, nearest_neighbor,
-               force_anti_aliasing_off);
+               nearest_neighbor, force_anti_aliasing_off);
 
   AggregatedRenderPassList pass_list;
   pass_list.push_back(std::move(pass));
@@ -5334,7 +5330,6 @@
 
 TEST_P(GPURendererPixelTest, TileQuadClamping) {
   gfx::Rect viewport(this->device_viewport_size_);
-  bool contents_premultiplied = true;
   bool needs_blending = true;
   bool nearest_neighbor = false;
   bool use_aa = false;
@@ -5389,7 +5384,7 @@
   auto* quad = pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   quad->SetNew(quad_shared, gfx::Rect(layer_size), gfx::Rect(layer_size),
                needs_blending, mapped_resource, tex_coord_rect, tile_size,
-               contents_premultiplied, nearest_neighbor, use_aa);
+               nearest_neighbor, use_aa);
 
   // Green background.
   SharedQuadState* background_shared =
diff --git a/components/viz/service/display/software_renderer_unittest.cc b/components/viz/service/display/software_renderer_unittest.cc
index b165ad1..f2badb35 100644
--- a/components/viz/service/display/software_renderer_unittest.cc
+++ b/components/viz/service/display/software_renderer_unittest.cc
@@ -268,11 +268,11 @@
   auto* inner_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   inner_quad->SetNew(shared_quad_state, inner_rect, inner_rect, needs_blending,
                      mapped_resource_cyan, gfx::RectF(gfx::SizeF(inner_size)),
-                     inner_size, false, false, false);
+                     inner_size, false, false);
   auto* outer_quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   outer_quad->SetNew(shared_quad_state, outer_rect, outer_rect, needs_blending,
                      mapped_resource_yellow, gfx::RectF(gfx::SizeF(outer_size)),
-                     outer_size, false, false, false);
+                     outer_size, false, false);
 
   AggregatedRenderPassList list;
   list.push_back(std::move(root_render_pass));
@@ -328,7 +328,7 @@
   auto* quad = root_render_pass->CreateAndAppendDrawQuad<TileDrawQuad>();
   quad->SetNew(shared_quad_state, tile_rect, tile_rect, needs_blending,
                mapped_resource_cyan, gfx::RectF(gfx::SizeF(tile_size)),
-               tile_size, false, false, false);
+               tile_size, false, false);
   quad->visible_rect = visible_rect;
 
   AggregatedRenderPassList list;
diff --git a/components/viz/service/input/input_manager.cc b/components/viz/service/input/input_manager.cc
index 44e4f1d..b6b8ce6e 100644
--- a/components/viz/service/input/input_manager.cc
+++ b/components/viz/service/input/input_manager.cc
@@ -12,11 +12,8 @@
 
 #include <utility>
 
-#include "base/debug/crash_logging.h"
-#include "base/json/values_util.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_macros.h"
-#include "base/values.h"
 #include "components/viz/service/input/render_input_router_delegate_impl.h"
 #include "components/viz/service/input/render_input_router_iterator_impl.h"
 #include "components/viz/service/input/render_input_router_support_child_frame.h"
@@ -72,8 +69,7 @@
     std::unique_ptr<RenderInputRouterDelegateImpl> delegate)
     : grouping_id(grouping_id),
       rir_support(std::move(support)),
-      rir_delegate(std::move(delegate)),
-      creation_time(base::TimeTicks::Now()) {}
+      rir_delegate(std::move(delegate)) {}
 
 FrameSinkMetadata::~FrameSinkMetadata() = default;
 
@@ -276,32 +272,6 @@
   }
 }
 
-void InputManager::OnRegisteredFrameSinkHierarchy(
-    const FrameSinkId& parent_frame_sink_id,
-    const FrameSinkId& child_frame_sink_id) {
-  auto it = frame_sink_metadata_map_.find(child_frame_sink_id);
-  if (it == frame_sink_metadata_map_.end()) {
-    return;
-  }
-
-  it->second.operations.emplace_back(
-      FrameSinkMetadata::Operation::Type::kRegisterFrameSinkHierarchy,
-      parent_frame_sink_id, base::TimeTicks::Now() - it->second.creation_time);
-}
-
-void InputManager::OnUnregisteredFrameSinkHierarchy(
-    const FrameSinkId& parent_frame_sink_id,
-    const FrameSinkId& child_frame_sink_id) {
-  auto it = frame_sink_metadata_map_.find(child_frame_sink_id);
-  if (it == frame_sink_metadata_map_.end()) {
-    return;
-  }
-
-  it->second.operations.emplace_back(
-      FrameSinkMetadata::Operation::Type::kUnregisterFrameSinkHierarchy,
-      parent_frame_sink_id, base::TimeTicks::Now() - it->second.creation_time);
-}
-
 void InputManager::OnFrameSinkDeviceScaleFactorChanged(
     const FrameSinkId& frame_sink_id,
     float device_scale_factor) {
@@ -451,42 +421,6 @@
       ->StateOnOverscrollTransfer(frame_sink_id, std::move(params));
 }
 
-std::string InputManager::EmitFrameSinkOperations(
-    const FrameSinkId& frame_sink_id) {
-  auto it = frame_sink_metadata_map_.find(frame_sink_id);
-  CHECK(it != frame_sink_metadata_map_.end());
-  const FrameSinkMetadata& metadata = it->second;
-
-  base::Value::Dict frame_sink_operations = base::Value::Dict();
-  frame_sink_operations.Set("id", frame_sink_id.ToString());
-
-  FrameSinkId root_compositor_frame_sink_id =
-      GetRootCompositorFrameSinkId(frame_sink_id);
-  frame_sink_operations.Set("root_id",
-                            root_compositor_frame_sink_id.ToString());
-
-  {
-    base::Value::List operations_list = base::Value::List();
-    for (const auto& operation : metadata.operations) {
-      base::Value::Dict dict = base::Value::Dict();
-      dict.Set("operation_type", static_cast<int>(operation.type));
-      if (operation.parent_frame_sink_id.has_value()) {
-        dict.Set("parent", operation.parent_frame_sink_id->ToString());
-      }
-      dict.Set("timestamp",
-               base::TimeDeltaToValue(operation.time_since_metadata_creation));
-      operations_list.Append(std::move(dict));
-    }
-    frame_sink_operations.Set("operations", std::move(operations_list));
-  }
-
-  std::string debug_string = frame_sink_operations.DebugString();
-  if (debug_string.size() >= 1024) {
-    return "";
-  }
-  return debug_string;
-}
-
 void InputManager::StateOnTouchTransfer(
     input::mojom::TouchTransferStatePtr state) {
 #if BUILDFLAG(IS_ANDROID)
@@ -509,13 +443,7 @@
       UMA_HISTOGRAM_ENUMERATION(
           kStateProcessingResultHistogram,
           InputOnVizStateProcessingResult::kFrameSinkIdCorrespondsToChildView);
-      {
-        // TODO(404741207): Remove crash keys after investigation.
-        SCOPED_CRASH_KEY_STRING1024(
-            "crbug404741207", "frame_sink_operations",
-            EmitFrameSinkOperations(state->root_widget_frame_sink_id));
-        base::debug::DumpWithoutCrashing();
-      }
+      base::debug::DumpWithoutCrashing();
     }
   } else {
     UMA_HISTOGRAM_ENUMERATION(
@@ -638,9 +566,6 @@
         iter->second.rir_support->IsRenderInputRouterSupportChildFrame()) {
       iter->second.rir_support.reset();
       auto* rir = rir_map_.find(frame_sink_id)->second.get();
-      iter->second.operations.emplace_back(
-          FrameSinkMetadata::Operation::Type::kRecreateSupport, std::nullopt,
-          base::TimeTicks::Now() - iter->second.creation_time);
       iter->second.rir_support =
           MakeRenderInputRouterSupport(rir, frame_sink_id);
     }
diff --git a/components/viz/service/input/input_manager.h b/components/viz/service/input/input_manager.h
index 30a935b2..48c77bb2 100644
--- a/components/viz/service/input/input_manager.h
+++ b/components/viz/service/input/input_manager.h
@@ -6,7 +6,6 @@
 #define COMPONENTS_VIZ_SERVICE_INPUT_INPUT_MANAGER_H_
 
 #include <memory>
-#include <string>
 #include <vector>
 
 #include "base/containers/flat_map.h"
@@ -53,19 +52,6 @@
   base::UnguessableToken grouping_id;
   std::unique_ptr<RenderInputRouterSupportBase> rir_support;
   std::unique_ptr<RenderInputRouterDelegateImpl> rir_delegate;
-
-  struct Operation {
-    enum class Type {
-      kRecreateSupport,
-      kRegisterFrameSinkHierarchy,
-      kUnregisterFrameSinkHierarchy,
-    } type;
-    // The value is set only for (un)RegisterFrameSinkHierarchy operations.
-    std::optional<FrameSinkId> parent_frame_sink_id;
-    base::TimeDelta time_since_metadata_creation;
-  };
-  std::vector<Operation> operations;
-  base::TimeTicks creation_time;
 };
 
 class VIZ_SERVICE_EXPORT InputManager
@@ -96,12 +82,6 @@
   // FrameSinkObserver overrides.
   void OnDestroyedCompositorFrameSink(
       const FrameSinkId& frame_sink_id) override;
-  void OnRegisteredFrameSinkHierarchy(
-      const FrameSinkId& parent_frame_sink_id,
-      const FrameSinkId& child_frame_sink_id) override;
-  void OnUnregisteredFrameSinkHierarchy(
-      const FrameSinkId& parent_frame_sink_id,
-      const FrameSinkId& child_frame_sink_id) override;
   void OnFrameSinkDeviceScaleFactorChanged(const FrameSinkId& frame_sink_id,
                                            float device_scale_factor) override;
 
@@ -219,8 +199,6 @@
 
   friend class MockInputManager;
 
-  std::string EmitFrameSinkOperations(const FrameSinkId& frame_sink_id);
-
   // Keeps track of InputEventRouter corresponding to FrameSinkIds using a
   // CompositorFrameSink grouping_id sent from the browser, allowing mirroring
   // 1:1 relationship in browser between WebContentsImpl and
diff --git a/components/viz/service/layers/layer_context_impl.cc b/components/viz/service/layers/layer_context_impl.cc
index f4a9b84..d145752 100644
--- a/components/viz/service/layers/layer_context_impl.cc
+++ b/components/viz/service/layers/layer_context_impl.cc
@@ -553,8 +553,9 @@
   if (wire.resource.id == kInvalidResourceId) {
     return base::unexpected("Invalid tile resource");
   }
-  return cc::TileDisplayLayerImpl::TileResource(
-      wire.resource, wire.is_premultiplied, wire.is_checkered);
+
+  return cc::TileDisplayLayerImpl::TileResource(wire.resource,
+                                                wire.is_checkered);
 }
 
 base::expected<cc::TileDisplayLayerImpl::TileContents, std::string>
@@ -1139,12 +1140,6 @@
   compositor_sink_->DidNotProduceFrame(ack);
 }
 
-void LayerContextImpl::DidAppendQuadsWithResources(
-    const std::vector<TransferableResource>& resources) {
-  next_frame_resources_.insert(next_frame_resources_.end(), resources.begin(),
-                               resources.end());
-}
-
 void LayerContextImpl::ImportResource(TransferableResource resource) {
   auto release_callback = base::BindOnce(
       [](LayerContextImpl* impl, ResourceId id,
diff --git a/components/viz/service/layers/layer_context_impl.h b/components/viz/service/layers/layer_context_impl.h
index 045e8d0..0c2b2d3 100644
--- a/components/viz/service/layers/layer_context_impl.h
+++ b/components/viz/service/layers/layer_context_impl.h
@@ -115,8 +115,6 @@
                           cc::FrameSkippedReason reason) override;
 
   // cc::TileDisplayLayerImpl::Client:
-  void DidAppendQuadsWithResources(
-      const std::vector<TransferableResource>& resources) override;
   void ImportResource(TransferableResource resource) override;
   void DiscardResource(ResourceId resource) override;
 
@@ -138,7 +136,6 @@
   const std::unique_ptr<cc::RenderingStatsInstrumentation> rendering_stats_;
   const std::unique_ptr<cc::LayerTreeHostImpl> host_impl_;
 
-  std::vector<TransferableResource> next_frame_resources_;
   std::vector<ReturnedResource> resources_to_return_;
 
   raw_ptr<cc::LayerTreeFrameSinkClient> frame_sink_client_ = nullptr;
diff --git a/content/browser/android/battery_metrics.cc b/content/browser/android/battery_metrics.cc
index 8752955..82a5fc7e 100644
--- a/content/browser/android/battery_metrics.cc
+++ b/content/browser/android/battery_metrics.cc
@@ -68,6 +68,10 @@
       return 0;
     case InputScenario::kTyping:
       return 1;
+    case InputScenario::kTap:
+      return 2;
+    case InputScenario::kScroll:
+      return 3;
   }
   NOTREACHED();
 }
@@ -97,6 +101,10 @@
     return "UnknownInputScenario";
   }
   switch (*scenario) {
+    case InputScenario::kScroll:
+      return "Scroll";
+    case InputScenario::kTap:
+      return "Tap";
     case InputScenario::kTyping:
       return "Typing";
     case InputScenario::kNoInput:
diff --git a/content/browser/android/battery_metrics_unittest.cc b/content/browser/android/battery_metrics_unittest.cc
index 52bf483..7b71627 100644
--- a/content/browser/android/battery_metrics_unittest.cc
+++ b/content/browser/android/battery_metrics_unittest.cc
@@ -25,7 +25,7 @@
   EXPECT_EQ(tracker.GetMetricSuffix(), "NoPageLoading_NoInput");
 }
 
-TEST(PerformanceScenarioTracker, InputTypingTakesPrecedence) {
+TEST(PerformanceScenarioTracker, InputTypingTakesPrecedenceOverNoInput) {
   AndroidBatteryMetrics::PerformanceScenarioTracker tracker;
   tracker.UpdateInputScenario(InputScenario::kNoInput);
   tracker.UpdateInputScenario(InputScenario::kTyping);
@@ -33,6 +33,28 @@
   EXPECT_EQ(tracker.GetMetricSuffix(), "UnknownLoadingScenario_Typing");
 }
 
+TEST(PerformanceScenarioTracker, InputTapTakesPrecedenceOverTyping) {
+  AndroidBatteryMetrics::PerformanceScenarioTracker tracker;
+  tracker.UpdateInputScenario(InputScenario::kNoInput);
+  tracker.UpdateInputScenario(InputScenario::kTyping);
+  tracker.UpdateInputScenario(InputScenario::kTap);
+  tracker.UpdateInputScenario(InputScenario::kTyping);
+  tracker.UpdateInputScenario(InputScenario::kNoInput);
+  EXPECT_EQ(tracker.GetMetricSuffix(), "UnknownLoadingScenario_Tap");
+}
+
+TEST(PerformanceScenarioTracker, InputScrollTakesPrecedence) {
+  AndroidBatteryMetrics::PerformanceScenarioTracker tracker;
+  tracker.UpdateInputScenario(InputScenario::kNoInput);
+  tracker.UpdateInputScenario(InputScenario::kTyping);
+  tracker.UpdateInputScenario(InputScenario::kTap);
+  tracker.UpdateInputScenario(InputScenario::kScroll);
+  tracker.UpdateInputScenario(InputScenario::kTap);
+  tracker.UpdateInputScenario(InputScenario::kTyping);
+  tracker.UpdateInputScenario(InputScenario::kNoInput);
+  EXPECT_EQ(tracker.GetMetricSuffix(), "UnknownLoadingScenario_Scroll");
+}
+
 TEST(PerformanceScenarioTracker, FocusedLoadingTakesPrecedence) {
   AndroidBatteryMetrics::PerformanceScenarioTracker tracker;
   tracker.UpdateLoadingScenario(LoadingScenario::kNoPageLoading);
diff --git a/content/browser/btm/btm_database.cc b/content/browser/btm/btm_database.cc
index 06fda48..0c8d666 100644
--- a/content/browser/btm/btm_database.cc
+++ b/content/browser/btm/btm_database.cc
@@ -110,6 +110,16 @@
     DCHECK(!db_path->empty())
         << "To create an in-memory BtmDatabase, explicitly pass an "
            "std::nullopt `db_path`.";
+    if (base::PathExists(db_path.value())) {
+      if (!base::PathIsReadable(db_path.value())) {
+        DLOG(ERROR) << "The BTM SQLite database is not readable.";
+        return;
+      }
+      if (!base::PathIsWritable(db_path.value())) {
+        DLOG(ERROR) << "The BTM SQLite database is not writable.";
+        return;
+      }
+    }
   }
 
   if (Init() != sql::INIT_OK) {
@@ -127,12 +137,13 @@
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   sql::UmaHistogramSqliteResult("Privacy.DIPS.DatabaseErrors", extended_error);
 
-  if (sql::IsErrorCatastrophic(extended_error)) {
+  if (sql::IsErrorCatastrophic(extended_error) && db_->is_open()) {
     // Normally this will poison the database, causing any subsequent operations
     // to silently fail without any side effects. However, if RazeAndPoison() is
     // called from the error callback in response to an error raised from within
     // sql::Database::Open, opening the now-razed database will be retried.
     db_->RazeAndPoison();
+    return;
   }
 
   // The default handling is to assert on debug and to ignore on release.
diff --git a/content/browser/loader/navigation_url_loader_impl_unittest.cc b/content/browser/loader/navigation_url_loader_impl_unittest.cc
index b9d7c66..fec429a 100644
--- a/content/browser/loader/navigation_url_loader_impl_unittest.cc
+++ b/content/browser/loader/navigation_url_loader_impl_unittest.cc
@@ -46,6 +46,7 @@
 #include "ppapi/buildflags/buildflags.h"
 #include "services/metrics/public/cpp/ukm_builders.h"
 #include "services/network/public/cpp/cors/origin_access_list.h"
+#include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/permissions_policy/permissions_policy.h"
 #include "services/network/public/cpp/single_request_url_loader_factory.h"
 #include "services/network/public/cpp/url_loader_completion_status.h"
@@ -127,11 +128,18 @@
         /*trust_token_helper=*/nullptr,
         /*shared_dictionary_manager=*/nullptr,
         /*shared_dictionary_checker=*/nullptr,
-        /*cookie_observer=*/mojo::NullRemote(),
-        /*trust_token_observer=*/mojo::NullRemote(),
-        /*url_loader_network_observer=*/mojo::NullRemote(),
-        /*devtools_observer=*/mojo::NullRemote(),
-        /*device_bound_session_observer=*/mojo::NullRemote(),
+        /*cookie_observer=*/
+        network::ObserverWrapper<network::mojom::CookieAccessObserver>(),
+        /*trust_token_observer=*/
+        network::ObserverWrapper<network::mojom::TrustTokenAccessObserver>(),
+        /*url_loader_network_observer=*/
+        network::ObserverWrapper<
+            network::mojom::URLLoaderNetworkServiceObserver>(),
+        /*devtools_observer=*/
+        network::ObserverWrapper<network::mojom::DevToolsObserver>(),
+        /*device_bound_session_observer=*/
+        network::ObserverWrapper<
+            network::mojom::DeviceBoundSessionAccessObserver>(),
         /*accept_ch_frame_observer=*/mojo::NullRemote(),
         /*shared_storage_writable=*/false);
   }
diff --git a/content/browser/renderer_host/media/video_capture_controller.cc b/content/browser/renderer_host/media/video_capture_controller.cc
index cd963f5..1e8a512 100644
--- a/content/browser/renderer_host/media/video_capture_controller.cc
+++ b/content/browser/renderer_host/media/video_capture_controller.cc
@@ -14,7 +14,7 @@
 #include "base/command_line.h"
 #include "base/containers/contains.h"
 #include "base/functional/bind.h"
-#include "base/functional/callback_forward.h"
+#include "base/functional/callback.h"
 #include "base/memory/raw_ptr.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -33,7 +33,7 @@
 #include "media/capture/video/video_capture_buffer_tracker_factory_impl.h"
 #include "media/capture/video/video_capture_device_client.h"
 #include "media/capture/video/video_capture_metrics.h"
-#include "services/video_effects/public/mojom/video_effects_processor.mojom-forward.h"
+#include "services/video_effects/public/mojom/video_effects_processor.mojom.h"
 
 #if !BUILDFLAG(IS_ANDROID)
 #include "content/browser/compositor/image_transport_factory.h"
@@ -201,7 +201,6 @@
       device_launcher_(std::move(device_launcher)),
       emit_log_message_cb_(std::move(emit_log_message_cb)),
       device_launch_observer_(nullptr),
-      state_(blink::VIDEO_CAPTURE_STATE_STARTING),
       has_received_frames_(false) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 }
@@ -255,7 +254,7 @@
   }
 
   // Signal error in case device is already in error state.
-  if (state_ == blink::VIDEO_CAPTURE_STATE_ERROR) {
+  if (state_ == State::kError) {
     event_handler->OnError(
         id,
         media::VideoCaptureError::kVideoCaptureControllerIsAlreadyInErrorState);
@@ -267,16 +266,15 @@
     return;
 
   // If the device has reported OnStarted event, report it to this client here.
-  if (state_ == blink::VIDEO_CAPTURE_STATE_STARTED)
+  if (state_ == State::kStarted) {
     event_handler->OnStarted(id);
+  }
 
   std::unique_ptr<ControllerClient> client =
       std::make_unique<ControllerClient>(id, event_handler, session_id, params);
   // If we already have gotten frame_info from the device, repeat it to the new
   // client.
-  if (state_ != blink::VIDEO_CAPTURE_STATE_ERROR) {
-    controller_clients_.push_back(std::move(client));
-  }
+  controller_clients_.push_back(std::move(client));
 }
 
 base::UnguessableToken VideoCaptureController::RemoveClient(
@@ -444,7 +442,7 @@
       frame.buffer_id, frame.frame_feedback_id, std::move(frame.frame_info),
       &frame_context);
 
-  if (state_ != blink::VIDEO_CAPTURE_STATE_ERROR) {
+  if (state_ != State::kError) {
     // Inform all active clients of the frames.
     for (const auto& client : controller_clients_) {
       if (client->session_closed || client->paused)
@@ -551,7 +549,7 @@
 
 void VideoCaptureController::OnError(media::VideoCaptureError error) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
-  state_ = blink::VIDEO_CAPTURE_STATE_ERROR;
+  state_ = State::kError;
   PerformForClientsWithOpenSession(base::BindRepeating(&CallOnError, error));
 }
 
@@ -601,7 +599,7 @@
 void VideoCaptureController::OnStarted() {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
   EmitLogMessage(__func__, 3);
-  state_ = blink::VIDEO_CAPTURE_STATE_STARTED;
+  state_ = State::kStarted;
   PerformForClientsWithOpenSession(base::BindRepeating(&CallOnStarted));
 }
 
diff --git a/content/browser/renderer_host/media/video_capture_controller.h b/content/browser/renderer_host/media/video_capture_controller.h
index d852501e9..0fd033a 100644
--- a/content/browser/renderer_host/media/video_capture_controller.h
+++ b/content/browser/renderer_host/media/video_capture_controller.h
@@ -20,13 +20,11 @@
 #include "content/browser/renderer_host/media/video_capture_provider.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/video_capture_device_launcher.h"
-#include "media/capture/mojom/video_capture.mojom.h"
-#include "media/capture/mojom/video_capture_types.mojom.h"
+#include "media/capture/mojom/video_capture_types.mojom-forward.h"
 #include "media/capture/video/video_frame_receiver.h"
 #include "media/capture/video_capture_types.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "services/video_effects/public/mojom/video_effects_processor.mojom-forward.h"
-#include "third_party/blink/public/common/media/video_capture.h"
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 
 namespace content {
@@ -224,6 +222,9 @@
         buffer_read_permission_;
   };
 
+  // `kError` is an absorbing state which stops the flow of data to clients.
+  enum class State { kStarting, kStarted, kError };
+
   ~VideoCaptureController() override;
 
   // Find a client of |id| and |handler| in |clients|.
@@ -278,9 +279,7 @@
   // All clients served by this controller.
   ControllerClients controller_clients_;
 
-  // Takes on only the states 'STARTING', 'STARTED' and 'ERROR'. 'ERROR' is an
-  // absorbing state which stops the flow of data to clients.
-  blink::VideoCaptureState state_;
+  State state_ = State::kStarting;
 
   int next_buffer_context_id_ = 0;
 
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index fbbd83a2f..14347ab 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -6940,6 +6940,8 @@
   if (response_head_->load_timing_internal_info) {
     navigation_handle_timing_.create_stream_delay =
         response_head_->load_timing_internal_info->create_stream_delay;
+    navigation_handle_timing_.connected_callback_delay =
+        response_head_->load_timing_internal_info->connected_callback_delay;
     navigation_handle_timing_.initialize_stream_delay =
         response_head_->load_timing_internal_info->initialize_stream_delay;
     // Reset `load_timing_internal_info` to make sure that isn't exposed.
diff --git a/content/public/browser/navigation_handle_timing.h b/content/public/browser/navigation_handle_timing.h
index 58d13c9..b2c771161 100644
--- a/content/public/browser/navigation_handle_timing.h
+++ b/content/public/browser/navigation_handle_timing.h
@@ -145,6 +145,9 @@
   // CreateStream related delay information.
   base::TimeDelta create_stream_delay;
 
+  // HttpNetwork::Transaction connected callback delay information.
+  base::TimeDelta connected_callback_delay;
+
   // InitializeStream related delay information.
   base::TimeDelta initialize_stream_delay;
 };
diff --git a/docs/website b/docs/website
index 911ac9b..dc80f90 160000
--- a/docs/website
+++ b/docs/website
@@ -1 +1 @@
-Subproject commit 911ac9ba06c70163c0feff9dfe9d5829dda94b83
+Subproject commit dc80f907bac0c93c587629f0a8d56b20a9575f4d
diff --git a/extensions/browser/api/web_request/web_request_api.cc b/extensions/browser/api/web_request/web_request_api.cc
index 3a99635c..9cf1f20 100644
--- a/extensions/browser/api/web_request/web_request_api.cc
+++ b/extensions/browser/api/web_request/web_request_api.cc
@@ -93,7 +93,9 @@
 
 namespace {
 
-WebRequestAPI::TestObserver* g_test_observer = nullptr;
+BASE_FEATURE(kDeferResetURLLoaderFactories,
+             "DeferResetURLLoaderFactories",
+             base::FEATURE_ENABLED_BY_DEFAULT);
 
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
@@ -342,8 +344,7 @@
   // We only have to observe ServiceWorkerTaskQueue and react to
   // `OnAllRegistrationsStored` if we need to defer calls to
   // `ResetURLLoaderFactories` to after registration storage.
-  if (base::FeatureList::IsEnabled(
-          extensions_features::kDeferResetURLLoaderFactories)) {
+  if (base::FeatureList::IsEnabled(kDeferResetURLLoaderFactories)) {
     service_worker_task_queue_observation_.Observe(
         ServiceWorkerTaskQueue::Get(browser_context_));
   }
@@ -372,15 +373,6 @@
   return g_factory.Pointer();
 }
 
-// static
-void WebRequestAPI::SetObserverForTest(TestObserver* observer) {
-  g_test_observer = observer;
-}
-
-WebRequestAPI::TestObserver::TestObserver() = default;
-
-WebRequestAPI::TestObserver::~TestObserver() = default;
-
 void WebRequestAPI::OnListenerRemoved(const EventListenerInfo& details) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
@@ -723,18 +715,10 @@
       ->HasAnyExtraHeadersListener(browser_context_);
 }
 
-void WebRequestAPI::ResetURLLoaderFactories() {
-  browser_context_->GetDefaultStoragePartition()->ResetURLLoaderFactories();
-  if (g_test_observer) {
-    g_test_observer->OnDidResetURLLoaderFactories();
-  }
-}
-
 void WebRequestAPI::UpdateMayHaveProxies() {
   bool may_have_proxies = MayHaveProxies();
   if (!may_have_proxies_ && may_have_proxies) {
-    if (base::FeatureList::IsEnabled(
-            extensions_features::kDeferResetURLLoaderFactories) &&
+    if (base::FeatureList::IsEnabled(kDeferResetURLLoaderFactories) &&
         has_pending_worker_registrations_) {
       // If any service worker registration is still in flight (started, but not
       // stored), it's not safe to call `ResetURLLoaderFactories`, since it
@@ -747,7 +731,7 @@
       // can be reset safely.
     } else {
       // Otherwise, we can safely call it now.
-      ResetURLLoaderFactories();
+      browser_context_->GetDefaultStoragePartition()->ResetURLLoaderFactories();
     }
   }
   may_have_proxies_ = may_have_proxies;
@@ -777,7 +761,7 @@
   service_worker_context_observation_.RemoveAllObservations();
   // ...and reset the URLLoaderFactories if we haven't done it already.
   if (deferred_reset_url_loader_factories_) {
-    ResetURLLoaderFactories();
+    browser_context_->GetDefaultStoragePartition()->ResetURLLoaderFactories();
     deferred_reset_url_loader_factories_ = false;
   }
 }
diff --git a/extensions/browser/api/web_request/web_request_api.h b/extensions/browser/api/web_request/web_request_api.h
index a8fc099e..2e166f51 100644
--- a/extensions/browser/api/web_request/web_request_api.h
+++ b/extensions/browser/api/web_request/web_request_api.h
@@ -199,19 +199,6 @@
   static BrowserContextKeyedAPIFactory<WebRequestAPI>* GetFactoryInstance();
   void Shutdown() override;
 
-  class TestObserver {
-   public:
-    TestObserver();
-    TestObserver(const TestObserver&) = delete;
-    TestObserver& operator=(const TestObserver&) = delete;
-    virtual ~TestObserver();
-
-    // Called when `ResetURLLoaderFactories()` has been performed.
-    virtual void OnDidResetURLLoaderFactories() {}
-  };
-
-  static void SetObserverForTest(TestObserver* observer);
-
   // EventRouter::Observer overrides:
   void OnListenerRemoved(const EventListenerInfo& details) override;
 
@@ -321,8 +308,6 @@
   // URLLoaderFactories if so.
   void UpdateMayHaveProxies();
 
-  void ResetURLLoaderFactories();
-
   // ExtensionRegistryObserver implementation.
   void OnExtensionLoaded(content::BrowserContext* browser_context,
                          const Extension* extension) override;
diff --git a/extensions/browser/service_worker/service_worker_task_queue.cc b/extensions/browser/service_worker/service_worker_task_queue.cc
index 721c2af..13b8a795 100644
--- a/extensions/browser/service_worker/service_worker_task_queue.cc
+++ b/extensions/browser/service_worker/service_worker_task_queue.cc
@@ -732,10 +732,6 @@
   const bool success = IsWorkerRegistrationSuccess(status_code);
   base::UmaHistogramBoolean(
       "Extensions.ServiceWorkerBackground.WorkerRegistrationState2", success);
-  if (!success && g_test_observer) {
-    g_test_observer->OnWorkerRegistrationFailed(context_id.extension_id,
-                                                status_code);
-  }
 
   ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
   const ExtensionId& extension_id = context_id.extension_id;
diff --git a/extensions/browser/service_worker/service_worker_task_queue.h b/extensions/browser/service_worker/service_worker_task_queue.h
index 4271b2eb..ca8fe59 100644
--- a/extensions/browser/service_worker/service_worker_task_queue.h
+++ b/extensions/browser/service_worker/service_worker_task_queue.h
@@ -348,10 +348,6 @@
     // it ultimately succeeds or fails).
     virtual void RequestedWorkerStart(const ExtensionId& extension_id) {}
 
-    virtual void OnWorkerRegistrationFailed(
-        const ExtensionId& extension_id,
-        blink::ServiceWorkerStatusCode status_code) {}
-
     virtual void DidStartWorkerFail(
         const ExtensionId& extension_id,
         size_t num_pending_tasks,
diff --git a/extensions/browser/service_worker/service_worker_test_utils.cc b/extensions/browser/service_worker/service_worker_test_utils.cc
index 20e3010..9a5522c 100644
--- a/extensions/browser/service_worker/service_worker_test_utils.cc
+++ b/extensions/browser/service_worker/service_worker_test_utils.cc
@@ -12,7 +12,6 @@
 #include "content/public/browser/storage_partition.h"
 #include "extensions/common/constants.h"
 #include "extensions/common/extension.h"
-#include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h"
 
 namespace extensions {
@@ -46,7 +45,6 @@
     : extension_scope_(GetScopeForExtensionID(std::move(extension_id))),
       context_(context) {
   scoped_observation_.Observe(context_);
-  scoped_sync_observation_.Observe(context_);
 }
 
 TestServiceWorkerContextObserver::TestServiceWorkerContextObserver(
@@ -55,7 +53,6 @@
     : extension_scope_(GetScopeForExtensionID(std::move(extension_id))),
       context_(GetServiceWorkerContext(browser_context)) {
   scoped_observation_.Observe(context_);
-  scoped_sync_observation_.Observe(context_);
 }
 
 TestServiceWorkerContextObserver::~TestServiceWorkerContextObserver() = default;
@@ -65,26 +62,13 @@
     return;
   }
 
-  SCOPED_TRACE("Waiting for worker registration to be stored");
   base::RunLoop run_loop;
   stored_quit_closure_ = run_loop.QuitClosure();
   run_loop.Run();
 }
 
-int64_t TestServiceWorkerContextObserver::WaitForStartWorkerMessageSent() {
-  if (!start_message_sent_version_id_) {
-    SCOPED_TRACE("Waiting for StartWorker message to be sent");
-    base::RunLoop run_loop;
-    start_message_sent_quit_closure_ = run_loop.QuitClosure();
-    run_loop.Run();
-  }
-
-  return *start_message_sent_version_id_;
-}
-
 int64_t TestServiceWorkerContextObserver::WaitForWorkerStarted() {
   if (!running_version_id_) {
-    SCOPED_TRACE("Waiting for worker to be started");
     base::RunLoop run_loop;
     started_quit_closure_ = run_loop.QuitClosure();
     run_loop.Run();
@@ -100,7 +84,6 @@
     return *stopped_version_id_;
   }
 
-  SCOPED_TRACE("Waiting for worker to be stopped");
   base::RunLoop run_loop;
   stopped_quit_closure_ = run_loop.QuitClosure();
   run_loop.Run();
@@ -110,7 +93,6 @@
 
 int64_t TestServiceWorkerContextObserver::WaitForWorkerActivated() {
   if (!activated_version_id_) {
-    SCOPED_TRACE("Waiting for worker to be activated");
     base::RunLoop run_loop;
     activated_quit_closure_ = run_loop.QuitClosure();
     run_loop.Run();
@@ -141,19 +123,6 @@
   }
 }
 
-void TestServiceWorkerContextObserver::OnStartWorkerMessageSent(
-    int64_t version_id,
-    const GURL& scope) {
-  if (extension_scope_ && extension_scope_ != scope) {
-    return;
-  }
-
-  start_message_sent_version_id_ = version_id;
-  if (start_message_sent_quit_closure_) {
-    std::move(start_message_sent_quit_closure_).Run();
-  }
-}
-
 void TestServiceWorkerContextObserver::OnVersionStartedRunning(
     int64_t version_id,
     const content::ServiceWorkerRunningInfo& running_info) {
@@ -192,7 +161,6 @@
 void TestServiceWorkerContextObserver::OnDestruct(
     content::ServiceWorkerContext* context) {
   scoped_observation_.Reset();
-  scoped_sync_observation_.Reset();
   context_ = nullptr;
 }
 
diff --git a/extensions/browser/service_worker/service_worker_test_utils.h b/extensions/browser/service_worker/service_worker_test_utils.h
index e272ccd0..2a99600 100644
--- a/extensions/browser/service_worker/service_worker_test_utils.h
+++ b/extensions/browser/service_worker/service_worker_test_utils.h
@@ -39,8 +39,7 @@
 // Note: This class only works well when there is a *single* service worker
 // being registered. We could extend this to track multiple workers.
 class TestServiceWorkerContextObserver
-    : public content::ServiceWorkerContextObserver,
-      public content::ServiceWorkerContextObserverSynchronous {
+    : public content::ServiceWorkerContextObserver {
  public:
   explicit TestServiceWorkerContextObserver(
       content::ServiceWorkerContext* context,
@@ -59,11 +58,6 @@
   // scope to be stored.
   void WaitForRegistrationStored();
 
-  // Wait for OnStartWorkerMessageSent event is triggered, so that the observer
-  // captures the version ID of the service worker that is about to be started.
-  // Returns the version ID.
-  int64_t WaitForStartWorkerMessageSent();
-
   // Wait for OnVersionStartedRunning event is triggered, so that the observer
   // captures the running service worker version ID. Returns the version ID.
   int64_t WaitForWorkerStarted();
@@ -95,9 +89,6 @@
   void OnVersionActivated(int64_t version_id, const GURL& scope) override;
   void OnDestruct(content::ServiceWorkerContext* context) override;
 
-  // ServiceWorkerContextObserverSynchronous:
-  void OnStartWorkerMessageSent(int64_t version_id, const GURL& scope) override;
-
   using RegistrationsMap = std::map<GURL, int>;
 
   RegistrationsMap registrations_completed_map_;
@@ -105,7 +96,6 @@
   // Multiple events may come in so we must wait for the specific event
   // to be triggered.
   base::OnceClosure activated_quit_closure_;
-  base::OnceClosure start_message_sent_quit_closure_;
   base::OnceClosure started_quit_closure_;
   base::OnceClosure stored_quit_closure_;
   base::OnceClosure stopped_quit_closure_;
@@ -114,7 +104,6 @@
 
   std::optional<bool> registration_stored_;
   std::optional<int64_t> activated_version_id_;
-  std::optional<int64_t> start_message_sent_version_id_;
   std::optional<int64_t> running_version_id_;
   std::optional<int64_t> stopped_version_id_;
 
@@ -123,10 +112,6 @@
   base::ScopedObservation<content::ServiceWorkerContext,
                           content::ServiceWorkerContextObserver>
       scoped_observation_{this};
-
-  base::ScopedObservation<content::ServiceWorkerContext,
-                          content::ServiceWorkerContextObserverSynchronous>
-      scoped_sync_observation_{this};
 };
 
 // Observes ProcessManager::UnregisterServiceWorker.
diff --git a/extensions/common/extension_features.cc b/extensions/common/extension_features.cc
index d1b5903..3316395e 100644
--- a/extensions/common/extension_features.cc
+++ b/extensions/common/extension_features.cc
@@ -64,10 +64,6 @@
              "EMF_NO_EXTENSION_ID_FOR_EXTENSION_SOURCE",
              base::FEATURE_ENABLED_BY_DEFAULT);
 
-BASE_FEATURE(kDeferResetURLLoaderFactories,
-             "DeferResetURLLoaderFactories",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 BASE_FEATURE(kEnableWebHidInWebView,
              "EnableWebHidInWebView",
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/extensions/common/extension_features.h b/extensions/common/extension_features.h
index a57edbd..30db8ea 100644
--- a/extensions/common/extension_features.h
+++ b/extensions/common/extension_features.h
@@ -85,11 +85,6 @@
 // extension).
 BASE_DECLARE_FEATURE(kCheckingNoExtensionIdInExtensionIpcs);
 
-// If enabled, defers the execution of WebRequestAPI call of
-// `ResetURLLoaderFactories()` to when there's no extension service worker
-// registrations in flight, to avoid disrupting the worker(s) registration(s).
-BASE_DECLARE_FEATURE(kDeferResetURLLoaderFactories);
-
 // If enabled, <webview>s will be allowed to request permission from an
 // embedding Chrome App to request access to Human Interface Devices.
 BASE_DECLARE_FEATURE(kEnableWebHidInWebView);
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt
index e7a47da3..9bed93a 100644
--- a/infra/inclusive_language_presubmit_exempt_dirs.txt
+++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -106,7 +106,6 @@
 chrome/test/data/third_party/kraken/tests/kraken-1.1 20 4
 chrome/test/data/third_party/spaceport 1 1
 chrome/test/data/updater 2 1
-chrome/test/data/variations/http_server 1 1
 chrome/test/data/webui 1 1
 chrome/test/data/webui/chromeos 1 1
 chrome/updater/win 1 1
@@ -209,7 +208,7 @@
 extensions/shell/common 1 1
 google_apis/gaia 1 1
 gpu/config 1 1
-infra 4 2
+infra 5 3
 infra/config/generated/luci 1 1
 infra/config/generators 2 1
 infra/config/gn_args 1 1
diff --git a/internal b/internal
index 3f05162..03be48c 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 3f05162719c305d3e7dcf93800c67fa5b4a295ee
+Subproject commit 03be48c96a22a496b50d3709c2749424c56c4300
diff --git a/ios/chrome/app/perf_tests_hook.mm b/ios/chrome/app/perf_tests_hook.mm
index c2ab61b0..0b7a5bfc 100644
--- a/ios/chrome/app/perf_tests_hook.mm
+++ b/ios/chrome/app/perf_tests_hook.mm
@@ -88,7 +88,8 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service) {
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service) {
   return nullptr;
 }
 std::unique_ptr<password_manager::BulkLeakCheckServiceInterface>
diff --git a/ios/chrome/app/tests_fake_hook.mm b/ios/chrome/app/tests_fake_hook.mm
index b4c259e6..f8d0410 100644
--- a/ios/chrome/app/tests_fake_hook.mm
+++ b/ios/chrome/app/tests_fake_hook.mm
@@ -72,7 +72,8 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service) {
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service) {
   return nullptr;
 }
 std::unique_ptr<password_manager::BulkLeakCheckServiceInterface>
diff --git a/ios/chrome/app/tests_hook.h b/ios/chrome/app/tests_hook.h
index 31eb774..143bf68 100644
--- a/ios/chrome/app/tests_hook.h
+++ b/ios/chrome/app/tests_hook.h
@@ -14,6 +14,7 @@
 class ProfileOAuth2TokenService;
 class ShareKitService;
 class SystemIdentityManager;
+class TabGroupService;
 class TrustedVaultClientBackend;
 
 namespace base {
@@ -149,7 +150,8 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service);
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service);
 
 // Returns a bulk leak check service that should be used when testing. The real
 // factory will be used if this hook returns a nullptr.
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS
index 81bf915..9b79d4d4 100644
--- a/ios/chrome/browser/DEPS
+++ b/ios/chrome/browser/DEPS
@@ -176,6 +176,7 @@
   "-ios/chrome/browser",
   "+ios/chrome/browser/profile/model",
   "+ios/chrome/browser/default_browser/model",
+  "+ios/chrome/browser/policy/model",
 
   # Shared dependencies.
   "+ios/chrome/browser/shared/coordinator",
diff --git a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
index 3bcb1e0..23260a3 100644
--- a/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/authentication_flow/authentication_flow_unittest.mm
@@ -243,11 +243,12 @@
                              /*shouldHandOverToFlowInProfile=*/YES);
 
     NSString* hosted_domain = GetHostedDomainFromEmail(identity.userEmail);
+    auto fetchManagedStatusCallback = ^(NSInvocation*) {
+      [authentication_flow_ didFetchManagedStatus:hosted_domain];
+    };
     OCMExpect([performer_mock_ fetchManagedStatus:personal_profile_.get()
                                       forIdentity:identity])
-        .andDo(^(NSInvocation*) {
-          [authentication_flow_ didFetchManagedStatus:hosted_domain];
-        });
+        .andDo(fetchManagedStatusCallback);
 
     ProfileIOS* final_profile = personal_profile_;
     Browser* final_browser = personal_browser_.get();
@@ -263,16 +264,21 @@
 
     if (hosted_domain.length) {
       if (AreSeparateProfilesForManagedAccountsEnabled()) {
+        auto fetchProfileSeparationPoliciesCallback = ^(NSInvocation*) {
+          [authentication_flow_
+              didFetchProfileSeparationPolicies:policy::ALWAYS_SEPARATE];
+        };
         OCMStub([performer_mock_
                     fetchProfileSeparationPolicies:personal_profile_.get()
                                        forIdentity:identity])
-            .andDo(^(NSInvocation*) {
-              [authentication_flow_
-                  didFetchProfileSeparationPolicies:policy::ALWAYS_SEPARATE];
-            });
+            .andDo(fetchProfileSeparationPoliciesCallback);
       }
 
       BOOL migrationDisabled = AreSeparateProfilesForManagedAccountsEnabled();
+      auto showManagedConfirmationForHostedDomainCallback = ^(NSInvocation*) {
+        managed_confirmation_dialog_shown_count_++;
+        [authentication_flow_ didAcceptManagedConfirmation:YES];
+      };
       OCMStub([performer_mock_
                   showManagedConfirmationForHostedDomain:hosted_domain
                                                 identity:identity
@@ -281,40 +287,38 @@
                                skipBrowsingDataMigration:migrationDisabled
                               mergeBrowsingDataByDefault:NO
                    browsingDataMigrationDisabledByPolicy:migrationDisabled])
-          .andDo(^(NSInvocation*) {
-            managed_confirmation_dialog_shown_count_++;
-            [authentication_flow_ didAcceptManagedConfirmation:YES];
-          });
+          .andDo(showManagedConfirmationForHostedDomainCallback);
 
       if (AreSeparateProfilesForManagedAccountsEnabled()) {
+        auto switchToProfileWithIdentityCallback = ^(NSInvocation*) {
+          [authentication_flow_
+              didSwitchToProfileWithNewProfileBrowser:final_browser];
+        };
         OCMExpect(
             [performer_mock_
                 switchToProfileWithIdentity:identity
                                  sceneState:personal_browser_->GetSceneState()])
-            .andDo(^(NSInvocation*) {
-              [authentication_flow_
-                  didSwitchToProfileWithNewProfileBrowser:final_browser];
-            });
+            .andDo(switchToProfileWithIdentityCallback);
       }
 
+      auto registerUserPolicyCallback = ^(NSInvocation*) {
+        [authentication_flow_in_profile_
+            didRegisterForUserPolicyWithDMToken:kFakeDMToken
+                                       clientID:kFakeClientID
+                             userAffiliationIDs:@[ kFakeUserAffiliationID ]];
+      };
       OCMExpect([performer_mock_ registerUserPolicy:final_profile
                                         forIdentity:identity])
-          .andDo(^(NSInvocation*) {
-            [authentication_flow_in_profile_
-                didRegisterForUserPolicyWithDMToken:kFakeDMToken
-                                           clientID:kFakeClientID
-                                 userAffiliationIDs:@[
-                                   kFakeUserAffiliationID
-                                 ]];
-          });
+          .andDo(registerUserPolicyCallback);
+      auto fetchUserPolicyCallback = ^(NSInvocation*) {
+        [authentication_flow_in_profile_ didFetchUserPolicyWithSuccess:YES];
+      };
       OCMExpect([performer_mock_ fetchUserPolicy:final_profile
                                      withDmToken:kFakeDMToken
                                         clientID:kFakeClientID
                               userAffiliationIDs:@[ kFakeUserAffiliationID ]
                                         identity:identity])
-          .andDo(^(NSInvocation*) {
-            [authentication_flow_in_profile_ didFetchUserPolicyWithSuccess:YES];
-          });
+          .andDo(fetchUserPolicyCallback);
     }
 
     const bool should_switch_profile =
diff --git a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_mediator_unittest.mm b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_mediator_unittest.mm
index ac52238d..342399f8 100644
--- a/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_mediator_unittest.mm
+++ b/ios/chrome/browser/authentication/ui_bundled/signin/consistency_promo_signin/consistency_promo_signin_mediator_unittest.mm
@@ -69,7 +69,7 @@
 
   void TearDown() override {
     EXPECT_OCMOCK_VERIFY((id)mediator_delegate_mock_);
-    EXPECT_OCMOCK_VERIFY((id)authentication_flow_);
+    EXPECT_OCMOCK_VERIFY((id)authentication_flow_mock_);
     PlatformTest::TearDown();
   }
 
@@ -82,7 +82,7 @@
         GetApplicationContext()->GetSystemIdentityManager());
   }
 
-  ConsistencyPromoSigninMediator* BuildConsistencyPromoSigninMediator(
+  void SetConsistencyPromoSigninMediator(
       signin_metrics::AccessPoint access_point) {
     ChromeAccountManagerService* chrome_account_manager_service =
         ChromeAccountManagerServiceFactory::GetForProfile(profile_.get());
@@ -92,38 +92,35 @@
         IdentityManagerFactory::GetForProfile(profile_.get());
     AccountReconcilor* account_reconcilor =
         ios::AccountReconcilorFactory::GetForProfile(profile_.get());
-    ConsistencyPromoSigninMediator* mediator =
-        [[ConsistencyPromoSigninMediator alloc]
-            initWithAccountManagerService:chrome_account_manager_service
-                    authenticationService:auth_service
-                          identityManager:identity_manager
-                        accountReconcilor:account_reconcilor
-                          userPrefService:GetPrefService()
-                              accessPoint:access_point];
-    mediator.delegate = mediator_delegate_mock_;
-    return mediator;
+    mediator_ = [[ConsistencyPromoSigninMediator alloc]
+        initWithAccountManagerService:chrome_account_manager_service
+                authenticationService:auth_service
+                      identityManager:identity_manager
+                    accountReconcilor:account_reconcilor
+                      userPrefService:GetPrefService()
+                          accessPoint:access_point];
+    mediator_.delegate = mediator_delegate_mock_;
   }
 
-  void SimulateCookieFetchSuccess(ConsistencyPromoSigninMediator* mediator,
-                                  id<SystemIdentity> identity) {
+  void SimulateCookieFetchSuccess(id<SystemIdentity> identity) {
     CHECK(!ShouldEnableIdentityInAuthErrorFlag());
     gaia::ListedAccount account;
     account.id = CoreAccountId::FromGaiaId(GaiaId(identity.gaiaID));
     signin::AccountsInCookieJarInfo cookie_jar_info(
         /*accounts_are_fresh=*/true,
         /*accounts=*/{account});
-    [(id<IdentityManagerObserverBridgeDelegate>)mediator
+    [(id<IdentityManagerObserverBridgeDelegate>)mediator_
         onAccountsInCookieUpdated:cookie_jar_info
                             error:GoogleServiceAuthError(
                                       GoogleServiceAuthError::State::NONE)];
   }
 
-  void SimulateCookieFetchError(ConsistencyPromoSigninMediator* mediator) {
+  void SimulateCookieFetchError() {
     CHECK(!ShouldEnableIdentityInAuthErrorFlag());
     signin::AccountsInCookieJarInfo cookie_jar_info(
         /*accounts_are_fresh=*/false,
         /*accounts=*/{});
-    [(id<IdentityManagerObserverBridgeDelegate>)mediator
+    [(id<IdentityManagerObserverBridgeDelegate>)mediator_
         onAccountsInCookieUpdated:cookie_jar_info
                             error:GoogleServiceAuthError(
                                       GoogleServiceAuthError::State::
@@ -142,10 +139,10 @@
         result == SigninCoordinatorResult::SigninCoordinatorResultSuccess;
     OCMExpect([mediator_delegate_mock_
         consistencyPromoSigninMediatorSigninStarted:[OCMArg any]]);
-    OCMExpect([authentication_flow_ identity]).andReturn(identity);
+    OCMExpect([authentication_flow_mock_ identity]).andReturn(identity);
     AuthenticationService* auth_service =
         AuthenticationServiceFactory::GetForProfile(profile_.get());
-    OCMExpect([authentication_flow_
+    OCMExpect([authentication_flow_mock_
         startSignInWithCompletion:[OCMArg
                                       checkWithBlock:^BOOL(
                                           signin_ui::SigninCompletionCallback
@@ -190,12 +187,13 @@
   bool ShouldEnableIdentityInAuthErrorFlag() { return GetParam(); }
 
  protected:
-  AuthenticationFlow* authentication_flow_ =
+  AuthenticationFlow* authentication_flow_mock_ =
       OCMStrictClassMock([AuthenticationFlow class]);
   id<ConsistencyPromoSigninMediatorDelegate> mediator_delegate_mock_ =
       OCMStrictProtocolMock(@protocol(ConsistencyPromoSigninMediatorDelegate));
   base::RepeatingCallback<void(signin::WebSigninTracker::Result)>
       captured_callback_;
+  ConsistencyPromoSigninMediator* mediator_;
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
@@ -210,10 +208,8 @@
 TEST_P(ConsistencyPromoSigninMediatorTest, StartAndStopForCancel) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
-  [mediator disconnectWithResult:SigninCoordinatorResultCanceledByUser];
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
+  [mediator_ disconnectWithResult:SigninCoordinatorResultCanceledByUser];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -231,10 +227,8 @@
 TEST_P(ConsistencyPromoSigninMediatorTest, StartAndStopForInterrupt) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
-  [mediator disconnectWithResult:SigninCoordinatorResultInterrupted];
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
+  [mediator_ disconnectWithResult:SigninCoordinatorResultInterrupted];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -259,23 +253,21 @@
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   ExpectWebSigninTrackerCreationAndCaptureCallback();
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   OCMExpect([mediator_delegate_mock_
-      consistencyPromoSigninMediatorSignInDone:mediator
+      consistencyPromoSigninMediatorSignInDone:mediator_
                                   withIdentity:kDefaultIdentity]);
 
   if (ShouldEnableIdentityInAuthErrorFlag()) {
     CHECK(captured_callback_);
     captured_callback_.Run(signin::WebSigninTracker::Result::kSuccess);
   } else {
-    SimulateCookieFetchSuccess(mediator, kDefaultIdentity);
+    SimulateCookieFetchSuccess(kDefaultIdentity);
   }
 
-  [mediator disconnectWithResult:SigninCoordinatorResultSuccess];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultSuccess];
 
   EXPECT_EQ(0,
             GetPrefService()->GetInteger(prefs::kSigninWebSignDismissalCount));
@@ -302,23 +294,21 @@
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   ExpectWebSigninTrackerCreationAndCaptureCallback();
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   OCMExpect([mediator_delegate_mock_
-      consistencyPromoSigninMediatorSignInDone:mediator
+      consistencyPromoSigninMediatorSignInDone:mediator_
                                   withIdentity:kNonDefaultIdentity]);
 
   if (ShouldEnableIdentityInAuthErrorFlag()) {
     CHECK(captured_callback_);
     captured_callback_.Run(signin::WebSigninTracker::Result::kSuccess);
   } else {
-    SimulateCookieFetchSuccess(mediator, kNonDefaultIdentity);
+    SimulateCookieFetchSuccess(kNonDefaultIdentity);
   }
 
-  [mediator disconnectWithResult:SigninCoordinatorResultSuccess];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultSuccess];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -337,30 +327,28 @@
        SigninCoordinatorResultSuccessWithAddedIdentity) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
-  [mediator systemIdentityAdded:kDefaultIdentity];
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
+  [mediator_ systemIdentityAdded:kDefaultIdentity];
 
   ExpectAuthFlowStartAndSetResult(
       kDefaultIdentity, signin_metrics::AccessPoint::kWebSignin,
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   ExpectWebSigninTrackerCreationAndCaptureCallback();
 
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   OCMExpect([mediator_delegate_mock_
-      consistencyPromoSigninMediatorSignInDone:mediator
+      consistencyPromoSigninMediatorSignInDone:mediator_
                                   withIdentity:kDefaultIdentity]);
 
   if (ShouldEnableIdentityInAuthErrorFlag()) {
     CHECK(captured_callback_);
     captured_callback_.Run(signin::WebSigninTracker::Result::kSuccess);
   } else {
-    SimulateCookieFetchSuccess(mediator, kDefaultIdentity);
+    SimulateCookieFetchSuccess(kDefaultIdentity);
   }
 
-  [mediator disconnectWithResult:SigninCoordinatorResultSuccess];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultSuccess];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -380,22 +368,20 @@
 TEST_P(ConsistencyPromoSigninMediatorTest, CookiesError) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
 
   ExpectAuthFlowStartAndSetResult(
       kDefaultIdentity, signin_metrics::AccessPoint::kWebSignin,
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   ExpectWebSigninTrackerCreationAndCaptureCallback();
 
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   // The error is only signaled after AuthenticationService::Signout() and
   // that's async.
   __block auto error_wait_loop = std::make_unique<base::RunLoop>();
   OCMExpect([mediator_delegate_mock_
-                consistencyPromoSigninMediator:mediator
+                consistencyPromoSigninMediator:mediator_
                                 errorDidHappen:
                                     ConsistencyPromoSigninMediatorErrorGeneric])
       .andDo(^(NSInvocation*) {
@@ -406,12 +392,12 @@
     CHECK(captured_callback_);
     captured_callback_.Run(signin::WebSigninTracker::Result::kOtherError);
   } else {
-    SimulateCookieFetchError(mediator);
+    SimulateCookieFetchError();
   }
 
   error_wait_loop->Run();
 
-  [mediator disconnectWithResult:SigninCoordinatorResultCanceledByUser];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultCanceledByUser];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -435,22 +421,20 @@
 TEST_P(ConsistencyPromoSigninMediatorTest, CookiesTimeout) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
 
   ExpectAuthFlowStartAndSetResult(
       kDefaultIdentity, signin_metrics::AccessPoint::kWebSignin,
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   ExpectWebSigninTrackerCreationAndCaptureCallback();
 
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   // The error is only signaled after AuthenticationService::Signout() and
   // that's async.
   __block auto error_wait_loop = std::make_unique<base::RunLoop>();
   OCMExpect([mediator_delegate_mock_
-                consistencyPromoSigninMediator:mediator
+                consistencyPromoSigninMediator:mediator_
                                 errorDidHappen:
                                     ConsistencyPromoSigninMediatorErrorTimeout])
       .andDo(^(NSInvocation*) {
@@ -466,7 +450,7 @@
 
   error_wait_loop->Run();
 
-  [mediator disconnectWithResult:SigninCoordinatorResultCanceledByUser];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultCanceledByUser];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -489,9 +473,7 @@
 TEST_P(ConsistencyPromoSigninMediatorTest, AuthFlowError) {
   base::HistogramTester histogram_tester;
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kWebSignin);
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kWebSignin);
 
   ExpectAuthFlowStartAndSetResult(
       kDefaultIdentity, signin_metrics::AccessPoint::kWebSignin,
@@ -502,16 +484,16 @@
   // call is made nonetheless).
   __block auto error_wait_loop = std::make_unique<base::RunLoop>();
   OCMExpect([mediator_delegate_mock_
-                consistencyPromoSigninMediatorSignInCancelled:mediator])
+                consistencyPromoSigninMediatorSignInCancelled:mediator_])
       .andDo(^(NSInvocation*) {
         error_wait_loop->Quit();
       });
 
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
 
   error_wait_loop->Run();
 
-  [mediator disconnectWithResult:SigninCoordinatorResultCanceledByUser];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultCanceledByUser];
 
   histogram_tester.ExpectTotalCount(
       "Signin.AccountConsistencyPromoAction.Shown", 1);
@@ -536,19 +518,17 @@
   base::HistogramTester histogram_tester;
   GetPrefService()->SetInteger(prefs::kSigninWebSignDismissalCount, 1);
 
-  ConsistencyPromoSigninMediator* mediator =
-      BuildConsistencyPromoSigninMediator(
-          signin_metrics::AccessPoint::kSettings);
+  SetConsistencyPromoSigninMediator(signin_metrics::AccessPoint::kSettings);
 
   ExpectAuthFlowStartAndSetResult(
       kDefaultIdentity, signin_metrics::AccessPoint::kSettings,
       SigninCoordinatorResult::SigninCoordinatorResultSuccess);
   OCMExpect([mediator_delegate_mock_
-      consistencyPromoSigninMediatorSignInDone:mediator
+      consistencyPromoSigninMediatorSignInDone:mediator_
                                   withIdentity:kDefaultIdentity]);
 
-  [mediator signinWithAuthenticationFlow:authentication_flow_];
-  [mediator disconnectWithResult:SigninCoordinatorResultSuccess];
+  [mediator_ signinWithAuthenticationFlow:authentication_flow_mock_];
+  [mediator_ disconnectWithResult:SigninCoordinatorResultSuccess];
 
   EXPECT_EQ(1,
             GetPrefService()->GetInteger(prefs::kSigninWebSignDismissalCount));
diff --git a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm
index c0c0a3a..deb4514 100644
--- a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm
+++ b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate.mm
@@ -93,8 +93,7 @@
       tab_group_service_(tab_group_service) {
   CHECK(browser_);
   CHECK(base_view_controller_);
-  // TODO(crbug.com/399289392): uncomment once downstream is landed.
-  //  CHECK(tab_group_service_);
+  CHECK(tab_group_service_);
   ProfileIOS* profile = browser_->GetProfile();
 
   share_kit_service_ = ShareKitServiceFactory::GetForProfile(profile);
@@ -263,10 +262,9 @@
 
   tab_group_service_registration_id_ =
       std::make_optional(tab_group->tab_group_id());
-  // TODO(crbug.com/399289392): uncomment once downstream is landed.
-  //  tab_group_service_->RegisterCollaborationControllerDelegate(
-  //      tab_group_service_registration_id_.value(),
-  //      weak_ptr_factory_.GetWeakPtr());
+  tab_group_service_->RegisterCollaborationControllerDelegate(
+      tab_group_service_registration_id_.value(),
+      weak_ptr_factory_.GetWeakPtr());
 
   auto callback = base::BindOnce(
       &IOSCollaborationControllerDelegate::ConfigureAndShareTabGroup,
@@ -349,9 +347,8 @@
 
 void IOSCollaborationControllerDelegate::OnFlowFinished() {
   if (tab_group_service_registration_id_) {
-    // TODO(crbug.com/399289392): uncomment once downstream is landed.
-    //    tab_group_service_->UnregisterCollaborationControllerDelegate(
-    //        tab_group_service_registration_id_.value());
+    tab_group_service_->UnregisterCollaborationControllerDelegate(
+        tab_group_service_registration_id_.value());
   }
   if (dismiss_join_screen_callback_) {
     // The dismissal should be handled before the end of the flow.
diff --git a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate_unittest.mm b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate_unittest.mm
index 68afd884..072af52 100644
--- a/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate_unittest.mm
+++ b/ios/chrome/browser/collaboration/model/ios_collaboration_controller_delegate_unittest.mm
@@ -62,9 +62,11 @@
   ProfileIOS* profile = static_cast<ProfileIOS*>(context);
   data_sharing::DataSharingService* data_sharing_service =
       data_sharing::DataSharingServiceFactory::GetForProfile(profile);
+  TabGroupService* tab_group_service =
+      TabGroupServiceFactory::GetForProfile(profile);
 
   return std::make_unique<TestShareKitService>(data_sharing_service, nullptr,
-                                               nullptr);
+                                               nullptr, tab_group_service);
 }
 
 std::unique_ptr<KeyedService> BuildFakeTabGroupSyncService(
@@ -78,7 +80,14 @@
 
 std::unique_ptr<KeyedService> BuildMockCollaborationService(
     web::BrowserState* context) {
-  return std::make_unique<MockCollaborationService>();
+  ServiceStatus collaboration_status;
+  collaboration_status.collaboration_status =
+      CollaborationStatus::kEnabledCreateAndJoin;
+  std::unique_ptr<MockCollaborationService> mock_collaboration_service =
+      std::make_unique<MockCollaborationService>();
+  ON_CALL(*mock_collaboration_service.get(), GetServiceStatus())
+      .WillByDefault(Return(collaboration_status));
+  return std::move(mock_collaboration_service);
 }
 
 std::unique_ptr<KeyedService> BuildTestFaviconLoader(
@@ -125,6 +134,9 @@
     test_profile_builder.AddTestingFactory(
         TabGroupServiceFactory::GetInstance(),
         TabGroupServiceFactory::GetDefaultFactory());
+    test_profile_builder.AddTestingFactory(
+        TabGroupServiceFactory::GetInstance(),
+        TabGroupServiceFactory::GetDefaultFactory());
 
     profile_ = std::move(test_profile_builder).Build();
     browser_ = std::make_unique<TestBrowser>(profile_.get());
@@ -254,8 +266,9 @@
   ServiceStatus collaboration_status_;
 };
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowShareDialog` with a valid tabGroup.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowShareDialogValid) {
+TEST_F(IOSCollaborationControllerDelegateTest, DISABLED_ShowShareDialogValid) {
   InitDelegate();
   base::MockCallback<
       CollaborationControllerDelegate::ResultWithGroupTokenCallback>
@@ -273,8 +286,10 @@
   [share_kit_flow_view_controller accept];
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowShareDialog` with an invalid tabGroup.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowShareDialogInvalid) {
+TEST_F(IOSCollaborationControllerDelegateTest,
+       DISABLED_ShowShareDialogInvalid) {
   InitDelegate();
 
   tab_groups::TabGroupId tab_group_id = tab_group_->tab_group_id();
@@ -292,8 +307,9 @@
   EXPECT_FALSE(base_view_controller_.presentedViewController);
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowJoinDialog` and accept.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowJoinDialogAccept) {
+TEST_F(IOSCollaborationControllerDelegateTest, DISABLED_ShowJoinDialogAccept) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -311,8 +327,9 @@
   [share_kit_flow_view_controller accept];
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowJoinDialog` and cancel.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowJoinDialogCancel) {
+TEST_F(IOSCollaborationControllerDelegateTest, DISABLED_ShowJoinDialogCancel) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -330,8 +347,10 @@
   [share_kit_flow_view_controller cancel];
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowManageDialog` and accept.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowManageDialogAccept) {
+TEST_F(IOSCollaborationControllerDelegateTest,
+       DISABLED_ShowManageDialogAccept) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -349,8 +368,10 @@
   [share_kit_flow_view_controller accept];
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowManageDialog` and cancel.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowManageDialogCancel) {
+TEST_F(IOSCollaborationControllerDelegateTest,
+       DISABLED_ShowManageDialogCancel) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -368,9 +389,10 @@
   [share_kit_flow_view_controller cancel];
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowAuthenticationUi` when the user chooses to cancel the sign in.
 TEST_F(IOSCollaborationControllerDelegateTest,
-       ShowAuthenticationUiSignInCanceled) {
+       DISABLED_ShowAuthenticationUiSignInCanceled) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -390,10 +412,11 @@
   delegate_->ShowAuthenticationUi(FlowType::kJoin, mock_callback.Get());
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowAuthenticationUi` when the user sign in and accept the sync opt
 // in.
 TEST_F(IOSCollaborationControllerDelegateTest,
-       ShowAuthenticationUiSyncAccepted) {
+       DISABLED_ShowAuthenticationUiSyncAccepted) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -415,8 +438,10 @@
   delegate_->ShowAuthenticationUi(FlowType::kJoin, mock_callback.Get());
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowAuthenticationUi` when the user sign in but don't sync.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowAuthenticationUiSyncDenied) {
+TEST_F(IOSCollaborationControllerDelegateTest,
+       DISABLED_ShowAuthenticationUiSyncDenied) {
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
       mock_callback;
@@ -438,8 +463,10 @@
   delegate_->ShowAuthenticationUi(FlowType::kJoin, mock_callback.Get());
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `ShowAuthenticationUi` when the user is signed-in.
-TEST_F(IOSCollaborationControllerDelegateTest, ShowAuthenticationUiWithSignIn) {
+TEST_F(IOSCollaborationControllerDelegateTest,
+       DISABLED_ShowAuthenticationUiWithSignIn) {
   SignIn();
   InitDelegate();
   base::MockCallback<CollaborationControllerDelegate::ResultCallback>
@@ -462,9 +489,10 @@
   delegate_->ShowAuthenticationUi(FlowType::kJoin, mock_callback.Get());
 }
 
+// TODO(crbug.com/409238636): failing on ios_simulator_noncq
 // Tests `NotifySignInAndSyncStatusChange`.
 TEST_F(IOSCollaborationControllerDelegateTest,
-       NotifySignInAndSyncStatusChange) {
+       DISABLED_NotifySignInAndSyncStatusChange) {
   InitDelegate();
   delegate_->NotifySignInAndSyncStatusChange();
 }
diff --git a/ios/chrome/browser/data_sharing/model/data_sharing_ui_delegate_ios.h b/ios/chrome/browser/data_sharing/model/data_sharing_ui_delegate_ios.h
index 8fc8270..5e6918c 100644
--- a/ios/chrome/browser/data_sharing/model/data_sharing_ui_delegate_ios.h
+++ b/ios/chrome/browser/data_sharing/model/data_sharing_ui_delegate_ios.h
@@ -22,11 +22,10 @@
 // IOS implementation of DataSharingUIDelegate.
 class DataSharingUIDelegateIOS : public DataSharingUIDelegate {
  public:
-  // TODO(crbug.com/399289392): make tab_group_service nonnull.
   explicit DataSharingUIDelegateIOS(
       ShareKitService* share_kit_service,
       collaboration::CollaborationService* collaboration_service,
-      TabGroupService* tab_group_service = nullptr);
+      TabGroupService* tab_group_service);
   ~DataSharingUIDelegateIOS() override;
 
   DataSharingUIDelegateIOS(const DataSharingUIDelegateIOS&) = delete;
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn b/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
index 03ddb96e..c7b38b8 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/BUILD.gn
@@ -183,6 +183,7 @@
     "autocomplete_result_consumer.h",
     "content_providing.h",
     "omnibox_icon.h",
+    "omnibox_popup_consumer.h",
     "popup_match_preview_delegate.h",
   ]
 }
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h b/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h
index a1bb296..1ef34b9 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h
@@ -9,7 +9,7 @@
 
 @protocol AutocompleteSuggestion;
 @protocol AutocompleteSuggestionGroup;
-@protocol AutocompleteResultConsumer;
+@protocol OmniboxPopupConsumer;
 
 @class SuggestAction;
 
@@ -18,58 +18,36 @@
 
 /// Notify about a size change.
 - (void)autocompleteResultConsumerDidChangeTraitCollection:
-    (id<AutocompleteResultConsumer>)sender;
+    (id<OmniboxPopupConsumer>)sender;
 
 /// Tells the delegate on scroll.
-- (void)autocompleteResultConsumerDidScroll:
-    (id<AutocompleteResultConsumer>)sender;
+- (void)autocompleteResultConsumerDidScroll:(id<OmniboxPopupConsumer>)sender;
 
 /// Tells the delegate when `suggestion` in `row` was selected.
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
-               didSelectSuggestion:(id<AutocompleteSuggestion>)suggestion
-                             inRow:(NSUInteger)row;
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
+         didSelectSuggestion:(id<AutocompleteSuggestion>)suggestion
+                       inRow:(NSUInteger)row;
 
 /// Tells the delegate when a `suggestion`'s `action` was selected in a given
 /// row index, for example "Directions" button for a local entity suggestion.
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
-         didSelectSuggestionAction:(SuggestAction*)action
-                        suggestion:(id<AutocompleteSuggestion>)suggestion
-                             inRow:(NSUInteger)row;
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
+    didSelectSuggestionAction:(SuggestAction*)action
+                   suggestion:(id<AutocompleteSuggestion>)suggestion
+                        inRow:(NSUInteger)row;
 
 /// Tells the delegate when `suggestion` in `row` was chosen for appending to
 /// omnibox.
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
     didTapTrailingButtonOnSuggestion:(id<AutocompleteSuggestion>)suggestion
                                inRow:(NSUInteger)row;
 
 /// Tells the delegate when `suggestion` in `row` was removed.
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
     didSelectSuggestionForDeletion:(id<AutocompleteSuggestion>)suggestion
                              inRow:(NSUInteger)row;
 
 @end
 
-/// An abstract consumer of autocomplete results.
-@protocol AutocompleteResultConsumer <NSObject>
-/// Updates the current data and forces a redraw. If animation is YES, adds
-/// CALayer animations to fade the OmniboxPopupRows in.
-/// `preselectedMatchGroupIndex` is the section selected by default when no row
-/// is highlighted.
-- (void)updateMatches:(NSArray<id<AutocompleteSuggestionGroup>>*)result
-    preselectedMatchGroupIndex:(NSInteger)groupIndex;
-
-/// Sets the text alignment of the popup content.
-- (void)setTextAlignment:(NSTextAlignment)alignment;
-/// Sets the semantic content attribute of the popup content.
-- (void)setSemanticContentAttribute:
-    (UISemanticContentAttribute)semanticContentAttribute;
-
-/// Informs consumer that new result are available. Consumer can request new
-/// results from its data source `AutocompleteResultDataSource`.
-- (void)newResultsAvailable;
-
-@end
-
 /// An abstract data source for autocomplete results.
 @protocol AutocompleteResultDataSource <NSObject>
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h
new file mode 100644
index 0000000..1d639a50
--- /dev/null
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h
@@ -0,0 +1,30 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_POPUP_CONSUMER_H_
+#define IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_POPUP_CONSUMER_H_
+
+// The omnibox popup consumer.
+@protocol OmniboxPopupConsumer <NSObject>
+
+/// Updates the current data and forces a redraw. If animation is YES, adds
+/// CALayer animations to fade the OmniboxPopupRows in.
+/// `preselectedMatchGroupIndex` is the section selected by default when no row
+/// is highlighted.
+- (void)updateMatches:(NSArray<id<AutocompleteSuggestionGroup>>*)result
+    preselectedMatchGroupIndex:(NSInteger)groupIndex;
+
+/// Sets the text alignment of the popup content.
+- (void)setTextAlignment:(NSTextAlignment)alignment;
+/// Sets the semantic content attribute of the popup content.
+- (void)setSemanticContentAttribute:
+    (UISemanticContentAttribute)semanticContentAttribute;
+
+/// Informs consumer that new result are available. Consumer can request new
+/// results from its data source `AutocompleteResultDataSource`.
+- (void)newResultsAvailable;
+
+@end
+
+#endif  // IOS_CHROME_BROWSER_OMNIBOX_UI_BUNDLED_POPUP_OMNIBOX_POPUP_CONSUMER_H_
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.h b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.h
index 9f02962b..89b97cf 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.h
@@ -24,6 +24,7 @@
 @protocol CarouselItemConsumer;
 @class OmniboxAutocompleteController;
 @class OmniboxImageFetcher;
+@protocol OmniboxPopupConsumer;
 @class OmniboxPopupMediator;
 @class OmniboxPopupPresenter;
 @class SceneState;
@@ -68,7 +69,7 @@
 @property(nonatomic, weak)
     OmniboxAutocompleteController* omniboxAutocompleteController;
 
-@property(nonatomic, weak) id<AutocompleteResultConsumer> consumer;
+@property(nonatomic, weak) id<OmniboxPopupConsumer> consumer;
 
 @property(nonatomic, weak) id<ApplicationCommands> applicationCommandsHandler;
 /// Browser scene state to notify about events happening in this popup.
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
index beb621b..751502b 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator.mm
@@ -39,6 +39,7 @@
 #import "ios/chrome/browser/omnibox/model/suggest_action.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item_menu_provider.h"
+#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator+Testing.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_presenter.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift.h"
@@ -167,13 +168,13 @@
 #pragma mark - AutocompleteResultConsumerDelegate
 
 - (void)autocompleteResultConsumerDidChangeTraitCollection:
-    (id<AutocompleteResultConsumer>)sender {
+    (id<OmniboxPopupConsumer>)sender {
   [self.presenter updatePopupAfterTraitCollectionChange];
 }
 
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
-               didSelectSuggestion:(id<AutocompleteSuggestion>)suggestion
-                             inRow:(NSUInteger)row {
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
+         didSelectSuggestion:(id<AutocompleteSuggestion>)suggestion
+                       inRow:(NSUInteger)row {
   [self logPedalShownForCurrentResult];
 
   // Log the suggest actions that were shown and not used.
@@ -225,10 +226,10 @@
   }
 }
 
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
-         didSelectSuggestionAction:(SuggestAction*)action
-                        suggestion:(id<AutocompleteSuggestion>)suggestion
-                             inRow:(NSUInteger)row {
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
+    didSelectSuggestionAction:(SuggestAction*)action
+                   suggestion:(id<AutocompleteSuggestion>)suggestion
+                        inRow:(NSUInteger)row {
   OmniboxActionInSuggest::RecordShownAndUsedMetrics(action.type,
                                                     true /* used */);
 
@@ -266,7 +267,7 @@
   }
 }
 
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
     didTapTrailingButtonOnSuggestion:(id<AutocompleteSuggestion>)suggestion
                                inRow:(NSUInteger)row {
   if ([suggestion isKindOfClass:[AutocompleteMatchFormatter class]]) {
@@ -295,7 +296,7 @@
   }
 }
 
-- (void)autocompleteResultConsumer:(id<AutocompleteResultConsumer>)sender
+- (void)omniboxPopupConsumer:(id<OmniboxPopupConsumer>)sender
     didSelectSuggestionForDeletion:(id<AutocompleteSuggestion>)suggestion
                              inRow:(NSUInteger)row {
   if ([suggestion isKindOfClass:[AutocompleteMatchFormatter class]]) {
@@ -311,8 +312,7 @@
   }
 }
 
-- (void)autocompleteResultConsumerDidScroll:
-    (id<AutocompleteResultConsumer>)sender {
+- (void)autocompleteResultConsumerDidScroll:(id<OmniboxPopupConsumer>)sender {
   [self.omniboxAutocompleteController onScroll];
 }
 
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
index 7eb74f6..23dfdf95 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator_unittest.mm
@@ -36,6 +36,7 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/favicon_retriever.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/image_retriever.h"
+#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_mediator+Testing.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_swift.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
@@ -105,8 +106,7 @@
 
     feature_engagement::test::MockTracker tracker;
 
-    mockResultConsumer_ =
-        OCMProtocolMock(@protocol(AutocompleteResultConsumer));
+    mockResultConsumer_ = OCMProtocolMock(@protocol(OmniboxPopupConsumer));
 
     omnibox_image_fetcher_ = [[OmniboxImageFetcher alloc]
         initWithFaviconLoader:nil
@@ -148,9 +148,9 @@
       "PasswordManager.ManagePasswordsReferrer",
       password_manager::ManagePasswordsReferrer::kOmniboxPedalSuggestion, 0);
 
-  [mediator_ autocompleteResultConsumer:mockResultConsumer_
-                    didSelectSuggestion:mockSuggestionWithPedal
-                                  inRow:0];
+  [mediator_ omniboxPopupConsumer:mockResultConsumer_
+              didSelectSuggestion:mockSuggestionWithPedal
+                            inRow:0];
 
   // Bucket count should now be one.
   histogram_tester.ExpectBucketCount(
@@ -196,18 +196,18 @@
                                      kActionTypeReview, 0);
 
   // Select an action suggestion.
-  [mediator_ autocompleteResultConsumer:nil
-                    didSelectSuggestion:actionSuggestion
-                                  inRow:0];
+  [mediator_ omniboxPopupConsumer:nil
+              didSelectSuggestion:actionSuggestion
+                            inRow:0];
 
   // Expect Shown not logged when selecting an action.
   histogram_tester.ExpectBucketCount("Omnibox.ActionInSuggest.Shown",
                                      kActionTypeReview, 0);
 
   // Select another suggestion.
-  [mediator_ autocompleteResultConsumer:nil
-                    didSelectSuggestion:nonActionSuggestion
-                                  inRow:1];
+  [mediator_ omniboxPopupConsumer:nil
+              didSelectSuggestion:nonActionSuggestion
+                            inRow:1];
 
   // Expect Shown logged.
   histogram_tester.ExpectBucketCount("Omnibox.ActionInSuggest.Shown",
@@ -244,7 +244,7 @@
   base::HistogramTester histogram_tester;
 
   // Select a suggestion.
-  [mediator_ autocompleteResultConsumer:nil didSelectSuggestion:match2 inRow:1];
+  [mediator_ omniboxPopupConsumer:nil didSelectSuggestion:match2 inRow:1];
 
   histogram_tester.ExpectUniqueSample("Omnibox.PedalShown", 1, 1);
 }
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h
index 9e62fed..471ca032 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h
@@ -11,6 +11,7 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/autocomplete_result_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/carousel/carousel_item.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/content_providing.h"
+#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h"
 
 @protocol CarouselItemMenuProvider;
 @protocol FaviconRetriever;
@@ -29,7 +30,7 @@
 /// arrows, so when the omnibox is the first responder, this view controller
 /// cannot receive these events. Hence the delegation.
 @interface OmniboxPopupViewController
-    : UIViewController <AutocompleteResultConsumer,
+    : UIViewController <OmniboxPopupConsumer,
                         CarouselItemConsumer,
                         ContentProviding,
                         OmniboxKeyboardDelegate,
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
index 5ef66b6..bee5725 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.mm
@@ -345,7 +345,7 @@
   }
 }
 
-#pragma mark - AutocompleteResultConsumer
+#pragma mark - OmniboxPopupConsumer
 
 - (void)updateMatches:(NSArray<id<AutocompleteSuggestionGroup>>*)result
     preselectedMatchGroupIndex:(NSInteger)groupIndex {
@@ -624,9 +624,9 @@
       [self suggestionAtIndexPath:self.highlightedIndexPath];
   NSInteger absoluteRow =
       [self absoluteRowIndexForIndexPath:self.highlightedIndexPath];
-  [self.delegate autocompleteResultConsumer:self
-                        didSelectSuggestion:suggestion
-                                      inRow:absoluteRow];
+  [self.delegate omniboxPopupConsumer:self
+                  didSelectSuggestion:suggestion
+                                inRow:absoluteRow];
 }
 
 #pragma mark - OmniboxPopupRowDelegate
@@ -639,9 +639,9 @@
   if (suggestion != configuration.suggestion) {
     return;
   }
-  [self.delegate autocompleteResultConsumer:self
-           didTapTrailingButtonOnSuggestion:suggestion
-                                      inRow:indexPath.row];
+  [self.delegate omniboxPopupConsumer:self
+      didTapTrailingButtonOnSuggestion:suggestion
+                                 inRow:indexPath.row];
 }
 
 - (void)omniboxPopupRowWithConfiguration:
@@ -669,10 +669,10 @@
 
   CHECK(suggestion == configuration.suggestion);
 
-  [self.delegate autocompleteResultConsumer:self
-                  didSelectSuggestionAction:action
-                                 suggestion:suggestion
-                                      inRow:configuration.indexPath.row];
+  [self.delegate omniboxPopupConsumer:self
+            didSelectSuggestionAction:action
+                           suggestion:suggestion
+                                inRow:configuration.indexPath.row];
 }
 
 - (void)tableView:(UITableView*)tableView
@@ -705,10 +705,9 @@
     return;
   }
   NSInteger absoluteRow = [self absoluteRowIndexForIndexPath:indexPath];
-  [self.delegate
-      autocompleteResultConsumer:self
-             didSelectSuggestion:[self suggestionAtIndexPath:indexPath]
-                           inRow:absoluteRow];
+  [self.delegate omniboxPopupConsumer:self
+                  didSelectSuggestion:[self suggestionAtIndexPath:indexPath]
+                                inRow:absoluteRow];
 }
 
 - (CGFloat)tableView:(UITableView*)tableView
@@ -810,9 +809,9 @@
       [self suggestionAtIndexPath:indexPath];
   DCHECK(suggestion);
   if (editingStyle == UITableViewCellEditingStyleDelete) {
-    [self.delegate autocompleteResultConsumer:self
-               didSelectSuggestionForDeletion:suggestion
-                                        inRow:indexPath.row];
+    [self.delegate omniboxPopupConsumer:self
+         didSelectSuggestionForDeletion:suggestion
+                                  inRow:indexPath.row];
   }
 }
 
@@ -990,9 +989,9 @@
 
   NSInteger absoluteRow =
       [self absoluteRowIndexForIndexPath:carouselItem.indexPath];
-  [self.delegate autocompleteResultConsumer:self
-                        didSelectSuggestion:suggestion
-                                      inRow:absoluteRow];
+  [self.delegate omniboxPopupConsumer:self
+                  didSelectSuggestion:suggestion
+                                inRow:absoluteRow];
 }
 
 #pragma mark - Internal API methods
diff --git a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
index 034ba3b6..5b1fb02 100644
--- a/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
+++ b/ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller_unittest.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_view_controller.h"
 
 #import "ios/chrome/browser/omnibox/model/autocomplete_suggestion_group_impl.h"
+#import "ios/chrome/browser/omnibox/ui_bundled/popup/omnibox_popup_consumer.h"
 #import "ios/chrome/browser/omnibox/ui_bundled/popup/popup_match_preview_delegate.h"
 #import "testing/gtest_mac.h"
 #import "testing/platform_test.h"
@@ -227,9 +228,9 @@
   // Pressing return key when a suggestion is highlighted call the
   // AutocompleteResultConsumerDelegate.
   [[delegate_ expect]
-      autocompleteResultConsumer:popup_view_controller_
-             didSelectSuggestion:first_suggestion_group_.suggestions[0]
-                           inRow:0];
+      omniboxPopupConsumer:popup_view_controller_
+       didSelectSuggestion:first_suggestion_group_.suggestions[0]
+                     inRow:0];
   EXPECT_TRUE([popup_view_controller_
       canPerformKeyboardAction:OmniboxKeyboardAction::kReturnKey]);
   [popup_view_controller_
diff --git a/ios/chrome/browser/passwords/ui_bundled/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm b/ios/chrome/browser/passwords/ui_bundled/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
index 3fef4d85..0e21909 100644
--- a/ios/chrome/browser/passwords/ui_bundled/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
+++ b/ios/chrome/browser/passwords/ui_bundled/bottom_sheet/password_suggestion_bottom_sheet_view_controller.mm
@@ -412,12 +412,8 @@
                                                   atIndexPath:indexPath];
   cell.accessoryType = [self accessoryType:indexPath];
 
-  [cell
-      setFaviconContainerBackgroundColor:
-          (self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark)
-              ? [UIColor colorNamed:kSeparatorColor]
-              : [UIColor colorNamed:kPrimaryBackgroundColor]];
-  [cell setFaviconContainerBorderColor:UIColor.clearColor];
+  [cell setFaviconContainerBackgroundColor:
+            [UIColor colorNamed:kPrimaryBackgroundColor]];
   cell.titleLabel.textColor = [UIColor colorNamed:kTextPrimaryColor];
   cell.backgroundColor = [UIColor colorNamed:kSecondaryBackgroundColor];
 
diff --git a/ios/chrome/browser/policy/model/policy_util.mm b/ios/chrome/browser/policy/model/policy_util.mm
index 57be10b..b021465e 100644
--- a/ios/chrome/browser/policy/model/policy_util.mm
+++ b/ios/chrome/browser/policy/model/policy_util.mm
@@ -22,6 +22,8 @@
   if (!pref_service) {
     return NO;
   }
+  // Platform note: on iOS it is not possible to disable the incognito mode at
+  // user level (only policy/enterprise or Family Link settings are respected).
   return pref_service->IsManagedPreference(
              policy::policy_prefs::kIncognitoModeAvailability) ||
          pref_service->IsPreferenceManagedByCustodian(
diff --git a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_orderer.mm b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_orderer.mm
index 4409eb61..bb3acf3 100644
--- a/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_orderer.mm
+++ b/ios/chrome/browser/popup_menu/ui_bundled/overflow_menu/overflow_menu_orderer.mm
@@ -194,6 +194,8 @@
 }
 
 - (void)disconnect {
+  [_destinationUsageHistoryEnabled stop];
+  _destinationUsageHistoryEnabled = nil;
   [self.destinationUsageHistory stop];
   self.destinationUsageHistory = nil;
 }
diff --git a/ios/chrome/browser/settings/ui_bundled/content_settings/content_settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/content_settings/content_settings_table_view_controller.mm
index 65bedc0..470e62e 100644
--- a/ios/chrome/browser/settings/ui_bundled/content_settings/content_settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/content_settings/content_settings_table_view_controller.mm
@@ -593,8 +593,15 @@
   [_linkPreviewEnabled stop];
   _linkPreviewEnabled.observer = nil;
   _linkPreviewEnabled = nil;
+  [_detectAddressesEnabled stop];
+  _detectAddressesEnabled.observer = nil;
+  _detectAddressesEnabled = nil;
+  [_detectUnitsEnabled stop];
+  _detectUnitsEnabled.observer = nil;
+  _detectUnitsEnabled = nil;
   [_webInspectorEnabled stop];
   _webInspectorEnabled.observer = nil;
+  _webInspectorEnabled = nil;
   [self.webInspectorStateViewCoordinator stop];
   self.webInspectorStateViewCoordinator = nil;
   [self.defaultModeViewCoordinator stop];
diff --git a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm
index f152c22f2..7ade5fc 100644
--- a/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/password/password_sharing/sharing_status_view_controller.mm
@@ -369,8 +369,6 @@
   FaviconContainerView* faviconContainerView =
       [[FaviconContainerView alloc] init];
   faviconContainerView.translatesAutoresizingMaskIntoConstraints = NO;
-  [faviconContainerView
-      setFaviconBackgroundColor:[UIColor colorNamed:kPrimaryBackgroundColor]];
   faviconContainerView.hidden = YES;
   self.faviconContainerView = faviconContainerView;
   return faviconContainerView;
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/lockdown_mode/lockdown_mode_mediator.mm b/ios/chrome/browser/settings/ui_bundled/privacy/lockdown_mode/lockdown_mode_mediator.mm
index 91e2671db..86d3616a 100644
--- a/ios/chrome/browser/settings/ui_bundled/privacy/lockdown_mode/lockdown_mode_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/privacy/lockdown_mode/lockdown_mode_mediator.mm
@@ -48,6 +48,7 @@
 }
 
 - (void)disconnect {
+  [_lockdownModePreference stop];
   _lockdownModePreference = nil;
 }
 
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_coordinator.mm
index 4469fa32f..c5ea3956 100644
--- a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_coordinator.mm
@@ -86,6 +86,8 @@
 - (void)stop {
   [self stopSafeBrowsingEnhancedProtectionCoordinator];
   [self stopSafeBrowsingStandardProtectionCoordinator];
+  [self.mediator disconnect];
+  self.mediator = nil;
   [super stop];
 }
 
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.h b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.h
index bbb062a..d213b9c 100644
--- a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.h
+++ b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.h
@@ -32,6 +32,9 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
+// Must be called before -dealloc.
+- (void)disconnect;
+
 // Handles logic for selecting an item in the view and the Privacy Safe Browsing
 // No Protection pop up.
 - (void)selectSettingItem:(TableViewItem*)item;
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm
index e8704b9f..272943f 100644
--- a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_mediator.mm
@@ -94,6 +94,14 @@
   return self;
 }
 
+- (void)disconnect {
+  [_safeBrowsingEnhancedProtectionPreference stop];
+  _safeBrowsingEnhancedProtectionPreference = nil;
+
+  [_safeBrowsingStandardProtectionPreference stop];
+  _safeBrowsingStandardProtectionPreference = nil;
+}
+
 - (void)selectSettingItem:(TableViewItem*)item {
   // If item is already selected or if we cancel turning off Safe Browsing,
   // don't do anything and keep the current selected choice.
diff --git a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_view_controller_unittest.mm b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_view_controller_unittest.mm
index 951b90b..c6918eb 100644
--- a/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_view_controller_unittest.mm
+++ b/ios/chrome/browser/settings/ui_bundled/privacy/privacy_safe_browsing_view_controller_unittest.mm
@@ -30,6 +30,12 @@
     profile_ = std::move(builder).Build();
   }
 
+  void TearDown() override {
+    [mediator_ disconnect];
+    mediator_ = nil;
+    LegacyChromeTableViewControllerTest::TearDown();
+  }
+
   // Makes a PrefService to be used by the test.
   std::unique_ptr<sync_preferences::PrefServiceSyncable> CreatePrefService() {
     auto prefs =
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_coordinator.mm b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_coordinator.mm
index 70e0bb9..3b4a39ce 100644
--- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_coordinator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_coordinator.mm
@@ -160,6 +160,9 @@
 
   [_optInAlertCoordinator stop];
   _optInAlertCoordinator = nil;
+
+  [self.mediator disconnect];
+  self.mediator = nil;
 }
 
 - (void)updateNotificationsButton:(BOOL)enabled {
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h
index 3014163..28fee099 100644
--- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h
+++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.h
@@ -77,6 +77,9 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
+// Must be called before -dealloc.
+- (void)disconnect;
+
 // Starts a safety check if one is not currently running.
 - (void)startCheckIfNotRunning;
 
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm
index 2244461..3a8b9d22 100644
--- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm
+++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator.mm
@@ -369,6 +369,14 @@
   return self;
 }
 
+- (void)disconnect {
+  [_safeBrowsingPreference stop];
+  _safeBrowsingPreference = nil;
+
+  [_enhancedSafeBrowsingPreference stop];
+  _enhancedSafeBrowsingPreference = nil;
+}
+
 - (void)setConsumer:(id<SafetyCheckConsumer>)consumer {
   if (_consumer == consumer) {
     return;
diff --git a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm
index 978b7fc..8e2af6a 100644
--- a/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm
+++ b/ios/chrome/browser/settings/ui_bundled/safety_check/safety_check_mediator_unittest.mm
@@ -165,6 +165,12 @@
                                     kSafetyCheck];
   }
 
+  void TearDown() override {
+    [mediator_ disconnect];
+    mediator_ = nil;
+    PlatformTest::TearDown();
+  }
+
   syncer::SyncService* syncService() {
     return SyncServiceFactory::GetForProfile(profile_.get());
   }
@@ -816,6 +822,7 @@
 TEST_F(SafetyCheckMediatorTest, NotificationsOptInButtonPromptsTurnOff) {
   feature_list_.InitWithFeatures({kSafetyCheckNotifications}, {});
 
+  [mediator_ disconnect];
   mediator_ = [[SafetyCheckMediator alloc]
       initWithUserPrefService:pref_service_
              localPrefService:local_pref_service_
@@ -838,6 +845,7 @@
 TEST_F(SafetyCheckMediatorTest, NotificationsOptInButtonPromptsTurnOn) {
   feature_list_.InitWithFeatures({kSafetyCheckNotifications}, {});
 
+  [mediator_ disconnect];
   mediator_ = [[SafetyCheckMediator alloc]
       initWithUserPrefService:pref_service_
              localPrefService:local_pref_service_
diff --git a/ios/chrome/browser/share_kit/model/share_kit_service_factory.mm b/ios/chrome/browser/share_kit/model/share_kit_service_factory.mm
index 24e24b21..947f72f 100644
--- a/ios/chrome/browser/share_kit/model/share_kit_service_factory.mm
+++ b/ios/chrome/browser/share_kit/model/share_kit_service_factory.mm
@@ -65,7 +65,8 @@
   // Give the opportunity for the test hook to override the service from
   // the provider (allowing EG tests to use a test ShareKitService).
   if (auto share_kit_service = tests_hook::CreateShareKitService(
-          data_sharing_service, collaboration_service, sync_service)) {
+          data_sharing_service, collaboration_service, sync_service,
+          tab_group_service)) {
     return share_kit_service;
   }
 
diff --git a/ios/chrome/browser/share_kit/model/test_share_kit_service.h b/ios/chrome/browser/share_kit/model/test_share_kit_service.h
index a400a077..4fd546d1 100644
--- a/ios/chrome/browser/share_kit/model/test_share_kit_service.h
+++ b/ios/chrome/browser/share_kit/model/test_share_kit_service.h
@@ -15,6 +15,8 @@
 #import "components/saved_tab_groups/public/types.h"
 #import "ios/chrome/browser/share_kit/model/share_kit_service.h"
 
+class TabGroupService;
+
 namespace collaboration {
 class CollaborationService;
 }  // namespace collaboration
@@ -29,7 +31,8 @@
   TestShareKitService(
       data_sharing::DataSharingService* data_sharing_service,
       collaboration::CollaborationService* collaboration_service,
-      tab_groups::TabGroupSyncService* tab_group_sync_service);
+      tab_groups::TabGroupSyncService* tab_group_sync_service,
+      TabGroupService* tab_group_service);
   TestShareKitService(const TestShareKitService&) = delete;
   TestShareKitService& operator=(const TestShareKitService&) = delete;
   ~TestShareKitService() override;
diff --git a/ios/chrome/browser/share_kit/model/test_share_kit_service.mm b/ios/chrome/browser/share_kit/model/test_share_kit_service.mm
index 11efdce..192fac3 100644
--- a/ios/chrome/browser/share_kit/model/test_share_kit_service.mm
+++ b/ios/chrome/browser/share_kit/model/test_share_kit_service.mm
@@ -94,13 +94,14 @@
 TestShareKitService::TestShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* tab_group_sync_service)
+    tab_groups::TabGroupSyncService* tab_group_sync_service,
+    TabGroupService* tab_group_service)
     : data_sharing_service_(data_sharing_service),
       tab_group_sync_service_(tab_group_sync_service) {
   if (data_sharing_service_) {
     std::unique_ptr<data_sharing::DataSharingUIDelegateIOS> ui_delegate =
         std::make_unique<data_sharing::DataSharingUIDelegateIOS>(
-            this, collaboration_service);
+            this, collaboration_service, tab_group_service);
     data_sharing_service_->SetUIDelegate(std::move(ui_delegate));
 
     std::unique_ptr<data_sharing::DataSharingSDKDelegateIOS> sdk_delegate =
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.h b/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.h
index 3bfff98..2db3651d 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.h
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.h
@@ -96,9 +96,6 @@
 // Sets the background color for the favicon container view.
 - (void)setFaviconContainerBackgroundColor:(UIColor*)backgroundColor;
 
-// Sets the border color for the favicon container view.
-- (void)setFaviconContainerBorderColor:(UIColor*)borderColor;
-
 @end
 
 #endif  // IOS_CHROME_BROWSER_SHARED_UI_TABLE_VIEW_CELLS_TABLE_VIEW_URL_ITEM_H_
diff --git a/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.mm b/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.mm
index 54a4229..8b83494 100644
--- a/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.mm
+++ b/ios/chrome/browser/shared/ui/table_view/cells/table_view_url_item.mm
@@ -302,10 +302,6 @@
   [self.faviconContainerView setFaviconBackgroundColor:backgroundColor];
 }
 
-- (void)setFaviconContainerBorderColor:(UIColor*)borderColor {
-  [self.faviconContainerView setFaviconBorderColor:borderColor];
-}
-
 // Hide or show the metadata and URL labels depending on the presence of text.
 // Align the horizontal stack properly depending on if the metadata label will
 // be present or not.
@@ -343,7 +339,6 @@
   [super prepareForReuse];
   [self.faviconView configureWithAttributes:nil];
   [self setFaviconContainerBackgroundColor:nil];
-  [self setFaviconContainerBorderColor:nil];
   self.faviconBadgeView.image = nil;
   self.metadataLabel.hidden = YES;
   self.metadataImage.image = nil;
diff --git a/ios/chrome/browser/supervised_user/model/BUILD.gn b/ios/chrome/browser/supervised_user/model/BUILD.gn
index f959d21..3099c13 100644
--- a/ios/chrome/browser/supervised_user/model/BUILD.gn
+++ b/ios/chrome/browser/supervised_user/model/BUILD.gn
@@ -40,6 +40,7 @@
     "//components/supervised_user/core/common",
     "//components/variations/service",
     "//ios/chrome/browser/first_run/model",
+    "//ios/chrome/browser/policy/model:policy_util",
     "//ios/chrome/browser/shared/model/application_context",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/profile",
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.h b/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.h
index d611d4f..fbdb0e5 100644
--- a/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.h
+++ b/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.h
@@ -19,7 +19,7 @@
   // supervised_user::SupervisedUserService::PlatformDelegate
   std::string GetCountryCode() const override;
   version_info::Channel GetChannel() const override;
-
+  bool ShouldCloseIncognitoTabs() const override;
   // Closes all incognito tabs of all windows when supervised users sign in.
   void CloseIncognitoTabs() override;
 
diff --git a/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.mm b/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.mm
index 1aea6313..2dd9dda 100644
--- a/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.mm
+++ b/ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.mm
@@ -5,6 +5,7 @@
 #import "ios/chrome/browser/supervised_user/model/supervised_user_service_platform_delegate.h"
 
 #import "components/variations/service/variations_service.h"
+#import "ios/chrome/browser/policy/model/policy_util.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list.h"
@@ -35,6 +36,10 @@
   return ::GetChannel();
 }
 
+bool SupervisedUserServicePlatformDelegate::ShouldCloseIncognitoTabs() const {
+  return IsIncognitoModeDisabled(profile_->GetPrefs());
+}
+
 void SupervisedUserServicePlatformDelegate::CloseIncognitoTabs() {
   BrowserList* browser_list = BrowserListFactory::GetForProfile(profile_);
   for (Browser* browser :
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn
index 39b9964..ad6a843 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/BUILD.gn
@@ -354,6 +354,7 @@
     "//ios/chrome/browser/drag_and_drop/model",
     "//ios/chrome/browser/main/model",
     "//ios/chrome/browser/saved_tab_groups/model",
+    "//ios/chrome/browser/saved_tab_groups/model:tab_group_service",
     "//ios/chrome/browser/share_kit/model:test_support",
     "//ios/chrome/browser/shared/model/browser",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
@@ -397,6 +398,7 @@
     "//ios/chrome/browser/history/model",
     "//ios/chrome/browser/main/model",
     "//ios/chrome/browser/saved_tab_groups/model",
+    "//ios/chrome/browser/saved_tab_groups/model:tab_group_service",
     "//ios/chrome/browser/sessions/model",
     "//ios/chrome/browser/sessions/model:fake",
     "//ios/chrome/browser/sessions/model:session_restoration_service_factory",
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 df58375..e52e502 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
@@ -26,6 +26,7 @@
 #import "ios/chrome/browser/commerce/model/shopping_persisted_data_tab_helper.h"
 #import "ios/chrome/browser/drag_and_drop/model/drag_item_util.h"
 #import "ios/chrome/browser/main/model/browser_web_state_list_delegate.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/share_kit/model/test_share_kit_service.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list.h"
@@ -59,6 +60,8 @@
 #import "ui/base/l10n/l10n_util_mac.h"
 #import "url/gurl.h"
 
+using tab_groups::SavedTabGroup;
+using tab_groups::SavedTabGroupTab;
 using tab_groups::TabGroupId;
 using testing::_;
 
@@ -74,14 +77,6 @@
 const char kHasPriceDropUserAction[] = "Commerce.TabGridSwitched.HasPriceDrop";
 const char kHasNoPriceDropUserAction[] = "Commerce.TabGridSwitched.NoPriceDrop";
 
-// Returns a test `SavedTabGroup`.
-tab_groups::SavedTabGroup TestSavedGroup() {
-  tab_groups::SavedTabGroup saved_group(
-      u"Test title", tab_groups::TabGroupColorId::kBlue, {}, std::nullopt,
-      base::Uuid::GenerateRandomV4(), tab_groups::TabGroupId::GenerateNew());
-  return saved_group;
-}
-
 }  // namespace
 
 class BaseGridMediatorTest
@@ -98,10 +93,8 @@
       mediator_ =
           [[IncognitoGridMediator alloc] initWithModeHolder:mode_holder_];
     } else {
-      tab_group_sync_service_ =
-          std::make_unique<tab_groups::FakeTabGroupSyncService>();
-      share_kit_service_ =
-          std::make_unique<TestShareKitService>(nullptr, nullptr, nullptr);
+      share_kit_service_ = std::make_unique<TestShareKitService>(
+          nullptr, nullptr, nullptr, tab_group_service_);
       collaboration_service_ =
           std::make_unique<collaboration::MockCollaborationService>();
 
@@ -130,7 +123,6 @@
   }
 
  protected:
-  std::unique_ptr<tab_groups::FakeTabGroupSyncService> tab_group_sync_service_;
   std::unique_ptr<ShareKitService> share_kit_service_;
   std::unique_ptr<collaboration::MockCollaborationService>
       collaboration_service_;
@@ -821,22 +813,22 @@
     return;
   }
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
-
   WebStateList* web_state_list = browser_->GetWebStateList();
   TabGroupId tab_group_id = TabGroupId::GenerateNew();
   web_state_list->CreateGroup({1}, {}, tab_group_id);
   const TabGroup* group = web_state_list->GetGroupOfWebStateAt(1);
+
+  std::optional<SavedTabGroup> saved_group =
+      tab_group_sync_service_->GetGroup(tab_group_id);
+  ASSERT_TRUE(saved_group.has_value());
+  ASSERT_EQ(tab_group_id, saved_group->local_group_id().value());
   EXPECT_EQ(1u, web_state_list->GetGroups().size());
   EXPECT_EQ(3, web_state_list->count());
 
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id, _))
-      .Times(0);
-
   [mediator_ ungroupTabGroup:group];
+  std::optional<SavedTabGroup> updated_group =
+      tab_group_sync_service_->GetGroup(saved_group->saved_guid());
+  ASSERT_FALSE(updated_group.has_value());
   EXPECT_EQ(0u, web_state_list->GetGroups().size());
   EXPECT_EQ(3, web_state_list->count());
 }
@@ -856,20 +848,20 @@
   ASSERT_TRUE(builder.BuildWebStateListFromDescription(
       "| a b c d e f g", other_browser_->GetProfile()));
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
   TabGroupId tab_group_id = TabGroupId::GenerateNew();
   other_web_state_list->CreateGroup({1}, {}, tab_group_id);
   const TabGroup* group = other_web_state_list->GetGroupOfWebStateAt(1);
+  std::optional<SavedTabGroup> saved_group =
+      tab_group_sync_service_->GetGroup(tab_group_id);
+  ASSERT_TRUE(saved_group.has_value());
   EXPECT_EQ(1u, other_web_state_list->GetGroups().size());
   EXPECT_EQ(7, other_web_state_list->count());
 
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id, _))
-      .Times(0);
 
   [mediator_ ungroupTabGroup:group];
+  std::optional<SavedTabGroup> updated_group =
+      tab_group_sync_service_->GetGroup(saved_group->saved_guid());
+  ASSERT_FALSE(updated_group.has_value());
   EXPECT_EQ(0u, other_web_state_list->GetGroups().size());
   EXPECT_EQ(7, other_web_state_list->count());
 }
@@ -882,11 +874,6 @@
     return;
   }
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
-
   TabGroupId tab_group_id = TabGroupId::GenerateNew();
   WebStateList* web_state_list = browser_->GetWebStateList();
   const TabGroup* group = web_state_list->CreateGroup({1}, {}, tab_group_id);
@@ -896,13 +883,17 @@
                                               withWebStateList:web_state_list]];
   EXPECT_EQ(1UL, [mediator_ allSelectedDragItems].count);
 
-  EXPECT_CALL(*mock_service, GetGroup(tab_group_id))
-      .WillOnce(testing::Return(TestSavedGroup()));
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id, _));
-  EXPECT_CALL(*mock_service, RemoveGroup(tab_group_id)).Times(0);
+  std::optional<SavedTabGroup> saved_group =
+      tab_group_sync_service_->GetGroup(tab_group_id);
+  ASSERT_TRUE(saved_group.has_value());
 
   [mediator_ closeItemsWithTabIDs:{} groupIDs:{tab_group_id} tabCount:1];
 
+  std::optional<SavedTabGroup> updated_group =
+      tab_group_sync_service_->GetGroup(saved_group->saved_guid());
+  ASSERT_TRUE(updated_group.has_value());
+  EXPECT_EQ(std::nullopt, updated_group->local_group_id());
+
   EXPECT_EQ(0UL, [mediator_ allSelectedDragItems].count);
 }
 
@@ -914,26 +905,25 @@
     return;
   }
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
-
   WebStateList* web_state_list = browser_->GetWebStateList();
   TabGroupId tab_group_id = TabGroupId::GenerateNew();
   web_state_list->CreateGroup({1}, {}, tab_group_id);
   const TabGroup* group = web_state_list->GetGroupOfWebStateAt(1);
   EXPECT_EQ(1u, web_state_list->GetGroups().size());
 
-  EXPECT_CALL(*mock_service, GetGroup(tab_group_id))
-      .WillOnce(testing::Return(TestSavedGroup()));
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id, _));
-  EXPECT_CALL(*mock_service, RemoveGroup(tab_group_id)).Times(0);
+  std::optional<SavedTabGroup> saved_group =
+      tab_group_sync_service_->GetGroup(tab_group_id);
+  ASSERT_TRUE(saved_group.has_value());
 
   [mediator_ closeItemWithIdentifier:[GridItemIdentifier
                                           groupIdentifier:group
                                          withWebStateList:web_state_list]];
   EXPECT_EQ(0u, web_state_list->GetGroups().size());
+
+  std::optional<SavedTabGroup> updated_group =
+      tab_group_sync_service_->GetGroup(saved_group->saved_guid());
+  ASSERT_TRUE(updated_group.has_value());
+  EXPECT_EQ(std::nullopt, updated_group->local_group_id());
 }
 
 // Tests that closing a group locally from another browser (e.g from Search)
@@ -951,25 +941,25 @@
   ASSERT_TRUE(builder.BuildWebStateListFromDescription(
       "| a b c d e f g", other_browser_->GetProfile()));
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
   TabGroupId tab_group_id = TabGroupId::GenerateNew();
   const TabGroup* group =
       other_web_state_list->CreateGroup({1}, {}, tab_group_id);
   EXPECT_EQ(1u, other_web_state_list->GetGroups().size());
 
-  EXPECT_CALL(*mock_service, GetGroup(tab_group_id))
-      .WillOnce(testing::Return(TestSavedGroup()));
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id, _));
-  EXPECT_CALL(*mock_service, RemoveGroup(tab_group_id)).Times(0);
+  std::optional<SavedTabGroup> saved_group =
+      tab_group_sync_service_->GetGroup(tab_group_id);
+  ASSERT_TRUE(saved_group.has_value());
 
   [mediator_
       closeItemWithIdentifier:[GridItemIdentifier
                                    groupIdentifier:group
                                   withWebStateList:other_web_state_list]];
   EXPECT_EQ(0u, other_web_state_list->GetGroups().size());
+
+  std::optional<SavedTabGroup> updated_group =
+      tab_group_sync_service_->GetGroup(saved_group->saved_guid());
+  ASSERT_TRUE(updated_group.has_value());
+  EXPECT_EQ(std::nullopt, updated_group->local_group_id());
 }
 
 // Tests that closing multiple selected items doesn't delete saved groups.
@@ -986,11 +976,6 @@
   ASSERT_TRUE(builder.BuildWebStateListFromDescription(
       "| a b c [ 1 d e ] [ 2 f g ] h", browser_->GetProfile()));
 
-  tab_groups::MockTabGroupSyncService* mock_service =
-      static_cast<tab_groups::MockTabGroupSyncService*>(
-          tab_groups::TabGroupSyncServiceFactory::GetForProfile(
-              profile_.get()));
-
   const TabGroup* group_1 = builder.GetTabGroupForIdentifier('1');
   const TabGroup* group_2 = builder.GetTabGroupForIdentifier('2');
   TabGroupId tab_group_id_1 = group_1->tab_group_id();
@@ -998,6 +983,13 @@
   web::WebState* web_state_a = builder.GetWebStateForIdentifier('a');
   web::WebState* web_state_b = builder.GetWebStateForIdentifier('b');
 
+  std::optional<SavedTabGroup> saved_group_1 =
+      tab_group_sync_service_->GetGroup(tab_group_id_1);
+  ASSERT_TRUE(saved_group_1.has_value());
+  std::optional<SavedTabGroup> saved_group_2 =
+      tab_group_sync_service_->GetGroup(tab_group_id_2);
+  ASSERT_TRUE(saved_group_2.has_value());
+
   mode_holder_.mode = TabGridMode::kSelection;
   [mediator_
       addToSelectionItemID:[GridItemIdentifier tabIdentifier:web_state_a]];
@@ -1013,20 +1005,20 @@
   // 2 tabs, 2 tab groups.
   EXPECT_EQ(4UL, [mediator_ allSelectedDragItems].count);
 
-  EXPECT_CALL(*mock_service, GetGroup(tab_group_id_1))
-      .WillOnce(testing::Return(TestSavedGroup()));
-  EXPECT_CALL(*mock_service, GetGroup(tab_group_id_2))
-      .WillOnce(testing::Return(TestSavedGroup()));
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id_1, _));
-  EXPECT_CALL(*mock_service, RemoveLocalTabGroupMapping(tab_group_id_2, _));
-  EXPECT_CALL(*mock_service, RemoveGroup(tab_group_id_1)).Times(0);
-  EXPECT_CALL(*mock_service, RemoveGroup(tab_group_id_2)).Times(0);
-
   [mediator_ closeItemsWithTabIDs:{web_state_a->GetUniqueIdentifier(),
                                    web_state_b->GetUniqueIdentifier()}
                          groupIDs:{tab_group_id_1, tab_group_id_2}
                          tabCount:6];
 
+  std::optional<SavedTabGroup> updated_group_1 =
+      tab_group_sync_service_->GetGroup(saved_group_1->saved_guid());
+  ASSERT_TRUE(updated_group_1.has_value());
+  EXPECT_EQ(std::nullopt, updated_group_1->local_group_id());
+  std::optional<SavedTabGroup> updated_group_2 =
+      tab_group_sync_service_->GetGroup(saved_group_2->saved_guid());
+  ASSERT_TRUE(updated_group_2.has_value());
+  EXPECT_EQ(std::nullopt, updated_group_2->local_group_id());
+
   ASSERT_EQ("| c h", builder.GetWebStateListDescription());
   EXPECT_EQ(0UL, [mediator_ allSelectedDragItems].count);
 }
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.h
index 5082f06..65b6818 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.h
@@ -28,10 +28,15 @@
 class IOSChromeScopedTestingLocalState;
 class PlatformTest;
 @class SceneState;
+class TabGroupService;
 class TestProfileIOS;
 class TestSceneUrlLoadingService;
 class UrlLoadingBrowserAgent;
 
+namespace tab_groups {
+class FakeTabGroupSyncService;
+}
+
 namespace web {
 class FakeWebState;
 }  // namespace web
@@ -72,6 +77,8 @@
   std::unique_ptr<TestSceneUrlLoadingService> scene_loader_;
   raw_ptr<UrlLoadingBrowserAgent> loader_;
   FakeURLLoadingDelegate* url_loading_delegate_;
+  raw_ptr<tab_groups::FakeTabGroupSyncService> tab_group_sync_service_;
+  raw_ptr<TabGroupService> tab_group_service_;
 };
 
 #endif  // IOS_CHROME_BROWSER_TAB_SWITCHER_UI_BUNDLED_TAB_GRID_GRID_GRID_MEDIATOR_TEST_H_
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.mm
index 51045bc6..7bbf3f8 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/grid_mediator_test.mm
@@ -6,10 +6,15 @@
 
 #import "base/containers/contains.h"
 #import "base/test/ios/wait_util.h"
+#import "components/saved_tab_groups/test_support/fake_tab_group_sync_service.h"
 #import "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h"
 #import "components/unified_consent/pref_names.h"
 #import "ios/chrome/browser/history/model/history_service_factory.h"
 #import "ios/chrome/browser/main/model/browser_web_state_list_delegate.h"
+#import "ios/chrome/browser/saved_tab_groups/model/ios_tab_group_sync_delegate.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_local_update_observer.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service_factory.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/sessions/model/fake_tab_restore_service.h"
 #import "ios/chrome/browser/sessions/model/ios_chrome_tab_restore_service_factory.h"
@@ -67,10 +72,28 @@
     web::ContentWorld::kIsolatedWorld,
 };
 
-// Returns a `MockTabGroupSyncService`.
-std::unique_ptr<KeyedService> CreateMockTabGroupSyncService(
+// Returns a `FakeTabGroupSyncService`.
+std::unique_ptr<KeyedService> CreateFakeTabGroupSyncService(
     web::BrowserState* context) {
-  return std::make_unique<tab_groups::MockTabGroupSyncService>();
+  ProfileIOS* profile = ProfileIOS::FromBrowserState(context);
+
+  std::unique_ptr<tab_groups::TabGroupSyncService> tab_group_sync_service =
+      std::make_unique<tab_groups::FakeTabGroupSyncService>();
+
+  BrowserList* browser_list = BrowserListFactory::GetForProfile(profile);
+  std::unique_ptr<tab_groups::TabGroupLocalUpdateObserver>
+      local_update_observer =
+          std::make_unique<tab_groups::TabGroupLocalUpdateObserver>(
+              browser_list, tab_group_sync_service.get());
+
+  std::unique_ptr<tab_groups::IOSTabGroupSyncDelegate> delegate =
+      std::make_unique<tab_groups::IOSTabGroupSyncDelegate>(
+          browser_list, tab_group_sync_service.get(),
+          std::move(local_update_observer));
+
+  tab_group_sync_service->SetTabGroupSyncDelegate(std::move(delegate));
+
+  return std::move(tab_group_sync_service);
 }
 }  // namespace
 
@@ -98,10 +121,13 @@
                             TestSessionRestorationService::GetTestingFactory());
   builder.AddTestingFactory(
       tab_groups::TabGroupSyncServiceFactory::GetInstance(),
-      base::BindRepeating(&CreateMockTabGroupSyncService));
+      base::BindRepeating(&CreateFakeTabGroupSyncService));
   builder.AddTestingFactory(TipsManagerIOSFactory::GetInstance(),
                             TipsManagerIOSFactory::GetDefaultFactory());
   profile_ = std::move(builder).Build();
+  tab_group_sync_service_ = static_cast<tab_groups::FakeTabGroupSyncService*>(
+      tab_groups::TabGroupSyncServiceFactory::GetForProfile(profile_.get()));
+  tab_group_service_ = TabGroupServiceFactory::GetForProfile(profile_.get());
   // Price Drops are only available to signed in MSBB users.
   profile_->GetPrefs()->SetBoolean(
       unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled, true);
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn
index bf21e9f..17b0b1b 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/BUILD.gn
@@ -106,6 +106,7 @@
     "//ios/chrome/browser/collaboration/model/messaging",
     "//ios/chrome/browser/history/model",
     "//ios/chrome/browser/policy/model:policy_util",
+    "//ios/chrome/browser/saved_tab_groups/model:tab_group_service",
     "//ios/chrome/browser/sessions/model",
     "//ios/chrome/browser/share_kit/model:test_support",
     "//ios/chrome/browser/shared/model/browser/test:test_support",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm
index 43bb40f..852801d9 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/grid/regular/regular_grid_mediator_unittest.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/collaboration/model/messaging/messaging_backend_service_bridge.h"
 #import "ios/chrome/browser/history/model/history_service_factory.h"
 #import "ios/chrome/browser/policy/model/policy_util.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service.h"
 #import "ios/chrome/browser/sessions/model/ios_chrome_tab_restore_service_factory.h"
 #import "ios/chrome/browser/share_kit/model/test_share_kit_service.h"
 #import "ios/chrome/browser/shared/model/browser/test/test_browser.h"
@@ -66,10 +67,8 @@
 
     GridMediatorTestClass::SetUp();
     mode_holder_ = [[TabGridModeHolder alloc] init];
-    tab_group_sync_service_ =
-        std::make_unique<tab_groups::FakeTabGroupSyncService>();
-    share_kit_service_ =
-        std::make_unique<TestShareKitService>(nullptr, nullptr, nullptr);
+    share_kit_service_ = std::make_unique<TestShareKitService>(
+        nullptr, nullptr, nullptr, tab_group_service_);
     collaboration_service_ =
         std::make_unique<collaboration::MockCollaborationService>();
 
@@ -96,7 +95,6 @@
  protected:
   base::test::ScopedFeatureList scoped_feature_list_;
   TestRegularGridMediator* mediator_ = nullptr;
-  std::unique_ptr<tab_groups::FakeTabGroupSyncService> tab_group_sync_service_;
   std::unique_ptr<ShareKitService> share_kit_service_;
   std::unique_ptr<collaboration::MockCollaborationService>
       collaboration_service_;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn
index 48b42974..dbc5fe3 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/BUILD.gn
@@ -295,6 +295,7 @@
     "//ios/chrome/browser/main/model",
     "//ios/chrome/browser/policy/model:policy_util",
     "//ios/chrome/browser/saved_tab_groups/model",
+    "//ios/chrome/browser/saved_tab_groups/model:tab_group_service",
     "//ios/chrome/browser/share_kit/model:constants",
     "//ios/chrome/browser/share_kit/model:factory",
     "//ios/chrome/browser/share_kit/model:test_support",
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator_unittest.mm
index cd0e03cd..d81add59 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_coordinator_unittest.mm
@@ -10,6 +10,7 @@
 #import "components/saved_tab_groups/test_support/fake_tab_group_sync_service.h"
 #import "components/tab_groups/tab_group_id.h"
 #import "ios/chrome/browser/data_sharing/model/data_sharing_service_factory.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service_factory.h"
 #import "ios/chrome/browser/saved_tab_groups/model/tab_group_sync_service_factory.h"
 #import "ios/chrome/browser/share_kit/model/share_kit_service_factory.h"
 #import "ios/chrome/browser/share_kit/model/test_share_kit_service.h"
@@ -60,9 +61,11 @@
   ProfileIOS* profile = static_cast<ProfileIOS*>(context);
   data_sharing::DataSharingService* data_sharing_service =
       data_sharing::DataSharingServiceFactory::GetForProfile(profile);
+  TabGroupService* tab_group_service =
+      TabGroupServiceFactory::GetForProfile(profile);
 
   return std::make_unique<TestShareKitService>(data_sharing_service, nullptr,
-                                               nullptr);
+                                               nullptr, tab_group_service);
 }
 
 class TabGroupCoordinatorTest : public PlatformTest {
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_mediator_unittest.mm
index e46b7a4..bb10716 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_group_mediator_unittest.mm
@@ -22,6 +22,7 @@
 #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/main/model/browser_web_state_list_delegate.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service.h"
 #import "ios/chrome/browser/share_kit/model/test_share_kit_service.h"
 #import "ios/chrome/browser/shared/model/browser/browser.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list.h"
@@ -102,10 +103,8 @@
     mode_holder_ = [[TabGridModeHolder alloc] init];
     tab_group_ = web_state_list->GetGroupOfWebStateAt(1);
     tab_group_consumer_ = OCMProtocolMock(@protocol(TabGroupConsumer));
-    tab_group_sync_service_ =
-        std::make_unique<tab_groups::FakeTabGroupSyncService>();
-    share_kit_service_ =
-        std::make_unique<TestShareKitService>(nullptr, nullptr, nullptr);
+    share_kit_service_ = std::make_unique<TestShareKitService>(
+        nullptr, nullptr, nullptr, tab_group_service_);
     collaboration_service_ =
         std::make_unique<collaboration::MockCollaborationService>();
     data_sharing_service_ = std::make_unique<
@@ -153,7 +152,6 @@
   id<TabGroupConsumer> tab_group_consumer_;
   raw_ptr<const TabGroup> tab_group_;
   std::unique_ptr<WebStateListBuilderFromDescription> builder_;
-  std::unique_ptr<tab_groups::FakeTabGroupSyncService> tab_group_sync_service_;
   std::unique_ptr<ShareKitService> share_kit_service_;
   std::unique_ptr<collaboration::MockCollaborationService>
       collaboration_service_;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_panel_mediator_unittest.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_panel_mediator_unittest.mm
index 9b0b2eb..5452e442 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_panel_mediator_unittest.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/tab_groups/tab_groups_panel_mediator_unittest.mm
@@ -17,6 +17,7 @@
 #import "components/saved_tab_groups/test_support/mock_tab_group_sync_service.h"
 #import "components/saved_tab_groups/test_support/saved_tab_group_test_utils.h"
 #import "components/strings/grit/components_strings.h"
+#import "ios/chrome/browser/saved_tab_groups/model/tab_group_service.h"
 #import "ios/chrome/browser/share_kit/model/test_share_kit_service.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list.h"
 #import "ios/chrome/browser/shared/model/browser/browser_list_factory.h"
@@ -120,8 +121,10 @@
     browser_list_ = BrowserListFactory::GetForProfile(profile_.get());
     browser_list_->AddBrowser(browser_.get());
     mode_holder_ = [[TabGridModeHolder alloc] init];
-    share_kit_service_ =
-        std::make_unique<TestShareKitService>(nullptr, nullptr, nullptr);
+    tab_group_service_ = std::make_unique<TabGroupService>(
+        profile_.get(), &tab_group_sync_service_);
+    share_kit_service_ = std::make_unique<TestShareKitService>(
+        nullptr, nullptr, nullptr, tab_group_service_.get());
     collaboration_service_ = std::make_unique<MockCollaborationService>();
     messaging_service_ = std::make_unique<MockMessagingBackendService>();
     data_sharing_service_ = std::make_unique<
@@ -135,6 +138,7 @@
   FakeWebStateListDelegate web_state_list_delegate_;
   WebStateList web_state_list_;
   ::testing::NiceMock<MockTabGroupSyncService> tab_group_sync_service_;
+  std::unique_ptr<TabGroupService> tab_group_service_;
   TabGridModeHolder* mode_holder_;
   std::unique_ptr<ShareKitService> share_kit_service_;
   std::unique_ptr<MockCollaborationService> collaboration_service_;
diff --git a/ios/chrome/common/ui/favicon/favicon_container_view.h b/ios/chrome/common/ui/favicon/favicon_container_view.h
index 4a19058..7ddb2c384 100644
--- a/ios/chrome/common/ui/favicon/favicon_container_view.h
+++ b/ios/chrome/common/ui/favicon/favicon_container_view.h
@@ -9,16 +9,15 @@
 
 @class FaviconView;
 
+// Container view that displays a `faviconView`.
 @interface FaviconContainerView : UIView
 
+// the `faviconView` to to display.
 @property(nonatomic, readonly, strong) FaviconView* faviconView;
 
 // Sets the favicon's background color. Can be nil to reset to original value.
 - (void)setFaviconBackgroundColor:(UIColor*)color;
 
-// Sets the favicon view border color. Can be nil to reset to original value.
-- (void)setFaviconBorderColor:(UIColor*)color;
-
 @end
 
 #endif  // IOS_CHROME_COMMON_UI_FAVICON_FAVICON_CONTAINER_VIEW_H_
diff --git a/ios/chrome/common/ui/favicon/favicon_container_view.mm b/ios/chrome/common/ui/favicon/favicon_container_view.mm
index 8210286..d5429d6 100644
--- a/ios/chrome/common/ui/favicon/favicon_container_view.mm
+++ b/ios/chrome/common/ui/favicon/favicon_container_view.mm
@@ -15,8 +15,6 @@
 const CGFloat kFaviconWidth = 16;
 // Corner radius of the favicon ImageView.
 const CGFloat kFaviconCornerRadius = 7.0;
-// Width of the favicon border ImageView.
-const CGFloat kFaviconBorderWidth = 1.5;
 // The width and height of the favicon container view.
 const CGFloat kFaviconContainerWidth = 30;
 }  // namespace
@@ -26,9 +24,6 @@
 // Store custom background color.
 @property(nonatomic, strong) UIColor* customBackgroundColor;
 
-// Store custom border color.
-@property(nonatomic, strong) UIColor* customBorderColor;
-
 @end
 
 @implementation FaviconContainerView
@@ -39,7 +34,6 @@
     [self.traitCollection performAsCurrentTraitCollection:^{
       [self resetColor];
     }];
-    self.layer.borderWidth = kFaviconBorderWidth;
     self.layer.cornerRadius = kFaviconCornerRadius;
     self.layer.masksToBounds = YES;
 
@@ -88,15 +82,6 @@
   }
 }
 
-- (void)setFaviconBorderColor:(UIColor*)color {
-  self.customBorderColor = color;
-  if (color) {
-    self.layer.borderColor = color.CGColor;
-  } else {
-    [self resetColor];
-  }
-}
-
 #if !defined(__IPHONE_17_0) || __IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_17_0
 - (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
   [super traitCollectionDidChange:previousTraitCollection];
@@ -114,12 +99,9 @@
   } else {
     self.backgroundColor =
         self.traitCollection.userInterfaceStyle == UIUserInterfaceStyleDark
-            ? [UIColor colorNamed:kSeparatorColor]
-            : UIColor.clearColor;
+            ? [UIColor colorNamed:kPrimaryBackgroundColor]
+            : [UIColor colorNamed:kSecondaryBackgroundColor];
   }
-  self.layer.borderColor = self.customBorderColor
-                               ? self.customBorderColor.CGColor
-                               : [UIColor colorNamed:kSeparatorColor].CGColor;
 }
 
 #pragma mark - Private
diff --git a/ios/chrome/credential_provider_extension/ui/multi_profile_passkey_creation_view_controller.mm b/ios/chrome/credential_provider_extension/ui/multi_profile_passkey_creation_view_controller.mm
index 6919aa2..d9774e5a 100644
--- a/ios/chrome/credential_provider_extension/ui/multi_profile_passkey_creation_view_controller.mm
+++ b/ios/chrome/credential_provider_extension/ui/multi_profile_passkey_creation_view_controller.mm
@@ -221,8 +221,6 @@
 - (UIView*)iconView {
   FaviconContainerView* faviconContainerView =
       [[FaviconContainerView alloc] init];
-  [faviconContainerView setFaviconBackgroundColor:GetBackgroundColor()];
-  [faviconContainerView setFaviconBorderColor:[UIColor clearColor]];
   _faviconView = faviconContainerView.faviconView;
   return faviconContainerView;
 }
diff --git a/ios/chrome/test/earl_grey/eg_tests_hook.mm b/ios/chrome/test/earl_grey/eg_tests_hook.mm
index 1a55a9a..9a19e40 100644
--- a/ios/chrome/test/earl_grey/eg_tests_hook.mm
+++ b/ios/chrome/test/earl_grey/eg_tests_hook.mm
@@ -232,9 +232,11 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service) {
-  return std::make_unique<TestShareKitService>(
-      data_sharing_service, collaboration_service, sync_service);
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service) {
+  return std::make_unique<TestShareKitService>(data_sharing_service,
+                                               collaboration_service,
+                                               sync_service, tab_group_service);
 }
 
 std::unique_ptr<password_manager::BulkLeakCheckServiceInterface>
diff --git a/ios/chrome/test/providers/share_kit/test_share_kit.mm b/ios/chrome/test/providers/share_kit/test_share_kit.mm
index 981a062..a274a524e 100644
--- a/ios/chrome/test/providers/share_kit/test_share_kit.mm
+++ b/ios/chrome/test/providers/share_kit/test_share_kit.mm
@@ -14,7 +14,7 @@
     std::unique_ptr<ShareKitServiceConfiguration> configuration) {
   return std::make_unique<TestShareKitService>(
       configuration->data_sharing_service, configuration->collaboration_service,
-      configuration->sync_service);
+      configuration->sync_service, configuration->tab_group_service);
 }
 
 }  // namespace ios::provider
diff --git a/ios/chrome/test/wpt/cwt_tests_hook.mm b/ios/chrome/test/wpt/cwt_tests_hook.mm
index bde92e1..a2e04d5 100644
--- a/ios/chrome/test/wpt/cwt_tests_hook.mm
+++ b/ios/chrome/test/wpt/cwt_tests_hook.mm
@@ -75,7 +75,8 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service) {
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service) {
   return nullptr;
 }
 std::unique_ptr<password_manager::BulkLeakCheckServiceInterface>
diff --git a/ios/chrome/test/xcuitest/xcuitests_hook.mm b/ios/chrome/test/xcuitest/xcuitests_hook.mm
index 8a781136..764415f 100644
--- a/ios/chrome/test/xcuitest/xcuitests_hook.mm
+++ b/ios/chrome/test/xcuitest/xcuitests_hook.mm
@@ -91,7 +91,8 @@
 std::unique_ptr<ShareKitService> CreateShareKitService(
     data_sharing::DataSharingService* data_sharing_service,
     collaboration::CollaborationService* collaboration_service,
-    tab_groups::TabGroupSyncService* sync_service) {
+    tab_groups::TabGroupSyncService* sync_service,
+    TabGroupService* tab_group_service) {
   return nullptr;
 }
 
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
index db6f747..3f2a3456 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-1df063c53d3657a2b2110684183e56d02b6c7d98
\ No newline at end of file
+b653d2068296c5a9b8ca2600a0092c1d88a10f9a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
index 9038751..936a4d7 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-fb621f01cdac9baa453e10c944bca56ebf853484
\ No newline at end of file
+d1ff2636bf48bfc37b306bab5a0eda4c7097f104
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index 5cae885..db34df670 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-4fe9a6ac3079ccd871fa953f6de5e2827ed83fa8
\ No newline at end of file
+f3c8104cd286b3c0616f409e1e4eab76000850ba
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
index 29c7d0ba..5ef8c9d 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-3470de930665aa2293303d43c3253190084f4c9e
\ No newline at end of file
+a6ab0c505a483e04732d62ace85866775daeaadf
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index 3501a5e..9867829 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-cb5575edbf8de51802df05abe3ec3aa2b3fc6e91
\ No newline at end of file
+b8d813cfeb881d7953e530668b013a83288a2f6d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
index f3892cc..e44f11d 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-d02a2324ec4fc3dc20ec655731fa8a04b83c1803
\ No newline at end of file
+b9a13ea6b1abd838ddfdf1ea7288e82602dd5203
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
index 01f0eca..afe7a2c 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-d63d051e7a8b85e885216106f9c5ba051772fb12
\ No newline at end of file
+737e330a27c092746237f9ff9e138cd757093ea6
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
index 01b2e65..39ae301 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-12232483b1bf4e73c55ed5a2aac1504a512f3f07
\ No newline at end of file
+cc6c50b9fdb307ce0ece38f3f3bb32e312d695e8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
index 0c07710..36b73add 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-ff1ce51492661a565cb81bc5c72a8a3aa8201a0f
\ No newline at end of file
+f582ef95beb26eb474950a9843709626b00bc1c4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
index cc53a7a..940d15b 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-8d26142a10f353114b976581a93f5d9d06294fc3
\ No newline at end of file
+6f76aa2962a06fdccd001f78ecf7c52fde13f18e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 63386ec4..2a842bc 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-d1a398ad8954fa0c9c3bee83a477789a2fab9e4c
\ No newline at end of file
+89c35665357aad688d00d06be9f046ec34a7e398
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
index 73426ab..f15f0dd9 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-2a4153c6c053256dc022f2ffe433e945579e226a
\ No newline at end of file
+729545f0190187028315a1fd31cd8abcd9726ed8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index c68380ea..233b9d1 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-905826404b3379f6c0a2264a2ecc57500c17a673
\ No newline at end of file
+d75f396ecd905cb2ba09af0c9d4a9a056bd36ee0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 285b9a4..12174ec 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-07038458237b28c7f438b57ff7375b4aeb560b5b
\ No newline at end of file
+c54f048859a25a0a190637dca153693a54f34d22
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 3dfc283..56da5f0 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-746b413cf414a304cc96cad8e59418967e79b0a1
\ No newline at end of file
+2564c9d44084a7bdb174048ebd8af6c1698fa4e1
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
index 0784a44..037f043 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-20d723a8f8b0d33675bac4aca7ea886dcd926a3a
\ No newline at end of file
+f59cfc2e47c98a8f998670ede8609bb40dac232f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index cebbbfc..1dd0a74 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-fcd383cf7ee754cd40afb3abf2aed48550956944
\ No newline at end of file
+23231f14b226595f1c7f82920ebb53e05d3ae313
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 9147bedf..561bbe9 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-40617e0b7668cd8c71da8a8c9abb4aaa15530ba1
\ No newline at end of file
+49ddfee2fc26070a633fa06e85881eed6d83f3f2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index 212cd4b..33325bf 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-e2a4847fc02afa2f4454b91391adce20a4d1572a
\ No newline at end of file
+5f3ef81c7c6ad91570e7373b0d5f42e0832a281b
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index 4dbb828..361a2e0 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-34cf7d6b3a97e04eec001876eade1a7a88d43306
\ No newline at end of file
+b7cb031488ad4452af26e1d32f7b015aed4940d5
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 360df5dc..5fe6d9f 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-93880b3afa88424d550c4805f246d5ecbc4f2009
\ No newline at end of file
+94c7ce17085c8e91b0d7df05cb0786a77d18a00f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
index e9af87c..afb99beb 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-fab65e366af2801c14e3e9d25ab911c675d217ac
\ No newline at end of file
+7f8ab814a52da5c2088202506f8cb10581eacc95
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index b847e7b..b4653b7 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-e109a219cc4a82e9546ac6041b39d121f7646df6
\ No newline at end of file
+b0347dbde19acf09afe72b01d106a1ce088288bc
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
index acc042e..2645f38b 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-0d6ff97799443044f0f7bf3e3c3067a6aae93ae0
\ No newline at end of file
+313799b6e11f272350ca7d3cdb70f12b46c3a77f
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 27083a65..36c3a8b0 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-f14ae25985b551ac7c9e2253caed0d99da11a20d
\ No newline at end of file
+958268ce0634240c85a0bc196d47ee66e5d1d331
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
index 9b10657..2659177 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-35b8fcd2f9f2ac5b660729b6e1995189ba4ea96e
\ No newline at end of file
+b498c9d5b59d6cbec79535bd9f4113825905efc4
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 7e682a89..baa33b8a 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-4574007793a1f677d1d9f6bd1a8cad92943320cd
\ No newline at end of file
+bb41226f39d20b182efb50b85be74d48ca5d6e56
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
index a3861a9b..e095c18 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-6b710694f1c7eb0aade5a8a482bb81d6ca0e3d2f
\ No newline at end of file
+da82b0057ccde50f5ed4bffb5701f6900099b1bf
\ No newline at end of file
diff --git a/ios/third_party/material_components_ios/src b/ios/third_party/material_components_ios/src
index a33768e6..f93b1dc 160000
--- a/ios/third_party/material_components_ios/src
+++ b/ios/third_party/material_components_ios/src
@@ -1 +1 @@
-Subproject commit a33768e63142497497c73383accc8d7254aa4dc9
+Subproject commit f93b1dcc0fd51e78a968e6823f02746f2938e1ec
diff --git a/ios/web/navigation/crw_wk_navigation_handler.mm b/ios/web/navigation/crw_wk_navigation_handler.mm
index 67bfd1b..623c3f23 100644
--- a/ios/web/navigation/crw_wk_navigation_handler.mm
+++ b/ios/web/navigation/crw_wk_navigation_handler.mm
@@ -2046,7 +2046,8 @@
 - (BOOL)shouldCancelLoadForCancelledError:(NSError*)error
                           provisionalLoad:(BOOL)provisionalLoad {
   DCHECK(error.code == NSURLErrorCancelled ||
-         error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange);
+         error.code == web::kWebKitErrorFrameLoadInterruptedByPolicyChange)
+      << base::SysNSStringToUTF8(error.description);
   // Do not cancel the load if it is for an app specific URL, as such errors
   // are produced during the app specific URL load process.
   const GURL errorURL =
diff --git a/ios_internal b/ios_internal
index 04489da..d107d1b 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 04489da71ef10228a79347ccfd484cfed4f613d3
+Subproject commit d107d1bf097cecf3dc2979e13d92a3361bcdf5f8
diff --git a/media/audio/android/audio_android_unittest.cc b/media/audio/android/audio_android_unittest.cc
index a4746c00..550a2b7b 100644
--- a/media/audio/android/audio_android_unittest.cc
+++ b/media/audio/android/audio_android_unittest.cc
@@ -21,13 +21,16 @@
 #include "base/synchronization/lock.h"
 #include "base/synchronization/waitable_event.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "media/audio/android/aaudio_stream_wrapper.h"
 #include "media/audio/android/audio_manager_android.h"
 #include "media/audio/audio_device_description.h"
 #include "media/audio/audio_device_info_accessor_for_tests.h"
+#include "media/audio/audio_features.h"
 #include "media/audio/audio_io.h"
 #include "media/audio/audio_unittest_util.h"
 #include "media/audio/mock_audio_source_callback.h"
@@ -50,8 +53,9 @@
 namespace {
 
 ACTION_P4(CheckCountAndPostQuitTask, count, limit, task_runner, quit_closure) {
-  if (++*count >= limit)
+  if (++*count >= limit) {
     task_runner->PostTask(FROM_HERE, quit_closure);
+  }
 }
 
 constexpr float kCallbackTestTimeMs = 2000.0;
@@ -159,6 +163,20 @@
   return os;
 }
 
+enum class AudioApi { AAudio, OpenSLES };
+
+std::ostream& operator<<(std::ostream& os, const AudioApi& audio_api) {
+  switch (audio_api) {
+    case AudioApi::AAudio:
+      os << "AAudio";
+      break;
+    case AudioApi::OpenSLES:
+      os << "OpenSLES";
+      break;
+  }
+  return os;
+}
+
 // Gmock implementation of AudioInputStream::AudioInputCallback.
 class MockAudioInputCallback : public AudioInputStream::AudioInputCallback {
  public:
@@ -221,8 +239,9 @@
     }
 
     // Set event to ensure that the test can stop when the file has ended.
-    if (stop_playing)
+    if (stop_playing) {
       event_->Signal();
+    }
 
     return frames;
   }
@@ -363,8 +382,9 @@
     // We add an initial delay of ~1 second before loopback starts to ensure
     // a stable callback sequence and to avoid initial bursts which might add
     // to the extra FIFO delay.
-    if (!started_)
+    if (!started_) {
       return;
+    }
 
     // Append new data to the FIFO and extend the size if the max capacity
     // was exceeded. Flush the FIFO when extended just in case.
@@ -426,8 +446,9 @@
   bool started_ = false;
 };
 
-// Test fixture class for tests which only exercise the output path.
-class AudioAndroidOutputTest : public testing::Test {
+// Test fixture class for tests which only exercise the output path. It is
+// value-parameterized to test against both the AAudio and OpenSLES paths.
+class AudioAndroidOutputTest : public testing::TestWithParam<AudioApi> {
  public:
   AudioAndroidOutputTest()
       : task_environment_(
@@ -438,6 +459,10 @@
         audio_output_stream_(nullptr) {
     // Flush the message loop to ensure that AudioManager is fully initialized.
     base::RunLoop().RunUntilIdle();
+
+    if (HasParam()) {
+      InitFeatures(GetParam());
+    }
   }
 
   AudioAndroidOutputTest(const AudioAndroidOutputTest&) = delete;
@@ -453,8 +478,32 @@
   AudioDeviceInfoAccessorForTests* audio_manager_device_info() {
     return &audio_manager_device_info_;
   }
-  const AudioParameters& audio_output_parameters() {
-    return audio_output_parameters_;
+
+  // Returns whether the test is running with a parameter, meaning GetParam()
+  // has a valid value.
+  bool HasParam() {
+    return testing::UnitTest::GetInstance()
+               ->current_test_info()
+               ->value_param() != nullptr;
+  }
+
+  void InitFeatures(AudioApi audio_api) {
+    const std::vector<base::test::FeatureRef> aaudio_features = {
+        features::kUseAAudioDriver, features::kUseAAudioInput};
+    switch (audio_api) {
+      case AudioApi::AAudio:
+        if (!__builtin_available(android AAUDIO_MIN_API, *)) {
+          GTEST_SKIP() << "AAudio is not available.";
+        }
+        feature_list_.InitWithFeatures(aaudio_features, {});
+        break;
+      case AudioApi::OpenSLES:
+#if !BUILDFLAG(USE_OPENSLES)
+        GTEST_SKIP() << "OpenSLES is disabled.";
+#endif
+        feature_list_.InitWithFeatures({}, aaudio_features);
+        break;
+    }
   }
 
   // Synchronously runs the provided callback/closure on the audio thread.
@@ -480,7 +529,7 @@
     event->Signal();
   }
 
-  void GetDefaultOutputStreamParametersOnAudioThread() {
+  AudioParameters GetDefaultOutputStreamParametersOnAudioThread() {
     RunOnAudioThread(base::BindOnce(
         [](AudioAndroidOutputTest* self) {
           std::string default_device_id =
@@ -491,6 +540,15 @@
           EXPECT_TRUE(self->audio_output_parameters_.IsValid());
         },
         base::Unretained(this)));
+    return audio_output_parameters_;
+  }
+
+  AudioDeviceDescriptions GetAudioOutputDeviceDescriptionsOnAudioThread() {
+    AudioDeviceDescriptions devices;
+    RunOnAudioThread(base::BindOnce(
+        &AudioDeviceInfoAccessorForTests::GetAudioOutputDeviceDescriptions,
+        base::Unretained(audio_manager_device_info()), &devices));
+    return devices;
   }
 
   void MakeAudioOutputStreamOnAudioThread(const AudioParameters& params) {
@@ -498,6 +556,11 @@
                                     base::Unretained(this), params));
   }
 
+  void CloseAudioOutputStreamOnAudioThread(raw_ptr<AudioOutputStream> stream) {
+    RunOnAudioThread(
+        base::BindOnce(&AudioOutputStream::Close, base::Unretained(stream)));
+  }
+
   void OpenAndCloseAudioOutputStreamOnAudioThread() {
     RunOnAudioThread(base::BindOnce(&AudioAndroidOutputTest::OpenAndClose,
                                     base::Unretained(this)));
@@ -587,6 +650,7 @@
     audio_output_stream_ = nullptr;
   }
 
+  base::test::ScopedFeatureList feature_list_;
   base::test::SingleThreadTaskEnvironment task_environment_;
   std::unique_ptr<AudioManager> audio_manager_;
   AudioDeviceInfoAccessorForTests audio_manager_device_info_;
@@ -597,10 +661,9 @@
 };
 
 // Test fixture class for tests which exercise the input path, or both input and
-// output paths. It is value-parameterized to test against both the Java
-// AudioRecord (when true) and native OpenSLES (when false) input paths.
-class AudioAndroidInputTest : public AudioAndroidOutputTest,
-                              public testing::WithParamInterface<bool> {
+// output paths. It is value-parameterized to test against both the AAudio and
+// OpenSLES paths.
+class AudioAndroidInputTest : public AudioAndroidOutputTest {
  public:
   AudioAndroidInputTest() : audio_input_stream_(nullptr) {}
 
@@ -608,26 +671,19 @@
   AudioAndroidInputTest& operator=(const AudioAndroidInputTest&) = delete;
 
  protected:
-  const AudioParameters& audio_input_parameters() {
-    return audio_input_parameters_;
-  }
-
-  AudioParameters GetInputStreamParameters() {
-    GetDefaultInputStreamParametersOnAudioThread();
-
-    AudioParameters params = audio_input_parameters();
-
-    // Only the AudioRecord path supports effects, so we can force it to be
-    // selected for the test by requesting one. OpenSLES is used otherwise.
-    params.set_effects(GetParam() ? AudioParameters::ECHO_CANCELLER
-                                  : AudioParameters::NO_EFFECTS);
-    return params;
-  }
-
-  void GetDefaultInputStreamParametersOnAudioThread() {
+  AudioParameters GetDefaultInputStreamParametersOnAudioThread() {
     RunOnAudioThread(
         base::BindOnce(&AudioAndroidInputTest::GetDefaultInputStreamParameters,
                        base::Unretained(this)));
+    return audio_input_parameters_;
+  }
+
+  AudioDeviceDescriptions GetAudioInputDeviceDescriptionsOnAudioThread() {
+    AudioDeviceDescriptions devices;
+    RunOnAudioThread(base::BindOnce(
+        &AudioDeviceInfoAccessorForTests::GetAudioInputDeviceDescriptions,
+        base::Unretained(audio_manager_device_info()), &devices));
+    return devices;
   }
 
   void MakeAudioInputStreamOnAudioThread(const AudioParameters& params) {
@@ -635,6 +691,11 @@
                                     base::Unretained(this), params));
   }
 
+  void CloseAudioInputStreamOnAudioThread(raw_ptr<AudioInputStream> stream) {
+    RunOnAudioThread(
+        base::BindOnce(&AudioInputStream::Close, base::Unretained(stream)));
+  }
+
   void OpenAndCloseAudioInputStreamOnAudioThread() {
     RunOnAudioThread(base::BindOnce(&AudioAndroidInputTest::OpenAndClose,
                                     base::Unretained(this)));
@@ -732,90 +793,88 @@
   AudioParameters audio_input_parameters_;
 };
 
-// Get the default audio input parameters and log the result.
-TEST_P(AudioAndroidInputTest, GetDefaultInputStreamParameters) {
-  // We don't go through AudioAndroidInputTest::GetInputStreamParameters() here
-  // so that we can log the real (non-overridden) values of the effects.
-  GetDefaultInputStreamParametersOnAudioThread();
-  EXPECT_TRUE(audio_input_parameters().IsValid());
-  DVLOG(1) << audio_input_parameters();
+// Get the default audio input parameters.
+TEST_F(AudioAndroidInputTest, GetDefaultInputStreamParameters) {
+  AudioParameters params = GetDefaultInputStreamParametersOnAudioThread();
+  EXPECT_TRUE(params.IsValid());
+}
+
+// Get the default audio output parameters.
+TEST_F(AudioAndroidOutputTest, GetDefaultOutputStreamParameters) {
+  AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread();
+  EXPECT_TRUE(params.IsValid());
 }
 
 // Verify input device enumeration.
 TEST_F(AudioAndroidInputTest, GetAudioInputDeviceDescriptions) {
   ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info()->HasAudioInputDevices());
-  AudioDeviceDescriptions devices;
-  RunOnAudioThread(base::BindOnce(
-      &AudioDeviceInfoAccessorForTests::GetAudioInputDeviceDescriptions,
-      base::Unretained(audio_manager_device_info()), &devices));
+  AudioDeviceDescriptions devices =
+      GetAudioInputDeviceDescriptionsOnAudioThread();
   CheckDeviceDescriptions(devices);
 }
 
 // Verify output device enumeration.
 TEST_F(AudioAndroidOutputTest, GetAudioOutputDeviceDescriptions) {
   ABORT_AUDIO_TEST_IF_NOT(audio_manager_device_info()->HasAudioOutputDevices());
-  AudioDeviceDescriptions devices;
-  RunOnAudioThread(base::BindOnce(
-      &AudioDeviceInfoAccessorForTests::GetAudioOutputDeviceDescriptions,
-      base::Unretained(audio_manager_device_info()), &devices));
+  AudioDeviceDescriptions devices =
+      GetAudioOutputDeviceDescriptionsOnAudioThread();
   CheckDeviceDescriptions(devices);
 }
 
 // Ensure that a default input stream can be created and closed.
 TEST_P(AudioAndroidInputTest, CreateAndCloseInputStream) {
-  AudioParameters params = GetInputStreamParameters();
+  AudioParameters params = GetDefaultInputStreamParametersOnAudioThread();
   MakeAudioInputStreamOnAudioThread(params);
-  RunOnAudioThread(base::BindOnce(&AudioInputStream::Close,
-                                  base::Unretained(audio_input_stream_)));
+  CloseAudioInputStreamOnAudioThread(audio_input_stream_);
 }
 
 // Ensure that a default output stream can be created and closed.
 // TODO(henrika): should we also verify that this API changes the audio mode
 // to communication mode, and calls RegisterHeadsetReceiver, the first time
 // it is called?
-TEST_F(AudioAndroidOutputTest, CreateAndCloseOutputStream) {
-  GetDefaultOutputStreamParametersOnAudioThread();
-  MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
-  RunOnAudioThread(base::BindOnce(&AudioOutputStream::Close,
-                                  base::Unretained(audio_output_stream_)));
+TEST_P(AudioAndroidOutputTest, CreateAndCloseOutputStream) {
+  AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread();
+  MakeAudioOutputStreamOnAudioThread(params);
+  CloseAudioOutputStreamOnAudioThread(audio_output_stream_);
 }
 
 // Ensure that a default input stream can be opened and closed.
 TEST_P(AudioAndroidInputTest, OpenAndCloseInputStream) {
-  AudioParameters params = GetInputStreamParameters();
+  AudioParameters params = GetDefaultInputStreamParametersOnAudioThread();
   MakeAudioInputStreamOnAudioThread(params);
   OpenAndCloseAudioInputStreamOnAudioThread();
 }
 
 // Ensure that a default output stream can be opened and closed.
-TEST_F(AudioAndroidOutputTest, OpenAndCloseOutputStream) {
-  GetDefaultOutputStreamParametersOnAudioThread();
-  MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
+TEST_P(AudioAndroidOutputTest, OpenAndCloseOutputStream) {
+  AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread();
+  MakeAudioOutputStreamOnAudioThread(params);
   OpenAndCloseAudioOutputStreamOnAudioThread();
 }
 
 // Start input streaming using default input parameters and ensure that the
 // callback sequence is sane.
 TEST_P(AudioAndroidInputTest, StartInputStreamCallbacks) {
-  AudioParameters native_params = GetInputStreamParameters();
+  AudioParameters native_params =
+      GetDefaultInputStreamParametersOnAudioThread();
   StartInputStreamCallbacks(native_params);
 }
 
-// Start input streaming using non default input parameters and ensure that the
-// callback sequence is sane. The only change we make in this test is to select
-// a 10ms buffer size instead of the default size.
+// Start input streaming using non default input parameters and ensure that
+// the callback sequence is sane. The only change we make in this test is to
+// select a 10ms buffer size instead of the default size.
 // Flaky, see crbug.com/683408.
 TEST_P(AudioAndroidInputTest, StartInputStreamCallbacksNonDefaultParameters) {
-  AudioParameters params = GetInputStreamParameters();
+  AudioParameters params = GetDefaultInputStreamParametersOnAudioThread();
   params.set_frames_per_buffer(params.sample_rate() / 100);
   StartInputStreamCallbacks(params);
 }
 
 // Start output streaming using default output parameters and ensure that the
 // callback sequence is sane.
-TEST_F(AudioAndroidOutputTest, StartOutputStreamCallbacks) {
-  GetDefaultOutputStreamParametersOnAudioThread();
-  StartOutputStreamCallbacks(audio_output_parameters());
+TEST_P(AudioAndroidOutputTest, StartOutputStreamCallbacks) {
+  AudioParameters params = GetDefaultOutputStreamParametersOnAudioThread();
+  StartOutputStreamCallbacks(params);
 }
 
 // Start output streaming using non default output parameters and ensure that
@@ -823,12 +882,12 @@
 // select a 10ms buffer size instead of the default size and to open up the
 // device in mono.
 // TODO(henrika): possibly add support for more variations.
-TEST_F(AudioAndroidOutputTest, StartOutputStreamCallbacksNonDefaultParameters) {
-  GetDefaultOutputStreamParametersOnAudioThread();
-  AudioParameters params(audio_output_parameters().format(),
-                         ChannelLayoutConfig::Mono(),
-                         audio_output_parameters().sample_rate(),
-                         audio_output_parameters().sample_rate() / 100);
+TEST_P(AudioAndroidOutputTest, StartOutputStreamCallbacksNonDefaultParameters) {
+  AudioParameters default_params =
+      GetDefaultOutputStreamParametersOnAudioThread();
+  AudioParameters params(default_params.format(), ChannelLayoutConfig::Mono(),
+                         default_params.sample_rate(),
+                         default_params.sample_rate() / 100);
   StartOutputStreamCallbacks(params);
 }
 
@@ -837,14 +896,13 @@
 // NOTE: this test requires user interaction and is not designed to run as an
 // automatized test on bots.
 TEST_P(AudioAndroidInputTest, DISABLED_RunSimplexInputStreamWithFileAsSink) {
-  AudioParameters params = GetInputStreamParameters();
+  AudioParameters params = GetDefaultInputStreamParametersOnAudioThread();
   DVLOG(1) << params;
   MakeAudioInputStreamOnAudioThread(params);
 
-  std::string file_name = base::StringPrintf("out_simplex_%d_%d_%d.pcm",
-                                             params.sample_rate(),
-                                             params.frames_per_buffer(),
-                                             params.channels());
+  std::string file_name =
+      base::StringPrintf("out_simplex_%d_%d_%d.pcm", params.sample_rate(),
+                         params.frames_per_buffer(), params.channels());
 
   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -861,18 +919,17 @@
 // NOTE: this test requires user interaction and is not designed to run as an
 // automatized test on bots.
 TEST_P(AudioAndroidInputTest, DISABLED_RunDuplexInputStreamWithFileAsSink) {
-  AudioParameters in_params = GetInputStreamParameters();
+  AudioParameters in_params = GetDefaultInputStreamParametersOnAudioThread();
   DVLOG(1) << in_params;
   MakeAudioInputStreamOnAudioThread(in_params);
 
-  GetDefaultOutputStreamParametersOnAudioThread();
-  DVLOG(1) << audio_output_parameters();
-  MakeAudioOutputStreamOnAudioThread(audio_output_parameters());
+  AudioParameters out_params = GetDefaultOutputStreamParametersOnAudioThread();
+  DVLOG(1) << out_params;
+  MakeAudioOutputStreamOnAudioThread(out_params);
 
-  std::string file_name = base::StringPrintf("out_duplex_%d_%d_%d.pcm",
-                                             in_params.sample_rate(),
-                                             in_params.frames_per_buffer(),
-                                             in_params.channels());
+  std::string file_name =
+      base::StringPrintf("out_duplex_%d_%d_%d.pcm", in_params.sample_rate(),
+                         in_params.frames_per_buffer(), in_params.channels());
 
   base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
                             base::WaitableEvent::InitialState::NOT_SIGNALED);
@@ -900,7 +957,8 @@
 TEST_P(AudioAndroidInputTest,
        DISABLED_RunSymmetricInputAndOutputStreamsInFullDuplex) {
   // Get native audio parameters for the input side.
-  AudioParameters default_input_params = GetInputStreamParameters();
+  AudioParameters default_input_params =
+      GetDefaultInputStreamParametersOnAudioThread();
 
   // Modify the parameters so that both input and output can use the same
   // parameters by selecting 10ms as buffer size. This will also ensure that
@@ -932,8 +990,14 @@
   StopAndCloseAudioInputStreamOnAudioThread();
 }
 
-INSTANTIATE_TEST_SUITE_P(AudioAndroidInputTest,
+INSTANTIATE_TEST_SUITE_P(,
+                         AudioAndroidOutputTest,
+                         testing::Values(AudioApi::AAudio, AudioApi::OpenSLES),
+                         testing::PrintToStringParamName());
+
+INSTANTIATE_TEST_SUITE_P(,
                          AudioAndroidInputTest,
-                         testing::Bool());
+                         testing::Values(AudioApi::AAudio, AudioApi::OpenSLES),
+                         testing::PrintToStringParamName());
 
 }  // namespace media
diff --git a/media/audio/audio_features.cc b/media/audio/audio_features.cc
index 5785be5..96e3b5f 100644
--- a/media/audio/audio_features.cc
+++ b/media/audio/audio_features.cc
@@ -37,6 +37,16 @@
 BASE_FEATURE(kUseAAudioInput,
              "UseAAudioInput",
              base::FEATURE_ENABLED_BY_DEFAULT);
+
+// Enables selection of audio devices for each individual AAudio stream instead
+// of using communication streams and managing the system-wide communication
+// route. This is not fully reliable on all Android devices.
+//
+// Requires `UseAAudioDriver`, `UseAAudioInput`, and an Android API level >=
+// `AAUDIO_MIN_API`, otherwise it will have no effect.
+BASE_FEATURE(kAAudioPerStreamDeviceSelection,
+             "AAudioPerStreamDeviceSelection",
+             base::FEATURE_DISABLED_BY_DEFAULT);
 #endif
 
 }  // namespace features
diff --git a/media/audio/audio_features.h b/media/audio/audio_features.h
index 79e8309..ca46ffe 100644
--- a/media/audio/audio_features.h
+++ b/media/audio/audio_features.h
@@ -14,6 +14,7 @@
 #if BUILDFLAG(IS_ANDROID)
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUseAAudioDriver);
 MEDIA_EXPORT BASE_DECLARE_FEATURE(kUseAAudioInput);
+MEDIA_EXPORT BASE_DECLARE_FEATURE(kAAudioPerStreamDeviceSelection);
 #endif
 
 }  // namespace features
diff --git a/mojo/public/cpp/base/big_buffer.cc b/mojo/public/cpp/base/big_buffer.cc
index ba9e586..372ef10 100644
--- a/mojo/public/cpp/base/big_buffer.cc
+++ b/mojo/public/cpp/base/big_buffer.cc
@@ -15,6 +15,7 @@
 #include "base/check.h"
 #include "base/containers/heap_array.h"
 #include "base/notreached.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value.h"
 
 namespace mojo_base {
 
@@ -141,6 +142,12 @@
   }
 }
 
+void BigBuffer::WriteIntoTrace(perfetto::TracedValue context) const {
+  // Don't write the data, otherwise traces become enormous, and crash the UI.
+  auto dict = std::move(context).WriteDictionary();
+  perfetto::WriteIntoTracedValue(dict.AddItem("size"), size());
+}
+
 BigBufferView::BigBufferView() = default;
 
 BigBufferView::BigBufferView(BigBufferView&& other) = default;
diff --git a/mojo/public/cpp/base/big_buffer.h b/mojo/public/cpp/base/big_buffer.h
index 1accfff..3b125fd 100644
--- a/mojo/public/cpp/base/big_buffer.h
+++ b/mojo/public/cpp/base/big_buffer.h
@@ -175,6 +175,8 @@
 
   const_iterator cend() const { return end(); }
 
+  void WriteIntoTrace(perfetto::TracedValue context) const;
+
  private:
   friend class BigBufferView;
 
diff --git a/net/BUILD.gn b/net/BUILD.gn
index b37347a6..c076ff3 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -671,6 +671,8 @@
     "http/http_stream_pool_attempt_manager.h",
     "http/http_stream_pool_attempt_manager_quic_task.cc",
     "http/http_stream_pool_attempt_manager_quic_task.h",
+    "http/http_stream_pool_attempt_manager_tcp_based_attempt.cc",
+    "http/http_stream_pool_attempt_manager_tcp_based_attempt.h",
     "http/http_stream_pool_group.cc",
     "http/http_stream_pool_group.h",
     "http/http_stream_pool_handle.cc",
diff --git a/net/base/features.cc b/net/base/features.cc
index 4f37a7d..8157d5b 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -149,6 +149,15 @@
              "SearchEnginePreconnectInterval",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kSearchEnginePreconnect2,
+             "SearchEnginePreconnect2",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
+extern const base::FeatureParam<int> kMaxPreconnectRetryInterval(
+    &kSearchEnginePreconnect2,
+    "MaxPreconnectRetryInterval",
+    30);
+
 BASE_FEATURE(kShortLaxAllowUnsafeThreshold,
              "ShortLaxAllowUnsafeThreshold",
              base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/net/base/features.h b/net/base/features.h
index 9482fc5f..726e926c 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -190,6 +190,13 @@
 // Changes the interval between two search engine preconnect attempts.
 NET_EXPORT BASE_DECLARE_FEATURE(kSearchEnginePreconnectInterval);
 
+// Enables a more efficient SearchEnginePreconnector
+NET_EXPORT BASE_DECLARE_FEATURE(kSearchEnginePreconnect2);
+
+// The maximum time to backoff when attempting preconnect retry for
+// SearchEnginePreconnector2.
+NET_EXPORT extern const base::FeatureParam<int> kMaxPreconnectRetryInterval;
+
 // When enabled, the time threshold for Lax-allow-unsafe cookies will be lowered
 // from 2 minutes to 10 seconds. This time threshold refers to the age cutoff
 // for which cookies that default into SameSite=Lax, which are newer than the
diff --git a/net/base/load_timing_internal_info.h b/net/base/load_timing_internal_info.h
index 88366d9..5de76138 100644
--- a/net/base/load_timing_internal_info.h
+++ b/net/base/load_timing_internal_info.h
@@ -24,6 +24,9 @@
   // The time taken for HTTP stream creating to finish.
   base::TimeDelta create_stream_delay;
 
+  // The time taken for HTTP transaction connected callback.
+  base::TimeDelta connected_callback_delay;
+
   // The time taken for HTTP stream initialization to finish if the
   // initialization was blocked.
   base::TimeDelta initialize_stream_delay;
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index e570a07e..f9f0b82 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -584,6 +584,12 @@
     load_timing_internal_info->create_stream_delay =
         create_stream_end_time_ - create_stream_start_time_;
   }
+  if (!connected_callback_start_time_.is_null() &&
+      !connected_callback_end_time_.is_null()) {
+    CHECK_LE(connected_callback_start_time_, connected_callback_end_time_);
+    load_timing_internal_info->connected_callback_delay =
+        connected_callback_end_time_ - connected_callback_start_time_;
+  }
   if (!initialize_stream_start_time_.is_null() &&
       !initialize_stream_end_time_.is_null()) {
     CHECK_LE(initialize_stream_start_time_, initialize_stream_end_time_);
@@ -671,6 +677,14 @@
 
 void HttpNetworkTransaction::ResumeAfterConnected(int result) {
   DCHECK_EQ(next_state_, STATE_CONNECTED_CALLBACK_COMPLETE);
+
+  connected_callback_end_time_ = base::TimeTicks::Now();
+  CHECK(!connected_callback_start_time_.is_null());
+  CHECK_LE(connected_callback_start_time_, connected_callback_end_time_);
+  base::UmaHistogramTimes(
+      "Net.NetworkTransaction.ConnectedCallbackDelay",
+      connected_callback_end_time_ - connected_callback_start_time_);
+
   OnIOComplete(result);
 }
 
@@ -1142,6 +1156,11 @@
     is_issued_by_known_root = ssl_info.is_issued_by_known_root;
   }
 
+  connected_callback_start_time_ = base::TimeTicks::Now();
+  // Reset `connected_callback_end_time_` to prevent an inconsistent state in
+  // case that `DoConnectedCallback` is called multiple times.
+  connected_callback_end_time_ = base::TimeTicks();
+
   return connected_callback_.Run(
       TransportInfo(type, remote_endpoint_,
                     std::string{stream_->GetAcceptChViaAlps()},
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index 7e6f4ee..0b97e734 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -534,6 +534,10 @@
   base::TimeTicks blocked_generate_proxy_auth_token_start_time_;
   base::TimeTicks blocked_generate_server_auth_token_start_time_;
 
+  // Timing information for the connected callback.
+  base::TimeTicks connected_callback_start_time_;
+  base::TimeTicks connected_callback_end_time_;
+
   // The number of bytes of the body received from network.
   int64_t received_body_bytes_ = 0;
 };
diff --git a/net/http/http_stream_pool_attempt_manager.cc b/net/http/http_stream_pool_attempt_manager.cc
index cf1c011..5a1867f 100644
--- a/net/http/http_stream_pool_attempt_manager.cc
+++ b/net/http/http_stream_pool_attempt_manager.cc
@@ -31,6 +31,7 @@
 #include "net/http/http_server_properties.h"
 #include "net/http/http_stream_key.h"
 #include "net/http/http_stream_pool_attempt_manager_quic_task.h"
+#include "net/http/http_stream_pool_attempt_manager_tcp_based_attempt.h"
 #include "net/http/http_stream_pool_group.h"
 #include "net/http/http_stream_pool_handle.h"
 #include "net/http/http_stream_pool_job.h"
@@ -62,34 +63,6 @@
              : StreamSocketHandle::SocketReuseType::kUnusedIdle;
 }
 
-std::string_view GetResultHistogramSuffix(std::optional<int> result) {
-  if (result.has_value()) {
-    return *result == OK ? "Success" : "Failure";
-  }
-  return "Canceled";
-}
-
-std::string_view GetHistogramSuffixForTcpBasedAttemptCancel(
-    StreamSocketCloseReason reason) {
-  switch (reason) {
-    case StreamSocketCloseReason::kSpdySessionCreated:
-      return "NewSpdySession";
-    case StreamSocketCloseReason::kQuicSessionCreated:
-      return "NewQuicSession";
-    case StreamSocketCloseReason::kUsingExistingSpdySession:
-      return "ExistingSpdySession";
-    case StreamSocketCloseReason::kUsingExistingQuicSession:
-      return "ExistingQuicSession";
-    case StreamSocketCloseReason::kUnspecified:
-    case StreamSocketCloseReason::kCloseAllConnections:
-    case StreamSocketCloseReason::kIpAddressChanged:
-    case StreamSocketCloseReason::kSslConfigChanged:
-    case StreamSocketCloseReason::kCannotUseTcpBasedProtocols:
-    case StreamSocketCloseReason::kAbort:
-      return "Other";
-  }
-}
-
 base::Value::Dict GetServiceEndpointRequestAsValue(
     HostResolver::ServiceEndpointRequest* request) {
   base::Value::Dict dict;
@@ -104,180 +77,6 @@
 
 }  // namespace
 
-// Represents a TCP based attempt.
-class HttpStreamPool::AttemptManager::TcpBasedAttempt
-    : public TlsStreamAttempt::SSLConfigProvider {
- public:
-  explicit TcpBasedAttempt(AttemptManager* manager) : manager_(manager) {}
-
-  TcpBasedAttempt(const TcpBasedAttempt&) = delete;
-  TcpBasedAttempt& operator=(const TcpBasedAttempt&) = delete;
-
-  ~TcpBasedAttempt() override {
-    base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
-    // TODO(bashi): Rename following histograms to use TcpBased*.
-    base::UmaHistogramTimes(
-        base::StrCat({"Net.HttpStreamPool.StreamAttemptTime.",
-                      GetResultHistogramSuffix(result_)}),
-        elapsed);
-
-    if (cancel_reason_.has_value()) {
-      base::UmaHistogramEnumeration(
-          "Net.HttpStreamPool.StreamAttemptCancelReason", *cancel_reason_);
-
-      std::string_view suffix =
-          GetHistogramSuffixForTcpBasedAttemptCancel(*cancel_reason_);
-      CHECK(manager_->initial_attempt_state_.has_value());
-      base::UmaHistogramEnumeration(
-          base::StrCat(
-              {"Net.HttpStreamPool.StreamAttemptCanceledInitialAttemptState.",
-               suffix}),
-          *manager_->initial_attempt_state_);
-      base::UmaHistogramTimes(
-          base::StrCat(
-              {"Net.HttpStreamPool.StreamAttemptCanceledTime.", suffix}),
-          elapsed);
-    }
-  }
-
-  void Start(std::unique_ptr<StreamAttempt> attempt,
-             TlsStreamAttempt* tls_attempt_ptr) {
-    CHECK(!attempt_);
-    attempt_ = std::move(attempt);
-    start_time_ = base::TimeTicks::Now();
-    int rv = attempt_->Start(
-        base::BindOnce(&TcpBasedAttempt::OnInFlightAttemptComplete,
-                       weak_ptr_factory_.GetWeakPtr()));
-    if (rv == ERR_IO_PENDING) {
-      // SAFETY: Unretained `manager_` is fine since `manager_` owns this and
-      // `this` owns `slow_timer_`.
-      slow_timer_.Start(FROM_HERE, HttpStreamPool::GetConnectionAttemptDelay(),
-                        base::BindOnce(&AttemptManager::OnTcpBasedAttemptSlow,
-                                       base::Unretained(manager_), this));
-      if (tls_attempt_ptr && !tls_attempt_ptr->IsTcpHandshakeCompleted()) {
-        // SAFETY: Unretained `manager_` is fine since the passed callback runs
-        // is invoked synchronously (without PostTask) when the TCP handshake
-        // completes. See TlsStreamAttempt::DoTcpAttemptComplete.
-        tls_attempt_ptr->SetTcpHandshakeCompletionCallback(base::BindOnce(
-            &AttemptManager::OnTcpBasedAttemptTcpHandshakeComplete,
-            base::Unretained(manager_), this));
-      }
-    } else {
-      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
-          FROM_HERE, base::BindOnce(&TcpBasedAttempt::OnInFlightAttemptComplete,
-                                    weak_ptr_factory_.GetWeakPtr(), rv));
-    }
-  }
-
-  void SetResult(int rv) {
-    CHECK(!result_.has_value());
-    result_ = rv;
-  }
-
-  void SetCancelReason(StreamSocketCloseReason reason) {
-    cancel_reason_ = reason;
-    if (attempt_) {
-      attempt_->SetCancelReason(reason);
-    }
-  }
-
-  StreamAttempt* attempt() { return attempt_.get(); }
-
-  base::TimeTicks start_time() const { return start_time_; }
-  base::TimeTicks ssl_config_wait_start_time() const {
-    return ssl_config_wait_start_time_;
-  }
-
-  const IPEndPoint& ip_endpoint() const { return attempt_->ip_endpoint(); }
-
-  bool is_slow() const { return is_slow_; }
-  void set_is_slow(bool is_slow) { is_slow_ = is_slow; }
-
-  base::OneShotTimer& slow_timer() { return slow_timer_; }
-
-  // Set to true when the attempt is aborted. When true, the attempt will fail
-  // but not be considered as an actual failure.
-  bool is_aborted() const { return is_aborted_; }
-  void set_is_aborted(bool is_aborted) { is_aborted_ = is_aborted; }
-
-  // TlsStreamAttempt::SSLConfigProvider implementation:
-  int WaitForSSLConfigReady(CompletionOnceCallback callback) override {
-    int rv = manager_->WaitForSSLConfigReady();
-    if (rv == ERR_IO_PENDING) {
-      ssl_config_wait_start_time_ = base::TimeTicks::Now();
-      ssl_config_waiting_callback_ = std::move(callback);
-    }
-    return rv;
-  }
-
-  base::expected<SSLConfig, TlsStreamAttempt::GetSSLConfigError> GetSSLConfig()
-      override {
-    return manager_->GetSSLConfig(this);
-  }
-
-  bool IsWaitingSSLConfig() const {
-    return !ssl_config_waiting_callback_.is_null();
-  }
-
-  CompletionOnceCallback TakeSSLConfigWaitingCallback() {
-    CHECK(!ssl_config_wait_start_time_.is_null());
-    base::UmaHistogramTimes(
-        "Net.HttpStreamPool.StreamAttemptSSLConfigWaitTime",
-        base::TimeTicks::Now() - ssl_config_wait_start_time_);
-
-    return std::move(ssl_config_waiting_callback_);
-  }
-
-  base::Value::Dict GetInfoAsValue() const {
-    base::Value::Dict dict;
-    if (attempt_) {
-      dict.Set("attempt_state", attempt_->GetInfoAsValue());
-      dict.Set("ip_endpoint", attempt_->ip_endpoint().ToString());
-      if (attempt_->stream_socket()) {
-        attempt_->stream_socket()->NetLog().source().AddToEventParameters(dict);
-      }
-    }
-    dict.Set("is_slow", is_slow_);
-    dict.Set("is_aborted", is_aborted_);
-    dict.Set("started", !start_time_.is_null());
-    if (!start_time_.is_null()) {
-      base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
-      dict.Set("elapsed_ms", static_cast<int>(elapsed.InMilliseconds()));
-    }
-    if (result_.has_value()) {
-      dict.Set("result", *result_);
-    }
-    if (cancel_reason_.has_value()) {
-      dict.Set("cancel_reason", static_cast<int>(*cancel_reason_));
-    }
-    manager_->net_log().source().AddToEventParameters(dict);
-    return dict;
-  }
-
- private:
-  void OnInFlightAttemptComplete(int rv) {
-    manager_->OnTcpBasedAttemptComplete(this, rv);
-  }
-
-  const raw_ptr<AttemptManager> manager_;
-  std::unique_ptr<StreamAttempt> attempt_;
-  base::TimeTicks start_time_;
-  std::optional<int> result_;
-  std::optional<StreamSocketCloseReason> cancel_reason_;
-  // Timer to start a next attempt. When fired, `this` is treated as a slow
-  // attempt but `this` is not timed out yet.
-  base::OneShotTimer slow_timer_;
-  // Set to true when `slow_timer_` is fired. See the comment of `slow_timer_`.
-  bool is_slow_ = false;
-  // Set to true when `this` and `attempt_` should abort. Currently used to
-  // handle ECH failure.
-  bool is_aborted_ = false;
-  base::TimeTicks ssl_config_wait_start_time_;
-  CompletionOnceCallback ssl_config_waiting_callback_;
-
-  base::WeakPtrFactory<TcpBasedAttempt> weak_ptr_factory_{this};
-};
-
 // static
 std::string_view HttpStreamPool::AttemptManager::CanAttemptResultToString(
     CanAttemptResult result) {
@@ -1410,39 +1209,14 @@
 
     CHECK(!preconnect_jobs_.empty() || group_->IdleStreamSocketCount() == 0);
 
-    auto tcp_based_attempt = std::make_unique<TcpBasedAttempt>(this);
-    TcpBasedAttempt* raw_attempt = tcp_based_attempt.get();
-    auto [_, inserted] =
+    auto tcp_based_attempt =
+        std::make_unique<TcpBasedAttempt>(this, using_tls, *ip_endpoint);
+    auto [attempt_iterator, inserted] =
         tcp_based_attempts_.emplace(std::move(tcp_based_attempt));
     CHECK(inserted);
     pool()->IncrementTotalConnectingStreamCount();
 
-    std::unique_ptr<StreamAttempt> attempt;
-    // Set to non-null if the attempt is a TLS attempt.
-    TlsStreamAttempt* tls_attempt_ptr = nullptr;
-    if (using_tls) {
-      attempt = std::make_unique<TlsStreamAttempt>(
-          pool()->stream_attempt_params(), *ip_endpoint,
-          HostPortPair::FromSchemeHostPort(stream_key().destination()),
-          /*ssl_config_provider=*/raw_attempt);
-      tls_attempt_ptr = static_cast<TlsStreamAttempt*>(attempt.get());
-    } else {
-      attempt = std::make_unique<TcpStreamAttempt>(
-          pool()->stream_attempt_params(), *ip_endpoint);
-    }
-
-    net_log().AddEvent(
-        NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_ATTEMPT_START, [&] {
-          base::Value::Dict dict = GetStatesAsNetLogParams();
-          attempt->net_log().source().AddToEventParameters(dict);
-          return dict;
-        });
-
-    raw_attempt->Start(std::move(attempt), tls_attempt_ptr);
-    // Add NetLog dependency after Start() so that the first event of the
-    // attempt can have meaningful description in the NetLog viewer.
-    raw_attempt->attempt()->net_log().AddEventReferencingSource(
-        NetLogEventType::STREAM_ATTEMPT_BOUND_TO_POOL, net_log().source());
+    (*attempt_iterator)->Start();
 
     ++num_attempts;
     if (max_attempts.has_value() && num_attempts >= *max_attempts) {
@@ -1995,15 +1769,6 @@
 void HttpStreamPool::AttemptManager::OnTcpBasedAttemptComplete(
     TcpBasedAttempt* raw_attempt,
     int rv) {
-  net_log().AddEvent(
-      NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_ATTEMPT_END, [&] {
-        base::Value::Dict dict = GetStatesAsNetLogParams();
-        dict.Set("result", ErrorToString(rv));
-        raw_attempt->attempt()->net_log().source().AddToEventParameters(dict);
-        return dict;
-      });
-  raw_attempt->SetResult(rv);
-  raw_attempt->slow_timer().Stop();
   if (raw_attempt->is_slow()) {
     CHECK_GT(slow_tcp_based_attempt_count_, 0u);
     --slow_tcp_based_attempt_count_;
diff --git a/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.cc b/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.cc
new file mode 100644
index 0000000..ed90e4e
--- /dev/null
+++ b/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.cc
@@ -0,0 +1,221 @@
+// 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 "net/http/http_stream_pool_attempt_manager_tcp_based_attempt.h"
+
+#include <memory>
+#include <optional>
+#include <string_view>
+
+#include "base/metrics/histogram_functions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "net/base/completion_once_callback.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/ip_endpoint.h"
+#include "net/http/http_stream_key.h"
+#include "net/http/http_stream_pool.h"
+#include "net/http/http_stream_pool_attempt_manager.h"
+#include "net/log/net_log_with_source.h"
+#include "net/socket/stream_attempt.h"
+#include "net/socket/stream_socket_close_reason.h"
+#include "net/socket/tcp_stream_attempt.h"
+#include "net/socket/tls_stream_attempt.h"
+
+namespace net {
+
+namespace {
+
+std::string_view GetResultHistogramSuffix(std::optional<int> result) {
+  if (result.has_value()) {
+    return *result == OK ? "Success" : "Failure";
+  }
+  return "Canceled";
+}
+
+std::string_view GetHistogramSuffixForTcpBasedAttemptCancel(
+    StreamSocketCloseReason reason) {
+  switch (reason) {
+    case StreamSocketCloseReason::kSpdySessionCreated:
+      return "NewSpdySession";
+    case StreamSocketCloseReason::kQuicSessionCreated:
+      return "NewQuicSession";
+    case StreamSocketCloseReason::kUsingExistingSpdySession:
+      return "ExistingSpdySession";
+    case StreamSocketCloseReason::kUsingExistingQuicSession:
+      return "ExistingQuicSession";
+    case StreamSocketCloseReason::kUnspecified:
+    case StreamSocketCloseReason::kCloseAllConnections:
+    case StreamSocketCloseReason::kIpAddressChanged:
+    case StreamSocketCloseReason::kSslConfigChanged:
+    case StreamSocketCloseReason::kCannotUseTcpBasedProtocols:
+    case StreamSocketCloseReason::kAbort:
+      return "Other";
+  }
+}
+
+}  // namespace
+
+HttpStreamPool::AttemptManager::TcpBasedAttempt::TcpBasedAttempt(
+    AttemptManager* manager,
+    bool using_tls,
+    IPEndPoint ip_endpoint)
+    : manager_(manager), using_tls_(using_tls) {
+  if (using_tls_) {
+    attempt_ = std::make_unique<TlsStreamAttempt>(
+        manager_->pool()->stream_attempt_params(), std::move(ip_endpoint),
+        HostPortPair::FromSchemeHostPort(manager_->stream_key().destination()),
+        /*ssl_config_provider=*/this);
+  } else {
+    attempt_ = std::make_unique<TcpStreamAttempt>(
+        manager_->pool()->stream_attempt_params(), std::move(ip_endpoint));
+  }
+}
+
+HttpStreamPool::AttemptManager::TcpBasedAttempt::~TcpBasedAttempt() {
+  base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
+  // TODO(bashi): Rename following histograms to use TcpBased*.
+  base::UmaHistogramTimes(base::StrCat({"Net.HttpStreamPool.StreamAttemptTime.",
+                                        GetResultHistogramSuffix(result_)}),
+                          elapsed);
+
+  if (cancel_reason_.has_value()) {
+    base::UmaHistogramEnumeration(
+        "Net.HttpStreamPool.StreamAttemptCancelReason", *cancel_reason_);
+
+    std::string_view suffix =
+        GetHistogramSuffixForTcpBasedAttemptCancel(*cancel_reason_);
+    CHECK(manager_->initial_attempt_state_.has_value());
+    base::UmaHistogramEnumeration(
+        base::StrCat(
+            {"Net.HttpStreamPool.StreamAttemptCanceledInitialAttemptState.",
+             suffix}),
+        *manager_->initial_attempt_state_);
+    base::UmaHistogramTimes(
+        base::StrCat({"Net.HttpStreamPool.StreamAttemptCanceledTime.", suffix}),
+        elapsed);
+  }
+}
+
+void HttpStreamPool::AttemptManager::TcpBasedAttempt::Start() {
+  CHECK(attempt_);
+  TlsStreamAttempt* tls_attempt_ptr =
+      using_tls_ ? static_cast<TlsStreamAttempt*>(attempt_.get()) : nullptr;
+  start_time_ = base::TimeTicks::Now();
+  int rv = attempt_->Start(base::BindOnce(&TcpBasedAttempt::OnAttemptComplete,
+                                          weak_ptr_factory_.GetWeakPtr()));
+  manager_->net_log().AddEvent(
+      NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_START,
+      [&] {
+        base::Value::Dict dict = manager_->GetStatesAsNetLogParams();
+        attempt()->net_log().source().AddToEventParameters(dict);
+        return dict;
+      });
+  // Add NetLog dependency after Start() so that the first event of the
+  // attempt can have meaningful description in the NetLog viewer.
+  attempt()->net_log().AddEventReferencingSource(
+      NetLogEventType::TCP_BASED_ATTEMPT_BOUND_TO_POOL,
+      manager_->net_log().source());
+
+  if (rv == ERR_IO_PENDING) {
+    // SAFETY: Unretained `manager_` is fine since `manager_` owns this and
+    // `this` owns `slow_timer_`.
+    slow_timer_.Start(FROM_HERE, HttpStreamPool::GetConnectionAttemptDelay(),
+                      base::BindOnce(&AttemptManager::OnTcpBasedAttemptSlow,
+                                     base::Unretained(manager_), this));
+    if (tls_attempt_ptr && !tls_attempt_ptr->IsTcpHandshakeCompleted()) {
+      // SAFETY: Unretained `manager_` is fine since the passed callback runs
+      // is invoked synchronously (without PostTask) when the TCP handshake
+      // completes. See TlsStreamAttempt::DoTcpAttemptComplete.
+      tls_attempt_ptr->SetTcpHandshakeCompletionCallback(
+          base::BindOnce(&AttemptManager::OnTcpBasedAttemptTcpHandshakeComplete,
+                         base::Unretained(manager_), this));
+    }
+  } else {
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE, base::BindOnce(&TcpBasedAttempt::OnAttemptComplete,
+                                  weak_ptr_factory_.GetWeakPtr(), rv));
+  }
+}
+
+void HttpStreamPool::AttemptManager::TcpBasedAttempt::SetCancelReason(
+    StreamSocketCloseReason reason) {
+  cancel_reason_ = reason;
+  if (attempt_) {
+    attempt_->SetCancelReason(reason);
+  }
+}
+
+int HttpStreamPool::AttemptManager::TcpBasedAttempt::WaitForSSLConfigReady(
+    CompletionOnceCallback callback) {
+  int rv = manager_->WaitForSSLConfigReady();
+  if (rv == ERR_IO_PENDING) {
+    ssl_config_wait_start_time_ = base::TimeTicks::Now();
+    ssl_config_waiting_callback_ = std::move(callback);
+  }
+  return rv;
+}
+
+base::expected<SSLConfig, TlsStreamAttempt::GetSSLConfigError>
+HttpStreamPool::AttemptManager::TcpBasedAttempt::GetSSLConfig() {
+  return manager_->GetSSLConfig(this);
+}
+
+CompletionOnceCallback HttpStreamPool::AttemptManager::TcpBasedAttempt::
+    TakeSSLConfigWaitingCallback() {
+  CHECK(!ssl_config_wait_start_time_.is_null());
+  base::UmaHistogramTimes("Net.HttpStreamPool.StreamAttemptSSLConfigWaitTime",
+                          base::TimeTicks::Now() - ssl_config_wait_start_time_);
+
+  return std::move(ssl_config_waiting_callback_);
+}
+
+base::Value::Dict
+HttpStreamPool::AttemptManager::TcpBasedAttempt::GetInfoAsValue() const {
+  base::Value::Dict dict;
+  if (attempt_) {
+    dict.Set("attempt_state", attempt_->GetInfoAsValue());
+    dict.Set("ip_endpoint", attempt_->ip_endpoint().ToString());
+    if (attempt_->stream_socket()) {
+      attempt_->stream_socket()->NetLog().source().AddToEventParameters(dict);
+    }
+  }
+  dict.Set("is_slow", is_slow_);
+  dict.Set("is_aborted", is_aborted_);
+  dict.Set("started", !start_time_.is_null());
+  if (!start_time_.is_null()) {
+    base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
+    dict.Set("elapsed_ms", static_cast<int>(elapsed.InMilliseconds()));
+  }
+  if (result_.has_value()) {
+    dict.Set("result", *result_);
+  }
+  if (cancel_reason_.has_value()) {
+    dict.Set("cancel_reason", static_cast<int>(*cancel_reason_));
+  }
+  manager_->net_log().source().AddToEventParameters(dict);
+  return dict;
+}
+
+void HttpStreamPool::AttemptManager::TcpBasedAttempt::OnAttemptComplete(
+    int rv) {
+  manager_->net_log().AddEvent(
+      NetLogEventType::HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_END,
+      [&] {
+        base::Value::Dict dict = manager_->GetStatesAsNetLogParams();
+        dict.Set("result", ErrorToString(rv));
+        attempt()->net_log().source().AddToEventParameters(dict);
+        return dict;
+      });
+
+  CHECK(!result_.has_value());
+  result_ = rv;
+  slow_timer_.Stop();
+  manager_->OnTcpBasedAttemptComplete(this, rv);
+}
+
+}  // namespace net
diff --git a/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.h b/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.h
new file mode 100644
index 0000000..fe857c6
--- /dev/null
+++ b/net/http/http_stream_pool_attempt_manager_tcp_based_attempt.h
@@ -0,0 +1,98 @@
+// 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 NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_H_
+#define NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_H_
+
+#include <memory>
+#include <optional>
+
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "base/types/expected.h"
+#include "base/values.h"
+#include "net/base/completion_once_callback.h"
+#include "net/base/ip_endpoint.h"
+#include "net/http/http_stream_pool_attempt_manager.h"
+#include "net/socket/stream_attempt.h"
+#include "net/socket/stream_socket_close_reason.h"
+#include "net/socket/tls_stream_attempt.h"
+
+namespace net {
+
+// Represents a TCP based attempt.
+class HttpStreamPool::AttemptManager::TcpBasedAttempt
+    : public TlsStreamAttempt::SSLConfigProvider {
+ public:
+  TcpBasedAttempt(AttemptManager* manager,
+                  bool using_tls,
+                  IPEndPoint ip_endpoint);
+
+  TcpBasedAttempt(const TcpBasedAttempt&) = delete;
+  TcpBasedAttempt& operator=(const TcpBasedAttempt&) = delete;
+
+  ~TcpBasedAttempt() override;
+
+  void Start();
+
+  void SetCancelReason(StreamSocketCloseReason reason);
+
+  StreamAttempt* attempt() { return attempt_.get(); }
+
+  base::TimeTicks start_time() const { return start_time_; }
+  base::TimeTicks ssl_config_wait_start_time() const {
+    return ssl_config_wait_start_time_;
+  }
+
+  const IPEndPoint& ip_endpoint() const { return attempt_->ip_endpoint(); }
+
+  bool is_slow() const { return is_slow_; }
+  void set_is_slow(bool is_slow) { is_slow_ = is_slow; }
+
+  base::OneShotTimer& slow_timer() { return slow_timer_; }
+
+  // Set to true when the attempt is aborted. When true, the attempt will fail
+  // but not be considered as an actual failure.
+  bool is_aborted() const { return is_aborted_; }
+  void set_is_aborted(bool is_aborted) { is_aborted_ = is_aborted; }
+
+  // TlsStreamAttempt::SSLConfigProvider implementation:
+  int WaitForSSLConfigReady(CompletionOnceCallback callback) override;
+  base::expected<SSLConfig, TlsStreamAttempt::GetSSLConfigError> GetSSLConfig()
+      override;
+
+  bool IsWaitingSSLConfig() const {
+    return !ssl_config_waiting_callback_.is_null();
+  }
+
+  CompletionOnceCallback TakeSSLConfigWaitingCallback();
+
+  base::Value::Dict GetInfoAsValue() const;
+
+ private:
+  void OnAttemptComplete(int rv);
+
+  const raw_ptr<AttemptManager> manager_;
+  const bool using_tls_;
+  std::unique_ptr<StreamAttempt> attempt_;
+  base::TimeTicks start_time_;
+  std::optional<int> result_;
+  std::optional<StreamSocketCloseReason> cancel_reason_;
+  // Timer to start a next attempt. When fired, `this` is treated as a slow
+  // attempt but `this` is not timed out yet.
+  base::OneShotTimer slow_timer_;
+  // Set to true when `slow_timer_` is fired. See the comment of `slow_timer_`.
+  bool is_slow_ = false;
+  // Set to true when `this` and `attempt_` should abort. Currently used to
+  // handle ECH failure.
+  bool is_aborted_ = false;
+  base::TimeTicks ssl_config_wait_start_time_;
+  CompletionOnceCallback ssl_config_waiting_callback_;
+
+  base::WeakPtrFactory<TcpBasedAttempt> weak_ptr_factory_{this};
+};
+
+}  // namespace net
+
+#endif  // NET_HTTP_HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_H_
diff --git a/net/log/net_log_event_type_list.h b/net/log/net_log_event_type_list.h
index f335c6e..22ee937 100644
--- a/net/log/net_log_event_type_list.h
+++ b/net/log/net_log_event_type_list.h
@@ -986,8 +986,8 @@
 // StreamAttempt and subclasses
 // ------------------------------------------------------------------------
 
-// Emitted when a StreamAttempt is created by HttpStreamPool.
-EVENT_TYPE(STREAM_ATTEMPT_BOUND_TO_POOL)
+// Emitted when a TcpBasedAttempt is created by HttpStreamPool.
+EVENT_TYPE(TCP_BASED_ATTEMPT_BOUND_TO_POOL)
 
 // Marks the creation/destruction of a TcpStreamAttempt.
 // For the BEGIN phase, the following parameter is attached:
@@ -1573,19 +1573,19 @@
 //     "quic_task_result": <The result of a QuicTask, if it is already finished>
 //   }
 
-// Emitted when an HttpStreamPool::AttemptManager started a StreamAttempt.
+// Emitted when an HttpStreamPool::AttemptManager started a TcpBasedAttempt.
 // This event has the common event parameters (see above).
-EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_ATTEMPT_START)
+EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_START)
 
 // Emitted when an HttpStreamPool::AttemptManager received completion from a
-// StreamAttempt.
+// TcpBasedAttempt.
 // This event has the common event parameters (see above).
 // In addition to the common event parameters, this event has the following
 // parameter:
 //   {
 //     "result": <String representation of the result>,
 //   }
-EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_ATTEMPT_END)
+EVENT_TYPE(HTTP_STREAM_POOL_ATTEMPT_MANAGER_TCP_BASED_ATTEMPT_END)
 
 // Emitted when an HttpStreamPool::AttemptManager is going to notify failure.
 // In addition to the common event parameters, this event has the following
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc
index 1dc91d7..ace8895 100644
--- a/sandbox/linux/services/credentials.cc
+++ b/sandbox/linux/services/credentials.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <array>
+
 #ifdef UNSAFE_BUFFERS_BUILD
 // TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
 #pragma allow_unsafe_buffers
@@ -202,7 +204,7 @@
     const std::vector<Capability>& caps) {
   struct cap_hdr hdr = {};
   hdr.version = _LINUX_CAPABILITY_VERSION_3;
-  struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {};
+  std::array<cap_data, _LINUX_CAPABILITY_U32S_3> data = {};
 
   // Initially, cap has no capability flags set. Enable the effective and
   // permitted flags only for the requested capabilities.
@@ -214,7 +216,7 @@
     data[index].permitted |= mask;
   }
 
-  return sys_capset(&hdr, data) == 0;
+  return sys_capset(&hdr, data.data()) == 0;
 }
 
 // static
@@ -234,9 +236,9 @@
 bool Credentials::HasAnyCapability() {
   struct cap_hdr hdr = {};
   hdr.version = _LINUX_CAPABILITY_VERSION_3;
-  struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {};
+  std::array<cap_data, _LINUX_CAPABILITY_U32S_3> data = {};
 
-  PCHECK(sys_capget(&hdr, data) == 0);
+  PCHECK(sys_capget(&hdr, data.data()) == 0);
 
   for (size_t i = 0; i < std::size(data); ++i) {
     if (data[i].effective || data[i].permitted || data[i].inheritable) {
@@ -250,9 +252,9 @@
 bool Credentials::HasCapability(Capability cap) {
   struct cap_hdr hdr = {};
   hdr.version = _LINUX_CAPABILITY_VERSION_3;
-  struct cap_data data[_LINUX_CAPABILITY_U32S_3] = {};
+  std::array<cap_data, _LINUX_CAPABILITY_U32S_3> data = {};
 
-  PCHECK(sys_capget(&hdr, data) == 0);
+  PCHECK(sys_capget(&hdr, data.data()) == 0);
 
   const int cap_num = CapabilityToKernelValue(cap);
   const size_t index = CAP_TO_INDEX(cap_num);
diff --git a/sandbox/linux/suid/client/setuid_sandbox_host.cc b/sandbox/linux/suid/client/setuid_sandbox_host.cc
index 6365ecc..6ab32f3 100644
--- a/sandbox/linux/suid/client/setuid_sandbox_host.cc
+++ b/sandbox/linux/suid/client/setuid_sandbox_host.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <array>
+
 #ifdef UNSAFE_BUFFERS_BUILD
 // TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
 #pragma allow_unsafe_buffers
@@ -51,11 +53,13 @@
 // inside another.
 void UnsetExpectedEnvironmentVariables(base::EnvironmentMap* env_map) {
   DCHECK(env_map);
-  const base::NativeEnvironmentString environment_vars[] = {
-      kSandboxDescriptorEnvironmentVarName, kSandboxHelperPidEnvironmentVarName,
-      kSandboxEnvironmentApiProvides,       kSandboxPIDNSEnvironmentVarName,
+  const auto environment_vars = std::to_array<base::NativeEnvironmentString>({
+      kSandboxDescriptorEnvironmentVarName,
+      kSandboxHelperPidEnvironmentVarName,
+      kSandboxEnvironmentApiProvides,
+      kSandboxPIDNSEnvironmentVarName,
       kSandboxNETNSEnvironmentVarName,
-  };
+  });
 
   for (size_t i = 0; i < std::size(environment_vars); ++i) {
     // Setting values in EnvironmentMap to an empty-string will make
diff --git a/sandbox/linux/syscall_broker/broker_process_unittest.cc b/sandbox/linux/syscall_broker/broker_process_unittest.cc
index 626d0c7..95787213 100644
--- a/sandbox/linux/syscall_broker/broker_process_unittest.cc
+++ b/sandbox/linux/syscall_broker/broker_process_unittest.cc
@@ -2,6 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include <array>
+
 #ifdef UNSAFE_BUFFERS_BUILD
 // TODO(crbug.com/351564777): Remove this and convert code to safer constructs.
 #pragma allow_unsafe_buffers
@@ -750,14 +752,15 @@
 
     // Reading /proc/self/status should return the same PID as the current
     // process's PID, not the broker's.
-    char buf[4096];
+    std::array<char, 4096> buf;
 
-    ssize_t num_read = HANDLE_EINTR(read(fd, buf, sizeof(buf)));
+    ssize_t num_read = HANDLE_EINTR(
+        read(fd, buf.data(), (buf.size() * sizeof(decltype(buf)::value_type))));
     ASSERT_GE(IGNORE_EINTR(close(fd)), 0);
 
     ASSERT_GT(num_read, 0);
 
-    std::string_view status(buf, static_cast<size_t>(num_read));
+    std::string_view status(buf.data(), static_cast<size_t>(num_read));
     std::string_view tracer("Pid:\t");
 
     std::string_view::size_type pid_index = status.find(tracer);
@@ -766,7 +769,8 @@
     std::string_view::size_type pid_end_index = status.find('\n', pid_index);
     ASSERT_NE(pid_end_index, std::string_view::npos);
 
-    std::string_view pid_str(buf + pid_index, pid_end_index - pid_index);
+    std::string_view pid_str(base::span<char>(buf).subspan(pid_index).data(),
+                             pid_end_index - pid_index);
     int pid = 0;
     ASSERT_TRUE(base::StringToInt(pid_str, &pid));
 
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn
index bbf14e0..98d1001 100644
--- a/services/network/BUILD.gn
+++ b/services/network/BUILD.gn
@@ -89,6 +89,7 @@
     "network_service_proxy_delegate.h",
     "oblivious_http_request_handler.cc",
     "oblivious_http_request_handler.h",
+    "observer_wrapper.h",
     "orb/orb_api.cc",
     "orb/orb_impl.cc",
     "orb/orb_impl.h",
diff --git a/services/network/observer_wrapper.h b/services/network/observer_wrapper.h
new file mode 100644
index 0000000..c706040
--- /dev/null
+++ b/services/network/observer_wrapper.h
@@ -0,0 +1,98 @@
+// 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 SERVICES_NETWORK_OBSERVER_WRAPPER_H_
+#define SERVICES_NETWORK_OBSERVER_WRAPPER_H_
+
+#include "base/memory/raw_ptr.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+
+namespace network {
+
+// Manages an observer interface pointer that might come from a request-specific
+// mojo::PendingRemote or a shared, factory-level fallback pointer.
+//
+// This pattern is used because for browser-initiated requests, observer remotes
+// (like DevToolsObserver, CookieAccessObserver) might be provided specifically
+// for that request via `ResourceRequest::TrustedParams`. In such cases, the
+// `remote` parameter passed to the constructor will be valid, and this wrapper
+// will bind and use it.
+//
+// For other requests (e.g., subresources initiated by a renderer), the
+// `TrustedParams` does not contain these specific observer remotes. Instead,
+// these requests need to use a shared observer remote that was provided by the
+// browser process when the URLLoaderFactory was created and is stored within
+// that factory. The `fallback` parameter passed to the constructor typically
+// points to the implementation associated with this shared remote.
+//
+// This class abstracts this selection logic.
+//
+// NOTE: This implementation caches the raw pointer at construction and does not
+// dynamically update if the remote disconnects.
+template <typename T>
+class ObserverWrapper {
+ public:
+  // Default constructor initializes with no observer.
+  ObserverWrapper() : ptr_(nullptr) {}
+
+  // Constructor taking a PendingRemote and an optional fallback raw pointer.
+  // If the remote is valid, it's bound, and the internal pointer points to it.
+  // Otherwise, the internal pointer points to the fallback.
+  explicit ObserverWrapper(mojo::PendingRemote<T> remote, T* fallback = nullptr)
+      : remote_(std::move(remote)) {
+    ptr_ = remote_.is_bound() ? remote_.get() : fallback;
+  }
+
+  // Allows checking the wrapper in boolean contexts (true if it points to
+  // a observer).
+  explicit operator bool() const { return !!ptr_; }
+
+  // Returns the cached raw pointer (either remote impl or fallback).
+  T* get() const { return ptr_.get(); }
+  // Provides pointer-like access via the arrow operator.
+  T* operator->() const {
+    CHECK(get());
+    return get();
+  }
+  // Provides pointer-like access via the dereference operator.
+  T& operator*() const {
+    CHECK(get());
+    return *get();
+  }
+
+  ObserverWrapper(const ObserverWrapper&) = delete;
+  ObserverWrapper& operator=(const ObserverWrapper&) = delete;
+
+  // Move constructor.
+  ObserverWrapper(ObserverWrapper&& other)
+      : remote_(std::move(other.remote_)),
+        ptr_(std::exchange(other.ptr_, nullptr)) {}
+  // Move assignment operator.
+  ObserverWrapper& operator=(ObserverWrapper&& other) {
+    if (this == &other) {
+      return *this;
+    }
+    remote_ = std::move(other.remote_);
+    ptr_ = other.ptr_;
+    other.ptr_ = nullptr;
+    return *this;
+  }
+
+  // Allows taking ownership of the internal `mojo::Remote`.
+  mojo::Remote<T> TakeRemote() {
+    ptr_ = nullptr;
+    return std::move(remote_);
+  }
+
+ private:
+  // Holds the Mojo remote connection, if one was provided.
+  mojo::Remote<T> remote_;
+  // Cached raw pointer to either the remote implementation or the fallback.
+  raw_ptr<T> ptr_;
+};
+
+}  // namespace network
+
+#endif  // SERVICES_NETWORK_OBSERVER_WRAPPER_H_
diff --git a/services/network/public/cpp/load_timing_internal_info_mojom_traits.cc b/services/network/public/cpp/load_timing_internal_info_mojom_traits.cc
index f89ba8ce..9936848 100644
--- a/services/network/public/cpp/load_timing_internal_info_mojom_traits.cc
+++ b/services/network/public/cpp/load_timing_internal_info_mojom_traits.cc
@@ -20,6 +20,14 @@
 const base::TimeDelta&
 StructTraits<network::mojom::LoadTimingInternalInfoDataView,
              net::LoadTimingInternalInfo>::
+    connected_callback_delay(const net::LoadTimingInternalInfo& info) {
+  return info.connected_callback_delay;
+}
+
+// static
+const base::TimeDelta&
+StructTraits<network::mojom::LoadTimingInternalInfoDataView,
+             net::LoadTimingInternalInfo>::
     initialize_stream_delay(const net::LoadTimingInternalInfo& info) {
   return info.initialize_stream_delay;
 }
diff --git a/services/network/public/cpp/load_timing_internal_info_mojom_traits.h b/services/network/public/cpp/load_timing_internal_info_mojom_traits.h
index 91a3d73..7263ba30 100644
--- a/services/network/public/cpp/load_timing_internal_info_mojom_traits.h
+++ b/services/network/public/cpp/load_timing_internal_info_mojom_traits.h
@@ -18,6 +18,8 @@
                  net::LoadTimingInternalInfo> {
   static const base::TimeDelta& create_stream_delay(
       const net::LoadTimingInternalInfo& info);
+  static const base::TimeDelta& connected_callback_delay(
+      const net::LoadTimingInternalInfo& info);
   static const base::TimeDelta& initialize_stream_delay(
       const net::LoadTimingInternalInfo& info);
   static bool Read(network::mojom::LoadTimingInternalInfoDataView data,
diff --git a/services/network/public/mojom/load_timing_internal_info.mojom b/services/network/public/mojom/load_timing_internal_info.mojom
index df8503e..06c82929 100644
--- a/services/network/public/mojom/load_timing_internal_info.mojom
+++ b/services/network/public/mojom/load_timing_internal_info.mojom
@@ -9,5 +9,6 @@
 // Mirror of net::LoadTimingInternalInfo.
 struct LoadTimingInternalInfo {
   mojo_base.mojom.TimeDelta create_stream_delay;
+  mojo_base.mojom.TimeDelta connected_callback_delay;
   mojo_base.mojom.TimeDelta initialize_stream_delay;
 };
diff --git a/services/network/test/url_loader_context_for_tests.cc b/services/network/test/url_loader_context_for_tests.cc
index a8f2a06..cd221905 100644
--- a/services/network/test/url_loader_context_for_tests.cc
+++ b/services/network/test/url_loader_context_for_tests.cc
@@ -23,16 +23,6 @@
   return factory_params_;
 }
 
-mojom::CookieAccessObserver* URLLoaderContextForTests::GetCookieAccessObserver()
-    const {
-  return nullptr;
-}
-
-mojom::TrustTokenAccessObserver*
-URLLoaderContextForTests::GetTrustTokenAccessObserver() const {
-  return nullptr;
-}
-
 mojom::CrossOriginEmbedderPolicyReporter*
 URLLoaderContextForTests::GetCoepReporter() const {
   return nullptr;
@@ -43,15 +33,6 @@
   return nullptr;
 }
 
-mojom::DevToolsObserver* URLLoaderContextForTests::GetDevToolsObserver() const {
-  return nullptr;
-}
-
-mojom::DeviceBoundSessionAccessObserver*
-URLLoaderContextForTests::GetDeviceBoundSessionAccessObserver() const {
-  return nullptr;
-}
-
 scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
 URLLoaderContextForTests::GetDeviceBoundSessionAccessObserverSharedRemote()
     const {
@@ -68,11 +49,6 @@
   return nullptr;
 }
 
-mojom::URLLoaderNetworkServiceObserver*
-URLLoaderContextForTests::GetURLLoaderNetworkServiceObserver() const {
-  return nullptr;
-}
-
 net::URLRequestContext* URLLoaderContextForTests::GetUrlRequestContext() const {
   return url_request_context_;
 }
diff --git a/services/network/test/url_loader_context_for_tests.h b/services/network/test/url_loader_context_for_tests.h
index b6ad259..497bd35 100644
--- a/services/network/test/url_loader_context_for_tests.h
+++ b/services/network/test/url_loader_context_for_tests.h
@@ -47,20 +47,13 @@
   bool ShouldRequireIsolationInfo() const override;
   const cors::OriginAccessList& GetOriginAccessList() const override;
   const mojom::URLLoaderFactoryParams& GetFactoryParams() const override;
-  mojom::CookieAccessObserver* GetCookieAccessObserver() const override;
-  mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver() const override;
   mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override;
   mojom::DocumentIsolationPolicyReporter* GetDipReporter() const override;
-  mojom::DevToolsObserver* GetDevToolsObserver() const override;
-  mojom::DeviceBoundSessionAccessObserver* GetDeviceBoundSessionAccessObserver()
-      const override;
   scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
   GetDeviceBoundSessionAccessObserverSharedRemote() const override;
   mojom::NetworkContextClient* GetNetworkContextClient() const override;
   mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
       const override;
-  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
-      const override;
   net::URLRequestContext* GetUrlRequestContext() const override;
   scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
       const override;
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index f846972..20fdf82b 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -211,19 +211,15 @@
   return hints;
 }
 
-template <typename T>
-T* PtrOrFallback(const mojo::Remote<T>& remote, T* fallback) {
-  return remote.is_bound() ? remote.get() : fallback;
-}
-
 scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
 MaybeInitializeDeviceBoundSessionAccessObserverSharedRemote(
-    mojo::Remote<mojom::DeviceBoundSessionAccessObserver>& remote,
+    ObserverWrapper<mojom::DeviceBoundSessionAccessObserver>& observer,
     URLLoaderContext& context) {
   if (!base::FeatureList::IsEnabled(
           features::kDeviceBoundSessionAccessObserverSharedRemote)) {
     return nullptr;
   }
+  auto remote = observer.TakeRemote();
   if (remote) {
     return base::MakeRefCounted<
         RefCountedDeviceBoundSessionAccessObserverRemote>(std::move(remote));
@@ -378,12 +374,12 @@
     std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_helper_factory,
     SharedDictionaryManager* shared_dictionary_manager,
     std::unique_ptr<SharedDictionaryAccessChecker> shared_dictionary_checker,
-    mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer,
-    mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer,
-    mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
+    ObserverWrapper<mojom::CookieAccessObserver> cookie_observer,
+    ObserverWrapper<mojom::TrustTokenAccessObserver> trust_token_observer,
+    ObserverWrapper<mojom::URLLoaderNetworkServiceObserver>
         url_loader_network_observer,
-    mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
-    mojo::PendingRemote<mojom::DeviceBoundSessionAccessObserver>
+    ObserverWrapper<mojom::DevToolsObserver> devtools_observer,
+    ObserverWrapper<mojom::DeviceBoundSessionAccessObserver>
         device_bound_session_observer,
     mojo::PendingRemote<mojom::AcceptCHFrameObserver> accept_ch_frame_observer,
     bool shared_storage_writable_eligible)
@@ -431,37 +427,22 @@
       storage_access_api_status_(request.storage_access_api_status),
       shared_dictionary_checker_(std::move(shared_dictionary_checker)),
       origin_access_list_(context.GetOriginAccessList()),
-      cookie_observer_remote_(std::move(cookie_observer)),
-      cookie_observer_(PtrOrFallback(cookie_observer_remote_,
-                                     context.GetCookieAccessObserver())),
-      trust_token_observer_remote_(std::move(trust_token_observer)),
-      trust_token_observer_(
-          PtrOrFallback(trust_token_observer_remote_,
-                        context.GetTrustTokenAccessObserver())),
-      url_loader_network_observer_remote_(
-          std::move(url_loader_network_observer)),
-      url_loader_network_observer_(
-          PtrOrFallback(url_loader_network_observer_remote_,
-                        context.GetURLLoaderNetworkServiceObserver())),
-      devtools_observer_remote_(std::move(devtools_observer)),
-      devtools_observer_(PtrOrFallback(devtools_observer_remote_,
-                                       context.GetDevToolsObserver())),
-      device_bound_session_observer_remote_(
-          std::move(device_bound_session_observer)),
-      device_bound_session_observer_(
-          PtrOrFallback(device_bound_session_observer_remote_,
-                        context.GetDeviceBoundSessionAccessObserver())),
+      cookie_observer_(std::move(cookie_observer)),
+      trust_token_observer_(std::move(trust_token_observer)),
+      url_loader_network_observer_(std::move(url_loader_network_observer)),
+      devtools_observer_(std::move(devtools_observer)),
+      device_bound_session_observer_(std::move(device_bound_session_observer)),
       device_bound_session_observer_shared_remote_(
           MaybeInitializeDeviceBoundSessionAccessObserverSharedRemote(
-              device_bound_session_observer_remote_,
+              device_bound_session_observer_,
               context)),
       shared_storage_request_helper_(
           std::make_unique<SharedStorageRequestHelper>(
               shared_storage_writable_eligible,
-              url_loader_network_observer_)),
+              url_loader_network_observer_.get())),
       ad_auction_event_record_request_helper_(
           request.attribution_reporting_eligibility,
-          url_loader_network_observer_),
+          url_loader_network_observer_.get()),
       has_fetch_streaming_upload_body_(HasFetchStreamingUploadBody(&request)),
       accept_ch_frame_observer_(std::move(accept_ch_frame_observer)),
       allow_cookies_from_browser_(
@@ -599,8 +580,6 @@
   // of this URLRequest. So pass a refcounted shared Remote that will outlive
   // `this`.
   if (device_bound_session_observer_shared_remote_) {
-    // Clear `device_bound_session_observer_` to avoid dangling ptr.
-    device_bound_session_observer_ = nullptr;
     url_request_->SetDeviceBoundSessionAccessCallback(base::BindRepeating(
         [](scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
                shared_remote,
@@ -1678,7 +1657,7 @@
   if (std::optional<mojom::BlockedByResponseReason> blocked_reason =
           MaybeBlockResponseForSRIMessageSignature(
               url_request_->url(), *response_, expected_public_keys_,
-              devtools_observer_, devtools_request_id().value_or(""))) {
+              devtools_observer_.get(), devtools_request_id().value_or(""))) {
     CompleteBlockedResponse(net::ERR_BLOCKED_BY_RESPONSE, false,
                             blocked_reason);
     // Close the socket associated with the request, to prevent leaking
diff --git a/services/network/url_loader.h b/services/network/url_loader.h
index 9c62cf1..103927c 100644
--- a/services/network/url_loader.h
+++ b/services/network/url_loader.h
@@ -40,6 +40,7 @@
 #include "services/network/ad_auction/event_record_request_helper.h"
 #include "services/network/keepalive_statistics_recorder.h"
 #include "services/network/network_service.h"
+#include "services/network/observer_wrapper.h"
 #include "services/network/partial_decoder.h"
 #include "services/network/private_network_access_checker.h"
 #include "services/network/public/cpp/cors/cors_error_status.h"
@@ -170,13 +171,13 @@
           trust_token_helper_factory,
       SharedDictionaryManager* shared_dictionary_manager,
       std::unique_ptr<SharedDictionaryAccessChecker> shared_dictionary_checker,
-      mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer,
-      mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer,
-      mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
+      ObserverWrapper<mojom::CookieAccessObserver> cookie_observer,
+      ObserverWrapper<mojom::TrustTokenAccessObserver> trust_token_observer,
+      ObserverWrapper<mojom::URLLoaderNetworkServiceObserver>
           url_loader_network_observer,
-      mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer,
-      mojo::PendingRemote<mojom::DeviceBoundSessionAccessObserver>
-          device_bound_session_access_observer,
+      ObserverWrapper<mojom::DevToolsObserver> devtools_observer,
+      ObserverWrapper<mojom::DeviceBoundSessionAccessObserver>
+          device_bound_session_observer,
       mojo::PendingRemote<mojom::AcceptCHFrameObserver>
           accept_ch_frame_observer,
       bool shared_storage_writable_eligible);
@@ -227,7 +228,7 @@
 
   mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
       const {
-    return url_loader_network_observer_;
+    return url_loader_network_observer_.get();
   }
 
   // mojom::AuthChallengeResponder:
@@ -749,29 +750,19 @@
   // Outlives `this`.
   const raw_ref<const cors::OriginAccessList> origin_access_list_;
 
-  // Observers bound to this specific URLLoader. There may be observers bound to
-  // an URLLoaderFactory as well so these `mojo::Remote`s should not be used
-  // directly, but the pointer fields should be used instead (e.g.
-  // `cookie_observer_` should be used since, it can be set to *either*
-  // `cookie_observer_.get()` *or* is can be pointing to some other
-  // CookieAccessObserver implementation from the URLLoaderContext aka
-  // URLLoaderFactory).
-  const mojo::Remote<mojom::CookieAccessObserver> cookie_observer_remote_;
-  const raw_ptr<mojom::CookieAccessObserver> cookie_observer_ = nullptr;
-  const mojo::Remote<mojom::TrustTokenAccessObserver>
-      trust_token_observer_remote_;
-  const raw_ptr<mojom::TrustTokenAccessObserver> trust_token_observer_ =
-      nullptr;
-  const mojo::Remote<mojom::URLLoaderNetworkServiceObserver>
-      url_loader_network_observer_remote_;
-  const raw_ptr<mojom::URLLoaderNetworkServiceObserver>
-      url_loader_network_observer_ = nullptr;
-  const mojo::Remote<mojom::DevToolsObserver> devtools_observer_remote_;
-  const raw_ptr<mojom::DevToolsObserver> devtools_observer_ = nullptr;
-  mojo::Remote<mojom::DeviceBoundSessionAccessObserver>
-      device_bound_session_observer_remote_;
-  raw_ptr<mojom::DeviceBoundSessionAccessObserver>
-      device_bound_session_observer_ = nullptr;
+  // Observer instances relevant to this URLLoader.
+  // Each ObserverWrapper encapsulates either a Mojo Remote for an observer
+  // specific to this request (usually passed via TrustedParams) or a fallback
+  // pointer (usually pointing to a shared observer implementation held by the
+  // URLLoaderFactory/URLLoaderContext).
+  ObserverWrapper<mojom::CookieAccessObserver> cookie_observer_;
+  ObserverWrapper<mojom::TrustTokenAccessObserver> trust_token_observer_;
+  ObserverWrapper<mojom::URLLoaderNetworkServiceObserver>
+      url_loader_network_observer_;
+  ObserverWrapper<mojom::DevToolsObserver> devtools_observer_;
+  ObserverWrapper<mojom::DeviceBoundSessionAccessObserver>
+      device_bound_session_observer_;
+
   const scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
       device_bound_session_observer_shared_remote_;
 
diff --git a/services/network/url_loader_context.h b/services/network/url_loader_context.h
index 87afffd6..bd7df86 100644
--- a/services/network/url_loader_context.h
+++ b/services/network/url_loader_context.h
@@ -25,14 +25,10 @@
 }  // namespace cors
 
 namespace mojom {
-class CookieAccessObserver;
 class CrossOriginEmbedderPolicyReporter;
-class DevToolsObserver;
 class NetworkContextClient;
 class TrustedURLLoaderHeaderClient;
-class TrustTokenAccessObserver;
 class URLLoaderFactoryParams;
-class URLLoaderNetworkServiceObserver;
 }  // namespace mojom
 
 using RefCountedDeviceBoundSessionAccessObserverRemote = base::RefCountedData<
@@ -45,24 +41,16 @@
   virtual bool ShouldRequireIsolationInfo() const = 0;
   virtual const cors::OriginAccessList& GetOriginAccessList() const = 0;
   virtual const mojom::URLLoaderFactoryParams& GetFactoryParams() const = 0;
-  virtual mojom::CookieAccessObserver* GetCookieAccessObserver() const = 0;
-  virtual mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver()
-      const = 0;
   virtual mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const = 0;
   virtual mojom::DocumentIsolationPolicyReporter* GetDipReporter() const = 0;
-  virtual mojom::DevToolsObserver* GetDevToolsObserver() const = 0;
   virtual mojom::NetworkContextClient* GetNetworkContextClient() const = 0;
   virtual mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
       const = 0;
-  virtual mojom::URLLoaderNetworkServiceObserver*
-  GetURLLoaderNetworkServiceObserver() const = 0;
   virtual net::URLRequestContext* GetUrlRequestContext() const = 0;
   virtual scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
       const = 0;
   virtual orb::PerFactoryState& GetMutableOrbState() = 0;
   virtual bool DataUseUpdatesEnabled() = 0;
-  virtual mojom::DeviceBoundSessionAccessObserver*
-  GetDeviceBoundSessionAccessObserver() const = 0;
   virtual scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
   GetDeviceBoundSessionAccessObserverSharedRemote() const = 0;
 
diff --git a/services/network/url_loader_factory.cc b/services/network/url_loader_factory.cc
index 41320bd6..7d9c7f1 100644
--- a/services/network/url_loader_factory.cc
+++ b/services/network/url_loader_factory.cc
@@ -26,6 +26,7 @@
 #include "services/network/cors/cors_url_loader_factory.h"
 #include "services/network/network_context.h"
 #include "services/network/network_service.h"
+#include "services/network/observer_wrapper.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/is_potentially_trustworthy.h"
 #include "services/network/public/cpp/resource_request.h"
@@ -41,6 +42,42 @@
 
 namespace network {
 
+namespace {
+
+// Helper function template to create ObserverWrapper instances.
+// Encapsulates the logic of potentially moving a PendingRemote from
+// TrustedParams based on a member pointer, or using a fallback pointer.
+template <typename T>
+ObserverWrapper<T> CreateObserverWrapper(
+    const std::optional<ResourceRequest::TrustedParams> trusted_params,
+    mojo::PendingRemote<T> ResourceRequest::TrustedParams::* remote_member_ptr,
+    T* fallback_ptr) {
+  mojo::PendingRemote<T> remote_to_pass;
+  if (trusted_params) {
+    auto& remote_member =
+        const_cast<ResourceRequest::TrustedParams*>(&trusted_params.value())
+            ->*remote_member_ptr;
+    if (remote_member.is_valid()) {
+      remote_to_pass = std::move(remote_member);
+    }
+  }
+  return ObserverWrapper<T>(std::move(remote_to_pass), fallback_ptr);
+}
+
+// Overload of CreateObserverWrapper that takes a mojo::Remote reference
+// for the fallback, simplifying calls where the fallback is held in a Remote.
+template <typename T>
+ObserverWrapper<T> CreateObserverWrapper(
+    const std::optional<ResourceRequest::TrustedParams> trusted_params,
+    mojo::PendingRemote<T> ResourceRequest::TrustedParams::* remote_member_ptr,
+    mojo::Remote<T>& remote_for_fallback_ptr) {
+  return CreateObserverWrapper<T>(
+      trusted_params, remote_member_ptr,
+      remote_for_fallback_ptr ? remote_for_fallback_ptr.get() : nullptr);
+}
+
+}  // namespace
+
 constexpr int URLLoaderFactory::kMaxKeepaliveConnections;
 constexpr int URLLoaderFactory::kMaxKeepaliveConnectionsPerTopLevelFrame;
 constexpr int URLLoaderFactory::kMaxTotalKeepaliveRequestSize;
@@ -301,47 +338,29 @@
     }
   }
 
-  mojo::PendingRemote<mojom::CookieAccessObserver> cookie_observer;
-  if (resource_request.trusted_params &&
-      resource_request.trusted_params->cookie_observer) {
-    cookie_observer =
-        std::move(const_cast<mojo::PendingRemote<mojom::CookieAccessObserver>&>(
-            resource_request.trusted_params->cookie_observer));
-  }
-  mojo::PendingRemote<mojom::TrustTokenAccessObserver> trust_token_observer;
-  if (resource_request.trusted_params &&
-      resource_request.trusted_params->trust_token_observer) {
-    trust_token_observer = std::move(
-        const_cast<mojo::PendingRemote<mojom::TrustTokenAccessObserver>&>(
-            resource_request.trusted_params->trust_token_observer));
-  }
-  mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>
-      url_loader_network_observer;
-  if (resource_request.trusted_params &&
-      resource_request.trusted_params->url_loader_network_observer) {
-    url_loader_network_observer =
-        std::move(const_cast<
-                  mojo::PendingRemote<mojom::URLLoaderNetworkServiceObserver>&>(
-            resource_request.trusted_params->url_loader_network_observer));
-  }
-
-  mojo::PendingRemote<mojom::DevToolsObserver> devtools_observer;
-  if (resource_request.trusted_params &&
-      resource_request.trusted_params->devtools_observer) {
-    devtools_observer =
-        std::move(const_cast<mojo::PendingRemote<mojom::DevToolsObserver>&>(
-            resource_request.trusted_params->devtools_observer));
-  }
-
-  mojo::PendingRemote<mojom::DeviceBoundSessionAccessObserver>
-      device_bound_session_observer;
-  if (resource_request.trusted_params &&
-      resource_request.trusted_params->device_bound_session_observer) {
-    device_bound_session_observer = std::move(
-        const_cast<
-            mojo::PendingRemote<mojom::DeviceBoundSessionAccessObserver>&>(
-            resource_request.trusted_params->device_bound_session_observer));
-  }
+  auto cookie_observer = CreateObserverWrapper<mojom::CookieAccessObserver>(
+      resource_request.trusted_params,
+      &ResourceRequest::TrustedParams::cookie_observer, cookie_observer_);
+  auto trust_token_observer =
+      CreateObserverWrapper<mojom::TrustTokenAccessObserver>(
+          resource_request.trusted_params,
+          &ResourceRequest::TrustedParams::trust_token_observer,
+          trust_token_observer_);
+  auto url_loader_network_observer =
+      CreateObserverWrapper<mojom::URLLoaderNetworkServiceObserver>(
+          resource_request.trusted_params,
+          &ResourceRequest::TrustedParams::url_loader_network_observer,
+          GetURLLoaderNetworkServiceObserver());
+  auto devtools_observer = CreateObserverWrapper<mojom::DevToolsObserver>(
+      resource_request.trusted_params,
+      &ResourceRequest::TrustedParams::devtools_observer, devtools_observer_);
+  auto device_bound_session_observer =
+      CreateObserverWrapper<mojom::DeviceBoundSessionAccessObserver>(
+          resource_request.trusted_params,
+          &ResourceRequest::TrustedParams::device_bound_session_observer,
+          device_bound_session_observer_
+              ? device_bound_session_observer_->data.get()
+              : nullptr);
 
   mojo::PendingRemote<mojom::AcceptCHFrameObserver> accept_ch_frame_observer;
   if (resource_request.trusted_params &&
@@ -382,34 +401,11 @@
   return nullptr;
 }
 
-mojom::DeviceBoundSessionAccessObserver*
-URLLoaderFactory::GetDeviceBoundSessionAccessObserver() const {
-  if (device_bound_session_observer_) {
-    return device_bound_session_observer_->data.get();
-  }
-  return nullptr;
-}
-
 scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
 URLLoaderFactory::GetDeviceBoundSessionAccessObserverSharedRemote() const {
   return device_bound_session_observer_;
 }
 
-mojom::CookieAccessObserver* URLLoaderFactory::GetCookieAccessObserver() const {
-  if (cookie_observer_) {
-    return cookie_observer_.get();
-  }
-  return nullptr;
-}
-
-mojom::TrustTokenAccessObserver* URLLoaderFactory::GetTrustTokenAccessObserver()
-    const {
-  if (trust_token_observer_) {
-    return trust_token_observer_.get();
-  }
-  return nullptr;
-}
-
 mojom::URLLoaderNetworkServiceObserver*
 URLLoaderFactory::GetURLLoaderNetworkServiceObserver() const {
   if (cors_url_loader_factory_->url_loader_network_service_observer()) {
diff --git a/services/network/url_loader_factory.h b/services/network/url_loader_factory.h
index 4bf78007..233a642 100644
--- a/services/network/url_loader_factory.h
+++ b/services/network/url_loader_factory.h
@@ -76,23 +76,16 @@
   bool ShouldRequireIsolationInfo() const override;
   const cors::OriginAccessList& GetOriginAccessList() const override;
   const mojom::URLLoaderFactoryParams& GetFactoryParams() const override;
-  mojom::CookieAccessObserver* GetCookieAccessObserver() const override;
-  mojom::TrustTokenAccessObserver* GetTrustTokenAccessObserver() const override;
   mojom::CrossOriginEmbedderPolicyReporter* GetCoepReporter() const override;
   mojom::DocumentIsolationPolicyReporter* GetDipReporter() const override;
-  mojom::DevToolsObserver* GetDevToolsObserver() const override;
   mojom::NetworkContextClient* GetNetworkContextClient() const override;
   mojom::TrustedURLLoaderHeaderClient* GetUrlLoaderHeaderClient()
       const override;
-  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
-      const override;
   net::URLRequestContext* GetUrlRequestContext() const override;
   scoped_refptr<ResourceSchedulerClient> GetResourceSchedulerClient()
       const override;
   orb::PerFactoryState& GetMutableOrbState() override;
   bool DataUseUpdatesEnabled() override;
-  mojom::DeviceBoundSessionAccessObserver* GetDeviceBoundSessionAccessObserver()
-      const override;
   scoped_refptr<RefCountedDeviceBoundSessionAccessObserverRemote>
   GetDeviceBoundSessionAccessObserverSharedRemote() const override;
 
@@ -107,6 +100,8 @@
       base::WeakPtr<mojom::URLLoaderClient> sync_client,
       const net::MutableNetworkTrafficAnnotationTag& traffic_annotation);
 
+  mojom::DevToolsObserver* GetDevToolsObserver() const;
+
   // Returns the network that URLLoaders, created out of this factory, will
   // target. If == net::handles::kInvalidNetworkHandle, then no network is being
   // targeted and the system default network will be used (see
@@ -118,6 +113,9 @@
   static constexpr int kMaxTotalKeepaliveRequestSize = 512 * 1024;
 
  private:
+  mojom::URLLoaderNetworkServiceObserver* GetURLLoaderNetworkServiceObserver()
+      const;
+
   // The NetworkContext that indirectly owns |this|.
   const raw_ptr<NetworkContext> context_;
   mojom::URLLoaderFactoryParamsPtr params_;
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index 6d90331..f8a2cc1 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -100,6 +100,7 @@
 #include "net/url_request/url_request_test_job.h"
 #include "net/url_request/url_request_test_util.h"
 #include "services/network/file_opener_for_upload.h"
+#include "services/network/observer_wrapper.h"
 #include "services/network/public/cpp/cors/origin_access_list.h"
 #include "services/network/public/cpp/features.h"
 #include "services/network/public/cpp/ip_address_space_util.h"
@@ -678,11 +679,13 @@
         keepalive_request_size, std::move(keepalive_statistics_recorder),
         std::move(trust_token_helper_factory),
         std::move(shared_dictionary_manager),
-        std::move(shared_dictionary_checker), std::move(cookie_observer),
-        std::move(trust_token_observer), std::move(url_loader_network_observer),
-        std::move(devtools_observer), std::move(device_bound_session_observer),
-        std::move(accept_ch_frame_observer),
-        shared_storage_writable_eligible);
+        std::move(shared_dictionary_checker),
+        ObserverWrapper(std::move(cookie_observer)),
+        ObserverWrapper(std::move(trust_token_observer)),
+        ObserverWrapper(std::move(url_loader_network_observer)),
+        ObserverWrapper(std::move(devtools_observer)),
+        ObserverWrapper(std::move(device_bound_session_observer)),
+        std::move(accept_ch_frame_observer), shared_storage_writable_eligible);
   }
 
   int32_t options = mojom::kURLLoadOptionNone;
diff --git a/services/on_device_model/ml/chrome_ml_api.h b/services/on_device_model/ml/chrome_ml_api.h
index 7e9e7544..195bab66 100644
--- a/services/on_device_model/ml/chrome_ml_api.h
+++ b/services/on_device_model/ml/chrome_ml_api.h
@@ -9,6 +9,7 @@
 #include <functional>
 #include <optional>
 #include <string>
+#include <vector>
 
 #include "services/on_device_model/ml/chrome_ml_types.h"
 #include "third_party/dawn/include/dawn/dawn_proc_table.h"
@@ -196,6 +197,11 @@
 // This will be called on the internal thread executing the model.
 using ChromeMLScoreFn = std::function<void(float)>;
 
+// Called with a vector of probability scores after a call to
+// GetProbabilitiesBlocking().
+using ChromeMLGetProbabilitiesBlockingFn =
+    std::function<void(const std::vector<float>&)>;
+
 struct ChromeMLExecuteOptions {
   int context_mode;
   uint32_t max_tokens;
@@ -377,6 +383,13 @@
                        const std::string& text,
                        const ChromeMLScoreFn& fn);
 
+  // Get the probabilities of a batch of tokens.
+  // Note that this is a blocking call, and mainly used for testing purpose.
+  void (*SessionGetProbabilitiesBlocking)(
+      ChromeMLSession session,
+      const std::string& input,
+      const ChromeMLGetProbabilitiesBlockingFn& fn);
+
   // Create a new session in the model, optionally loading adaptation data.
   ChromeMLSession (*CreateSession)(
       ChromeMLModel model,
diff --git a/services/on_device_model/ml/on_device_model_executor.cc b/services/on_device_model/ml/on_device_model_executor.cc
index 4de2b0c..2ba7e53 100644
--- a/services/on_device_model/ml/on_device_model_executor.cc
+++ b/services/on_device_model/ml/on_device_model_executor.cc
@@ -323,6 +323,14 @@
   session_->Score(text, ConvertCallbackToFn(std::move(callback)));
 }
 
+DISABLE_CFI_DLSYM
+void SessionImpl::GetProbabilitiesBlocking(
+    const std::string& input,
+    base::OnceCallback<void(const std::vector<float>&)> callback) {
+  session_->GetProbabilitiesBlocking(input,
+                                     ConvertCallbackToFn(std::move(callback)));
+}
+
 std::unique_ptr<SessionImpl> SessionImpl::Clone() {
   return std::make_unique<SessionImpl>(
       chrome_ml_.get(), model_, session_->Clone(), max_tokens_, adaptation_id_);
diff --git a/services/on_device_model/ml/on_device_model_executor.h b/services/on_device_model/ml/on_device_model_executor.h
index 49662db6..3c1145a 100644
--- a/services/on_device_model/ml/on_device_model_executor.h
+++ b/services/on_device_model/ml/on_device_model_executor.h
@@ -8,6 +8,7 @@
 #include <cstdint>
 #include <functional>
 #include <memory>
+#include <vector>
 
 #include "base/component_export.h"
 #include "base/files/file_path.h"
@@ -53,6 +54,9 @@
   void SizeInTokens(on_device_model::mojom::InputPtr input,
                     base::OnceCallback<void(uint32_t)> callback);
   void Score(const std::string& text, base::OnceCallback<void(float)> callback);
+  void GetProbabilitiesBlocking(
+      const std::string& input,
+      base::OnceCallback<void(const std::vector<float>&)> callback);
   std::unique_ptr<SessionImpl> Clone();
 
  private:
diff --git a/services/on_device_model/ml/session_accessor.cc b/services/on_device_model/ml/session_accessor.cc
index d566b17f..71e4a9ed 100644
--- a/services/on_device_model/ml/session_accessor.cc
+++ b/services/on_device_model/ml/session_accessor.cc
@@ -120,6 +120,15 @@
                      text, std::move(score_fn)));
 }
 
+void SessionAccessor::GetProbabilitiesBlocking(
+    const std::string& input,
+    ChromeMLGetProbabilitiesBlockingFn get_prob_fn) {
+  task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&SessionAccessor::GetProbabilitiesBlockingInternal,
+                     base::Unretained(this), input, std::move(get_prob_fn)));
+}
+
 void SessionAccessor::SizeInTokens(on_device_model::mojom::InputPtr input,
                                    ChromeMLSizeInTokensFn size_in_tokens_fn) {
   task_runner_->PostTask(
@@ -233,6 +242,15 @@
 }
 
 DISABLE_CFI_DLSYM
+void SessionAccessor::GetProbabilitiesBlockingInternal(
+    const std::string& input,
+    ChromeMLGetProbabilitiesBlockingFn get_prob_fn) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+  chrome_ml_->api().SessionGetProbabilitiesBlocking(session_, input,
+                                                    get_prob_fn);
+}
+
+DISABLE_CFI_DLSYM
 void SessionAccessor::SizeInTokensInternal(
     on_device_model::mojom::InputPtr input,
     ChromeMLSizeInTokensFn size_in_tokens_fn) {
diff --git a/services/on_device_model/ml/session_accessor.h b/services/on_device_model/ml/session_accessor.h
index d5520a7..47db944 100644
--- a/services/on_device_model/ml/session_accessor.h
+++ b/services/on_device_model/ml/session_accessor.h
@@ -41,6 +41,8 @@
   ChromeMLCancelFn Generate(on_device_model::mojom::GenerateOptionsPtr options,
                             ChromeMLExecutionOutputFn output_fn);
   void Score(const std::string& text, ChromeMLScoreFn score_fn);
+  void GetProbabilitiesBlocking(const std::string& input,
+                                ChromeMLGetProbabilitiesBlockingFn get_prob_fn);
   void SizeInTokens(on_device_model::mojom::InputPtr input,
                     ChromeMLSizeInTokensFn size_in_tokens_fn);
 
@@ -64,6 +66,9 @@
       ChromeMLExecutionOutputFn output_fn,
       scoped_refptr<Canceler> canceler);
   void ScoreInternal(const std::string& text, ChromeMLScoreFn score_fn);
+  void GetProbabilitiesBlockingInternal(
+      const std::string& input,
+      ChromeMLGetProbabilitiesBlockingFn get_prob_fn);
   void SizeInTokensInternal(on_device_model::mojom::InputPtr input,
                             ChromeMLSizeInTokensFn size_in_tokens_fn);
 
diff --git a/services/on_device_model/on_device_model_service.cc b/services/on_device_model/on_device_model_service.cc
index 546d3cd..2f826e5b 100644
--- a/services/on_device_model/on_device_model_service.cc
+++ b/services/on_device_model/on_device_model_service.cc
@@ -59,6 +59,9 @@
   void GetSizeInTokens(mojom::InputPtr input,
                        GetSizeInTokensCallback callback) override;
   void Score(const std::string& text, ScoreCallback callback) override;
+  void GetProbabilitiesBlocking(
+      const std::string& text,
+      GetProbabilitiesBlockingCallback callback) override;
   void Clone(mojo::PendingReceiver<mojom::Session> session) override;
 
   mojo::Receiver<mojom::Session>& receiver() { return receiver_; }
@@ -91,6 +94,14 @@
     session_->Score(text, std::move(callback).Then(std::move(on_complete)));
   }
 
+  void GetProbabilitiesBlockingInternal(
+      const std::string& text,
+      GetProbabilitiesBlockingCallback callback,
+      base::OnceClosure on_complete) {
+    session_->GetProbabilitiesBlocking(
+        text, std::move(callback).Then(std::move(on_complete)));
+  }
+
   void CloneInternal(mojo::PendingReceiver<mojom::Session> session);
 
   base::WeakPtr<ModelWrapper> model_;
@@ -298,6 +309,20 @@
       weak_ptr_factory_.GetWeakPtr());
 }
 
+void SessionWrapper::GetProbabilitiesBlocking(
+    const std::string& text,
+    GetProbabilitiesBlockingCallback callback) {
+  if (!model_) {
+    std::move(callback).Run(std::vector<float>());
+    return;
+  }
+
+  model_->AddAndRunPendingTask(
+      base::BindOnce(&SessionWrapper::GetProbabilitiesBlockingInternal,
+                     weak_ptr_factory_.GetWeakPtr(), text, std::move(callback)),
+      weak_ptr_factory_.GetWeakPtr());
+}
+
 void SessionWrapper::Clone(mojo::PendingReceiver<mojom::Session> session) {
   if (!model_) {
     return;
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.cc b/services/on_device_model/public/cpp/test_support/fake_service.cc
index 32cfdd4..50d7ca7 100644
--- a/services/on_device_model/public/cpp/test_support/fake_service.cc
+++ b/services/on_device_model/public/cpp/test_support/fake_service.cc
@@ -133,6 +133,12 @@
   std::move(callback).Run(0.5);
 }
 
+void FakeOnDeviceSession::GetProbabilitiesBlocking(
+    const std::string& text,
+    GetProbabilitiesBlockingCallback callback) {
+  std::move(callback).Run({0.5});
+}
+
 void FakeOnDeviceSession::Clone(
     mojo::PendingReceiver<on_device_model::mojom::Session> session) {
   auto new_session =
diff --git a/services/on_device_model/public/cpp/test_support/fake_service.h b/services/on_device_model/public/cpp/test_support/fake_service.h
index 11829829..6846b07 100644
--- a/services/on_device_model/public/cpp/test_support/fake_service.h
+++ b/services/on_device_model/public/cpp/test_support/fake_service.h
@@ -89,6 +89,10 @@
 
   void Score(const std::string& text, ScoreCallback callback) override;
 
+  void GetProbabilitiesBlocking(
+      const std::string& text,
+      GetProbabilitiesBlockingCallback callback) override;
+
   void Clone(
       mojo::PendingReceiver<on_device_model::mojom::Session> session) override;
 
diff --git a/services/on_device_model/public/mojom/on_device_model.mojom b/services/on_device_model/public/mojom/on_device_model.mojom
index 6ab0c489..d16d2e7 100644
--- a/services/on_device_model/public/mojom/on_device_model.mojom
+++ b/services/on_device_model/public/mojom/on_device_model.mojom
@@ -240,6 +240,13 @@
   // Clones the current session. The cloned session will have the same context
   // as the current session.
   Clone@4(pending_receiver<Session> session);
+
+  // Gets the probability for a series of tokens on top of the current
+  // context. Capabilities.probabilities_output must be specified to use this.
+  // Note that this is implemented as a blocking method on the service side
+  // and should only be used in debugging/testing.
+  [MinVersion=3]
+  GetProbabilitiesBlocking@8(string text) => (array<float> probabilities);
 };
 
 // A loaded model which can be queried. This interface must be controlled by the
diff --git a/services/viz/public/cpp/compositing/mojom_traits_perftest.cc b/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
index c076c6f..b890098 100644
--- a/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
+++ b/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
@@ -267,10 +267,10 @@
           /*fast_rounded_corner=*/false);
       for (uint32_t j = 0; j < 6; ++j) {
         auto* tile_in = pass_in->CreateAndAppendDrawQuad<TileDrawQuad>();
-        tile_in->SetAll(
-            shared_state2_in, arbitrary_rect2, arbitrary_rect1_inside_rect2,
-            arbitrary_bool1, arbitrary_resourceid3, arbitrary_rectf1,
-            arbitrary_size1, arbitrary_bool2, arbitrary_bool3, arbitrary_bool4);
+        tile_in->SetAll(shared_state2_in, arbitrary_rect2,
+                        arbitrary_rect1_inside_rect2, arbitrary_bool1,
+                        arbitrary_resourceid3, arbitrary_rectf1,
+                        arbitrary_size1, arbitrary_bool2, arbitrary_bool3);
       }
     }
 
diff --git a/services/viz/public/mojom/compositing/tiling.mojom b/services/viz/public/mojom/compositing/tiling.mojom
index 8fcec3f..26dd1de 100644
--- a/services/viz/public/mojom/compositing/tiling.mojom
+++ b/services/viz/public/mojom/compositing/tiling.mojom
@@ -13,9 +13,6 @@
   // Identifies the actual texture resource containing rasterized tile contents.
   TransferableResource resource;
 
-  // Whether or not the texture has a premultiplied alpha channel.
-  bool is_premultiplied;
-
   // Whether or not the texture was rasterized with checker-imaged content.
   bool is_checkered;
 };
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index c05f3d7..123ba43 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -15440,27 +15440,6 @@
             ]
         }
     ],
-    "NewOSCryptAlgorithmForPasswords": [
-        {
-            "platforms": [
-                "android",
-                "chromeos",
-                "ios",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "EncryptAllPasswordsWithOSCryptAsync",
-                        "UseNewEncryptionMethod"
-                    ]
-                }
-            ]
-        }
-    ],
     "NoPasswordSuggestionFiltering": [
         {
             "platforms": [
@@ -18245,9 +18224,6 @@
                     "enable_features": [
                         "DocumentPolicyExpectNoLinkedResources",
                         "PreloadLinkRelDataUrls"
-                    ],
-                    "disable_features": [
-                        "BypassCSPForPreloads"
                     ]
                 }
             ]
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index a15cb44e..bfe8f6f 100644
--- a/third_party/androidx/build.gradle
+++ b/third_party/androidx/build.gradle
@@ -296,7 +296,7 @@
     google()
     maven {
         // This URL is generated by the fetch_all_androidx.py script.
-        url 'https://androidx.dev/snapshots/builds/13323247/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/13325735/artifacts/repository'
     }
     mavenCentral()
 }
diff --git a/third_party/angle b/third_party/angle
index 6e992fa..48b7d12 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit 6e992fa20b4bbcc5c7892ce085d95b0549c9cfa8
+Subproject commit 48b7d12ee04af9fae02eb756f94d1974f1c4bd45
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index bb019158..b6e1daf0 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -4862,6 +4862,7 @@
   kCustomHighlightPseudoElement = 5476,
   kSpellingErrorPseudoElement = 5477,
   kGrammarErrorPseudoElement = 5478,
+  kSpeculationRulesTags = 5479,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots. Also don't add extra
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
index 29a3a3a..bf6651b 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.cc
@@ -521,6 +521,11 @@
   for (auto& [style_sheet, rule_set] : active_style_sheets_) {
     AddRuleSetToRuleSetGroupList(rule_set, rule_set_groups_);
   }
+  // Any @layer rules within the new list of active stylesheets
+  // must be collected in the cross-sheet layer map. Otherwise,
+  // CascadeLayerSeeker will not be able to figure out the layer
+  // order during rule collection.
+  RebuildCascadeLayerMap(active_style_sheets_);
 }
 
 void ScopedStyleResolver::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
index b8eaa09..523be57d 100644
--- a/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
+++ b/third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h
@@ -83,7 +83,22 @@
     return active_style_sheets_;
   }
 
-  // See InspectorGhostRules.
+  // When the stylesheets are quietly swapped, no invalidation takes
+  // place, but calls to ElementRuleCollector::CollectMatchingRules
+  // will "see" the swapped-in sheets, and return its result accordingly.
+  // This allows the Inspector to query an "alternate reality" which
+  // may be different from what the style engine normally observes
+  // (see InspectorGhostRules).
+  //
+  // This approach has limitations, however: name-defining at-rules
+  // such as @keyframes are generally not applied: if `other` contains
+  // any @keyframes that differ from the original stylesheets,
+  // those changes are effectively ignored.
+  //
+  // Quietly swapping stylesheets does however cause the layer map
+  // (`cascade_layer_map_`) to be rebuilt, because any CascadeLayer
+  // instances within `other` must exist in this map for rule matching
+  // to function (see `CascadeLayerSeeker`).
   void QuietlySwapActiveStyleSheets(ActiveStyleSheetVector& other);
 
   void AppendActiveStyleSheets(unsigned index, const ActiveStyleSheetVector&);
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 13d77078..011d4055 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
@@ -73,7 +73,7 @@
     return nullptr;
   SkImageInfo info = SkImageInfo::Make(
       gfx::SizeToSkISize(size), GetRenderingContextSkColorType(),
-      kPremul_SkAlphaType, GetRenderingContextSkColorSpace());
+      kPremul_SkAlphaType, GetRenderingContextColorSpace().ToSkColorSpace());
   sk_sp<SkSurface> surface =
       SkSurfaces::Raster(info, info.minRowBytes(), nullptr);
   if (!surface)
@@ -374,11 +374,6 @@
                             : GetN32FormatForCanvas();
 }
 
-sk_sp<SkColorSpace>
-CanvasRenderingContextHost::GetRenderingContextSkColorSpace() const {
-  return GetRenderingContextColorSpace().ToSkColorSpace();
-}
-
 gfx::ColorSpace CanvasRenderingContextHost::GetRenderingContextColorSpace()
     const {
   return RenderingContext() ? RenderingContext()->GetColorSpace()
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
index dd043a3..8dec2f2 100644
--- a/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
+++ b/third_party/blink/renderer/core/html/canvas/canvas_rendering_context_host.h
@@ -112,7 +112,6 @@
   SkAlphaType GetRenderingContextAlphaType() const;
   SkColorType GetRenderingContextSkColorType() const;
   viz::SharedImageFormat GetRenderingContextFormat() const;
-  sk_sp<SkColorSpace> GetRenderingContextSkColorSpace() const;
   gfx::ColorSpace GetRenderingContextColorSpace() const;
   PlainTextPainter& GetPlainTextPainter();
 
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
index ca6c4496..d1645b9f 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.cc
@@ -1204,18 +1204,18 @@
         // size. Hence, we need to query the adjusted size of DrawingBuffer.
         gfx::Size adjusted_size = context_->DrawingBufferSize();
         if (!adjusted_size.IsEmpty()) {
-          SkColorType color_type = GetRenderingContextSkColorType();
-          if (color_type == kN32_SkColorType) {
-            color_type = kRGBA_8888_SkColorType;
-          } else {
-            color_type = kRGBA_F16_SkColorType;
+          auto format = GetRenderingContextFormat();
+          if (format != viz::SinglePlaneFormat::kRGBA_8888) {
+            format = (format == viz::SinglePlaneFormat::kBGRA_8888)
+                         ? viz::SinglePlaneFormat::kRGBA_8888
+                         : viz::SinglePlaneFormat::kRGBA_F16;
           }
           image_bitmap = StaticBitmapImage::Create(
               std::move(pixel_data),
               SkImageInfo::Make(
                   SkISize::Make(adjusted_size.width(), adjusted_size.height()),
-                  color_type, kUnpremul_SkAlphaType,
-                  GetRenderingContextSkColorSpace()));
+                  viz::ToClosestSkColorType(format), kUnpremul_SkAlphaType,
+                  GetRenderingContextColorSpace().ToSkColorSpace()));
         }
       }
     }
diff --git a/third_party/blink/renderer/core/inspector/dev_tools_host.cc b/third_party/blink/renderer/core/inspector/dev_tools_host.cc
index 4c131ba..25a0e0a 100644
--- a/third_party/blink/renderer/core/inspector/dev_tools_host.cc
+++ b/third_party/blink/renderer/core/inspector/dev_tools_host.cc
@@ -197,7 +197,7 @@
   // '&' does not show up in context menus unless replaced by '&&'.
   String label = item->getLabelOr(String()).Replace('&', "&&");
   label.Ensure16Bit();
-  return std::u16string(label.Characters16(), label.length());
+  return std::u16string(label.View16());
 }
 
 static std::vector<MenuItemInfo> PopulateContextMenuItems(
diff --git a/third_party/blink/renderer/core/layout/box_fragment_builder.cc b/third_party/blink/renderer/core/layout/box_fragment_builder.cc
index 249c208..7c6096d 100644
--- a/third_party/blink/renderer/core/layout/box_fragment_builder.cc
+++ b/third_party/blink/renderer/core/layout/box_fragment_builder.cc
@@ -408,6 +408,10 @@
   for (auto& child : children_)
     child.offset.block_offset += delta;
 
+  for (auto& child : children_with_size_dependent_propagation_) {
+    child.offset.block_offset += delta;
+  }
+
   for (auto& candidate : oof_positioned_candidates_)
     candidate.static_position.offset.block_offset += delta;
   for (auto& descendant : oof_positioned_fragmentainer_descendants_) {
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.cc b/third_party/blink/renderer/core/loader/base_fetch_context.cc
index 950089f..56be385 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -39,13 +39,11 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     ReportingDisposition reporting_disposition,
-    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-    FetchParameters::HasPreloadedResponseCandidate
-        has_preloaded_response_candidate) const {
+    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+    const {
   std::optional<ResourceRequestBlockedReason> blocked_reason =
       CanRequestInternal(type, resource_request, url, options,
-                         reporting_disposition, redirect_info,
-                         has_preloaded_response_candidate);
+                         reporting_disposition, redirect_info);
   if (blocked_reason &&
       reporting_disposition == ReportingDisposition::kReport) {
     DispatchDidBlockRequest(resource_request, options, blocked_reason.value(),
@@ -183,9 +181,8 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     ReportingDisposition reporting_disposition,
-    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-    FetchParameters::HasPreloadedResponseCandidate
-        has_preloaded_response_candidate) const {
+    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+    const {
   if (GetResourceFetcherProperties().IsDetached()) {
     if (!resource_request.GetKeepalive() || !redirect_info.has_value()) {
       return ResourceRequestBlockedReason::kOther;
@@ -202,39 +199,35 @@
       resource_request.GetRequestDestination();
   const auto request_mode = resource_request.GetMode();
 
-  if (!RuntimeEnabledFeatures::PreloadLinkRelDataUrlsEnabled() ||
-      !has_preloaded_response_candidate) {
-    scoped_refptr<const SecurityOrigin> origin =
-        resource_request.RequestorOrigin();
+  scoped_refptr<const SecurityOrigin> origin =
+      resource_request.RequestorOrigin();
 
-    // On navigation cases, Context().GetSecurityOrigin() may return nullptr, so
-    // the request's origin may be nullptr.
-    // TODO(yhirano): Figure out if it's actually fine.
-    CHECK(request_mode == network::mojom::RequestMode::kNavigate || origin);
-    if (request_mode != network::mojom::RequestMode::kNavigate &&
-        !resource_request.CanDisplay(url)) {
-      if (reporting_disposition == ReportingDisposition::kReport) {
-        console_logger_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
-            mojom::ConsoleMessageSource::kJavaScript,
-            mojom::ConsoleMessageLevel::kError,
-            "Not allowed to load local resource: " + url.GetString()));
-      }
-      RESOURCE_LOADING_DVLOG(1)
-          << "ResourceFetcher::requestResource URL was not "
-             "allowed by SecurityOrigin::CanDisplay";
-      return ResourceRequestBlockedReason::kOther;
+  // On navigation cases, Context().GetSecurityOrigin() may return nullptr, so
+  // the request's origin may be nullptr.
+  // TODO(yhirano): Figure out if it's actually fine.
+  CHECK(request_mode == network::mojom::RequestMode::kNavigate || origin);
+  if (request_mode != network::mojom::RequestMode::kNavigate &&
+      !resource_request.CanDisplay(url)) {
+    if (reporting_disposition == ReportingDisposition::kReport) {
+      console_logger_->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
+          mojom::ConsoleMessageSource::kJavaScript,
+          mojom::ConsoleMessageLevel::kError,
+          "Not allowed to load local resource: " + url.GetString()));
     }
+    RESOURCE_LOADING_DVLOG(1) << "ResourceFetcher::requestResource URL was not "
+                                 "allowed by SecurityOrigin::CanDisplay";
+    return ResourceRequestBlockedReason::kOther;
+  }
 
-    if (!url.ProtocolIsData()) {
-      // CORS is defined only for HTTP(S) requests. See
-      // https://fetch.spec.whatwg.org/#http-extensions.
-      if (request_mode == network::mojom::RequestMode::kSameOrigin &&
-          cors::CalculateCorsFlag(url, origin.get(),
-                                  resource_request.IsolatedWorldOrigin().get(),
-                                  request_mode)) {
-        PrintAccessDeniedMessage(url);
-        return ResourceRequestBlockedReason::kOrigin;
-      }
+  if (!url.ProtocolIsData()) {
+    // CORS is defined only for HTTP(S) requests. See
+    // https://fetch.spec.whatwg.org/#http-extensions.
+    if (request_mode == network::mojom::RequestMode::kSameOrigin &&
+        cors::CalculateCorsFlag(url, origin.get(),
+                                resource_request.IsolatedWorldOrigin().get(),
+                                request_mode)) {
+      PrintAccessDeniedMessage(url);
+      return ResourceRequestBlockedReason::kOrigin;
     }
   }
 
@@ -247,25 +240,21 @@
     return ResourceRequestBlockedReason::kOther;
   }
 
-  if (!has_preloaded_response_candidate ||
-      !RuntimeEnabledFeatures::BypassCSPForPreloadsEnabled() ||
-      !RuntimeEnabledFeatures::PreloadLinkRelDataUrlsEnabled()) {
-    const KURL& url_before_redirects =
-        redirect_info.has_value() ? redirect_info->original_url : url;
-    const ResourceRequestHead::RedirectStatus redirect_status =
-        redirect_info.has_value()
-            ? ResourceRequestHead::RedirectStatus::kFollowedRedirect
-            : ResourceRequestHead::RedirectStatus::kNoRedirect;
-    // We check the 'report-only' headers before upgrading the request (in
-    // populateResourceRequest). We check the enforced headers here to ensure
-    // we block things we ought to block.
-    if (CheckCSPForRequestInternal(
-            request_context, request_destination, request_mode, url, options,
-            reporting_disposition, url_before_redirects, redirect_status,
-            ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
-        ResourceRequestBlockedReason::kCSP) {
-      return ResourceRequestBlockedReason::kCSP;
-    }
+  const KURL& url_before_redirects =
+      redirect_info.has_value() ? redirect_info->original_url : url;
+  const ResourceRequestHead::RedirectStatus redirect_status =
+      redirect_info.has_value()
+          ? ResourceRequestHead::RedirectStatus::kFollowedRedirect
+          : ResourceRequestHead::RedirectStatus::kNoRedirect;
+  // We check the 'report-only' headers before upgrading the request (in
+  // populateResourceRequest). We check the enforced headers here to ensure
+  // we block things we ought to block.
+  if (CheckCSPForRequestInternal(
+          request_context, request_destination, request_mode, url, options,
+          reporting_disposition, url_before_redirects, redirect_status,
+          ContentSecurityPolicy::CheckHeaderType::kCheckEnforce) ==
+      ResourceRequestBlockedReason::kCSP) {
+    return ResourceRequestBlockedReason::kCSP;
   }
 
   if (type == ResourceType::kScript) {
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context.h b/third_party/blink/renderer/core/loader/base_fetch_context.h
index d9f1fa7..b928c9b 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/base_fetch_context.h
@@ -41,9 +41,7 @@
       const KURL&,
       const ResourceLoaderOptions&,
       ReportingDisposition,
-      base::optional_ref<const ResourceRequest::RedirectInfo>,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) const override;
+      base::optional_ref<const ResourceRequest::RedirectInfo>) const override;
   std::optional<ResourceRequestBlockedReason>
   CanRequestBasedOnSubresourceFilterOnly(
       ResourceType,
@@ -149,9 +147,8 @@
       const KURL&,
       const ResourceLoaderOptions&,
       ReportingDisposition,
-      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) const;
+      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+      const;
 
   std::optional<ResourceRequestBlockedReason> CheckCSPForRequestInternal(
       mojom::blink::RequestContextType,
diff --git a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
index 6612d45..482abe0f2 100644
--- a/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/base_fetch_context_test.cc
@@ -125,14 +125,11 @@
   Member<const FetchClientSettingsObjectImpl> fetch_client_settings_object_;
 };
 
-class BaseFetchContextTest
-    : public testing::Test,
-      public testing::WithParamInterface<std::tuple<bool, bool, bool>> {
+class BaseFetchContextTest : public testing::Test,
+                             public testing::WithParamInterface<bool> {
  protected:
   BaseFetchContextTest()
-      : has_preloaded_response_candidate_(std::get<0>(GetParam())),
-        preload_link_rel_data_urls_(PreloadLinkRelDataUrlsForTestEnabled()),
-        bypass_csp_for_preloads_(BypassCSPForPreloadsEnabled()) {}
+      : preload_link_rel_data_urls_(PreloadLinkRelDataUrlsForTestEnabled()) {}
   ~BaseFetchContextTest() override {
     execution_context_->NotifyContextDestroyed();
   }
@@ -164,29 +161,21 @@
     return GetFetchClientSettingsObject().GetSecurityOrigin();
   }
 
-  bool PreloadLinkRelDataUrlsForTestEnabled() {
-    return std::get<1>(GetParam());
-  }
-  bool BypassCSPForPreloadsEnabled() { return std::get<2>(GetParam()); }
+  bool PreloadLinkRelDataUrlsForTestEnabled() { return GetParam(); }
 
   test::TaskEnvironment task_environment_;
   Persistent<ExecutionContext> execution_context_;
   Persistent<MockBaseFetchContext> fetch_context_;
   Persistent<ResourceFetcher> resource_fetcher_;
   Persistent<TestResourceFetcherProperties> resource_fetcher_properties_;
-  FetchParameters::HasPreloadedResponseCandidate
-      has_preloaded_response_candidate_;
 
  private:
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(BaseFetchContextTest,
                          BaseFetchContextTest,
-                         testing::Combine(testing::Bool(),
-                                          testing::Bool(),
-                                          testing::Bool()));
+                         testing::Bool());
 
 // Tests that CanRequest() checks the enforced CSP headers.
 // We use non-script resource types to make sure we are actually getting CSP
@@ -213,22 +202,11 @@
 
   ResourceLoaderOptions options(nullptr /* world */);
 
-  if (PreloadLinkRelDataUrlsForTestEnabled() && BypassCSPForPreloadsEnabled() &&
-      has_preloaded_response_candidate_) {
-    EXPECT_EQ(std::nullopt,
-              fetch_context_->CanRequest(
-                  ResourceType::kImage, resource_request, url, options,
-                  ReportingDisposition::kReport, std::nullopt,
-                  has_preloaded_response_candidate_));
-    EXPECT_EQ(0u, policy->violation_reports_sent_.size());
-  } else {
-    EXPECT_EQ(ResourceRequestBlockedReason::kCSP,
-              fetch_context_->CanRequest(
-                  ResourceType::kImage, resource_request, url, options,
-                  ReportingDisposition::kReport, std::nullopt,
-                  has_preloaded_response_candidate_));
-    EXPECT_EQ(1u, policy->violation_reports_sent_.size());
-  }
+  EXPECT_EQ(ResourceRequestBlockedReason::kCSP,
+            fetch_context_->CanRequest(
+                ResourceType::kImage, resource_request, url, options,
+                ReportingDisposition::kReport, std::nullopt));
+  EXPECT_EQ(1u, policy->violation_reports_sent_.size());
 }
 
 // Tests that CheckCSPForRequest() checks the report-only CSP headers.
@@ -269,17 +247,17 @@
   keepalive_request.SetRequestorOrigin(GetSecurityOrigin());
   keepalive_request.SetKeepalive(true);
 
-  EXPECT_EQ(std::nullopt, fetch_context_->CanRequest(
-                              ResourceType::kRaw, request, url,
-                              ResourceLoaderOptions(nullptr /* world */),
-                              ReportingDisposition::kSuppressReporting,
-                              std::nullopt, has_preloaded_response_candidate_));
+  EXPECT_EQ(std::nullopt,
+            fetch_context_->CanRequest(
+                ResourceType::kRaw, request, url,
+                ResourceLoaderOptions(nullptr /* world */),
+                ReportingDisposition::kSuppressReporting, std::nullopt));
 
-  EXPECT_EQ(std::nullopt, fetch_context_->CanRequest(
-                              ResourceType::kRaw, keepalive_request, url,
-                              ResourceLoaderOptions(nullptr /* world */),
-                              ReportingDisposition::kSuppressReporting,
-                              std::nullopt, has_preloaded_response_candidate_));
+  EXPECT_EQ(std::nullopt,
+            fetch_context_->CanRequest(
+                ResourceType::kRaw, keepalive_request, url,
+                ResourceLoaderOptions(nullptr /* world */),
+                ReportingDisposition::kSuppressReporting, std::nullopt));
 
   ResourceRequest::RedirectInfo redirect_info(
       KURL(NullURL(), "http://www.redirecting.com/"),
@@ -288,15 +266,13 @@
             fetch_context_->CanRequest(
                 ResourceType::kRaw, request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, redirect_info));
 
   EXPECT_EQ(std::nullopt,
             fetch_context_->CanRequest(
                 ResourceType::kRaw, keepalive_request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, redirect_info));
 
   resource_fetcher_->ClearContext();
 
@@ -304,29 +280,25 @@
             fetch_context_->CanRequest(
                 ResourceType::kRaw, request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, std::nullopt,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, std::nullopt));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 ResourceType::kRaw, keepalive_request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, std::nullopt,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, std::nullopt));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 ResourceType::kRaw, request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, redirect_info));
 
   EXPECT_EQ(std::nullopt,
             fetch_context_->CanRequest(
                 ResourceType::kRaw, keepalive_request, url,
                 ResourceLoaderOptions(nullptr /* world */),
-                ReportingDisposition::kSuppressReporting, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kSuppressReporting, redirect_info));
 }
 
 // Test that User Agent CSS can only load images with data urls.
@@ -345,20 +317,17 @@
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 ResourceType::kScript, resource_request, test_url, options,
-                ReportingDisposition::kReport, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kReport, redirect_info));
 
   EXPECT_EQ(ResourceRequestBlockedReason::kOther,
             fetch_context_->CanRequest(
                 ResourceType::kImage, resource_request, test_url, options,
-                ReportingDisposition::kReport, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kReport, redirect_info));
 
   EXPECT_EQ(std::nullopt,
             fetch_context_->CanRequest(
                 ResourceType::kImage, resource_request, data_url, options,
-                ReportingDisposition::kReport, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kReport, redirect_info));
 }
 
 // Test that User Agent CSS can bypass CSP to load embedded images.
@@ -383,8 +352,7 @@
   EXPECT_EQ(std::nullopt,
             fetch_context_->CanRequest(
                 ResourceType::kImage, resource_request, data_url, options,
-                ReportingDisposition::kReport, redirect_info,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kReport, redirect_info));
 }
 
 // Tests that CanRequest() checks for data: URL in SVGUseElement.
@@ -406,15 +374,14 @@
   EXPECT_EQ(ResourceRequestBlockedReason::kOrigin,
             fetch_context_->CanRequest(
                 ResourceType::kImage, resource_request, url, options,
-                ReportingDisposition::kReport, std::nullopt,
-                has_preloaded_response_candidate_));
+                ReportingDisposition::kReport, std::nullopt));
 
   scoped_command_line.GetProcessCommandLine()->AppendSwitch(
       blink::switches::kDataUrlInSvgUseEnabled);
-  EXPECT_EQ(std::nullopt, fetch_context_->CanRequest(
-                              ResourceType::kImage, resource_request, url,
-                              options, ReportingDisposition::kReport,
-                              std::nullopt, has_preloaded_response_candidate_));
+  EXPECT_EQ(std::nullopt,
+            fetch_context_->CanRequest(
+                ResourceType::kImage, resource_request, url, options,
+                ReportingDisposition::kReport, std::nullopt));
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.cc b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
index 6ebd09d..a8667be 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -836,9 +836,7 @@
 
 void FrameFetchContext::PopulateResourceRequestBeforeCacheAccess(
     const ResourceLoaderOptions& options,
-    ResourceRequest& request,
-    FetchParameters::HasPreloadedResponseCandidate
-        has_preloaded_response_candidate) {
+    ResourceRequest& request) {
   if (!GetResourceFetcherProperties().IsDetached()) {
     probe::SetDevToolsIds(Probe(), request, options.initiator_info);
   }
@@ -1313,9 +1311,8 @@
     const KURL& url,
     const ResourceLoaderOptions& options,
     ReportingDisposition reporting_disposition,
-    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-    FetchParameters::HasPreloadedResponseCandidate
-        has_preloaded_response_candidate) const {
+    base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+    const {
   const bool detached = GetResourceFetcherProperties().IsDetached();
   if (!detached && document_->IsFreezingInProgress() &&
       !resource_request.GetKeepalive()) {
@@ -1329,8 +1326,7 @@
   }
   std::optional<ResourceRequestBlockedReason> blocked_reason =
       BaseFetchContext::CanRequest(type, resource_request, url, options,
-                                   reporting_disposition, redirect_info,
-                                   has_preloaded_response_candidate);
+                                   reporting_disposition, redirect_info);
   if (blocked_reason) {
     return blocked_reason;
   }
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context.h b/third_party/blink/renderer/core/loader/frame_fetch_context.h
index 20611f4..6baa7f4b 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -81,9 +81,8 @@
       const KURL& url,
       const ResourceLoaderOptions& options,
       ReportingDisposition reporting_disposition,
-      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) const override;
+      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+      const override;
   mojom::FetchCacheMode ResourceRequestCachePolicy(
       const ResourceRequest&,
       ResourceType,
@@ -101,9 +100,7 @@
 
   void PopulateResourceRequestBeforeCacheAccess(
       const ResourceLoaderOptions& options,
-      ResourceRequest& request,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) override;
+      ResourceRequest& request) override;
 
   void WillSendRequest(ResourceRequest& resource_request) override;
 
diff --git a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
index 7d3d318..230f50d 100644
--- a/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
+++ b/third_party/blink/renderer/core/loader/frame_fetch_context_test.cc
@@ -232,32 +232,28 @@
   Persistent<DummyFrameOwner> owner;
 };
 
-class FrameFetchContextTest
-    : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool>> {
+class FrameFetchContextTest : public FrameFetchContextTestBase,
+                              public testing::WithParamInterface<bool> {
  protected:
   FrameFetchContextTest()
-      : preload_link_rel_data_urls_(PreloadLinkRelDataUrlsEnabled()),
-        bypass_csp_for_preloads_(std::get<1>(GetParam())) {}
+      : preload_link_rel_data_urls_(PreloadLinkRelDataUrlsEnabled()) {}
 
-  bool PreloadLinkRelDataUrlsEnabled() { return std::get<0>(GetParam()); }
+  bool PreloadLinkRelDataUrlsEnabled() { return GetParam(); }
 
  private:
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(FrameFetchContextTest,
                          FrameFetchContextTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Bool());
 
 class FrameFetchContextSubresourceFilterTest
     : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool>> {
+      public testing::WithParamInterface<bool> {
  protected:
   FrameFetchContextSubresourceFilterTest()
-      : preload_link_rel_data_urls_(std::get<0>(GetParam())),
-        bypass_csp_for_preloads_(std::get<1>(GetParam())) {}
+      : preload_link_rel_data_urls_(GetParam()) {}
 
   void SetUp() override {
     FrameFetchContextTestBase::SetUp();
@@ -302,7 +298,6 @@
 
  private:
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 
   std::optional<ResourceRequestBlockedReason> CanRequestInternal(
       ReportingDisposition reporting_disposition,
@@ -316,10 +311,9 @@
                                             .GetSecurityOrigin());
     ResourceLoaderOptions options(nullptr /* world */);
     // DJKim
-    return GetFetchContext()->CanRequest(
-        ResourceType::kImage, resource_request, input_url, options,
-        reporting_disposition, std::nullopt,
-        FetchParameters::HasPreloadedResponseCandidate(false));
+    return GetFetchContext()->CanRequest(ResourceType::kImage, resource_request,
+                                         input_url, options,
+                                         reporting_disposition, std::nullopt);
   }
 
   int filtered_load_callback_counter_;
@@ -327,16 +321,15 @@
 
 INSTANTIATE_TEST_SUITE_P(FrameFetchContextSubresourceFilterTest,
                          FrameFetchContextSubresourceFilterTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Bool());
 
 // This test class sets up a mock frame loader client.
 class FrameFetchContextMockedLocalFrameClientTest
     : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool>> {
+      public testing::WithParamInterface<bool> {
  protected:
   FrameFetchContextMockedLocalFrameClientTest()
-      : preload_link_rel_data_urls_(std::get<0>(GetParam())),
-        bypass_csp_for_preloads_(std::get<1>(GetParam())) {}
+      : preload_link_rel_data_urls_(GetParam()) {}
 
   void SetUp() override {
     url = KURL("https://example.test/foo");
@@ -362,21 +355,19 @@
 
  private:
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(FrameFetchContextMockedLocalFrameClientTest,
                          FrameFetchContextMockedLocalFrameClientTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Bool());
 
 class FrameFetchContextModifyRequestTest
     : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool>> {
+      public testing::WithParamInterface<bool> {
  public:
   FrameFetchContextModifyRequestTest()
       : example_origin(SecurityOrigin::Create(KURL("https://example.test/"))),
-        preload_link_rel_data_urls_(std::get<0>(GetParam())),
-        bypass_csp_for_preloads_(std::get<1>(GetParam())) {}
+        preload_link_rel_data_urls_(GetParam()) {}
 
  protected:
   void ModifyRequestForMixedContentUpgrade(
@@ -477,12 +468,11 @@
 
  private:
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(FrameFetchContextModifyRequestTest,
                          FrameFetchContextModifyRequestTest,
-                         testing::Combine(testing::Bool(), testing::Bool()));
+                         testing::Bool());
 
 TEST_P(FrameFetchContextModifyRequestTest, UpgradeInsecureResourceRequests) {
   struct TestCase {
@@ -655,11 +645,10 @@
 
 class FrameFetchContextHintsTest
     : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool, bool>> {
+      public testing::WithParamInterface<std::tuple<bool, bool>> {
  public:
   FrameFetchContextHintsTest()
-      : preload_link_rel_data_urls_(std::get<1>(GetParam())),
-        bypass_csp_for_preloads_(std::get<2>(GetParam())) {
+      : preload_link_rel_data_urls_(std::get<1>(GetParam())) {
     std::vector<base::test::FeatureRef> enabled_features = {};
     std::vector<base::test::FeatureRef> disabled_features = {};
     if (std::get<0>(GetParam())) {
@@ -726,13 +715,11 @@
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(All,
                          FrameFetchContextHintsTest,
                          testing::Combine(testing::ValuesIn({false, true}),
-                                          testing::Bool(),
                                           testing::Bool()));
 // Verify that the client hints should be attached for subresources fetched
 // over secure transport. Tests when the persistent client hint feature is
@@ -1682,39 +1669,28 @@
 }
 
 TEST_P(FrameFetchContextTest, SetTopFrameOriginBeforeCacheAccess) {
-  const bool has_preloaded_response_candidate[] = {true, false};
-  for (const auto test_case : has_preloaded_response_candidate) {
-    if (!PreloadLinkRelDataUrlsEnabled() && test_case) {
-      // `has_preloaded_response_candidate` is not set to "true" if the
-      // PreloadLinkRelDataUrls feature is disabled, so skip this case.
-      continue;
-    }
+  const KURL document_url("https://www2.example.com/foo/bar");
+  RecreateFetchContext(document_url);
+  const SecurityOrigin* origin = document->domWindow()->GetSecurityOrigin();
 
-    const KURL document_url("https://www2.example.com/foo/bar");
-    RecreateFetchContext(document_url);
-    const SecurityOrigin* origin = document->domWindow()->GetSecurityOrigin();
+  const KURL url("https://www.example.com/hoge/fuga");
+  ResourceRequest request(url);
+  request.SetRequestorOrigin(origin);
 
-    const KURL url("https://www.example.com/hoge/fuga");
-    ResourceRequest request(url);
-    request.SetRequestorOrigin(origin);
+  TestResourceRequestContext request_context;
+  FetchParameters fetch_parameters =
+      FetchParameters::CreateForTest(std::move(request));
 
-    TestResourceRequestContext request_context;
-    FetchParameters fetch_parameters =
-        FetchParameters::CreateForTest(std::move(request));
-
-    fetch_parameters.SetIsPreloadedResponseCandidatePresent(test_case);
-
-    std::optional<ResourceRequestBlockedReason> block_reason =
-        PrepareResourceRequestForCacheAccess(
-            ResourceType::kImage,
-            GetFetchContext()
-                ->GetResourceFetcherProperties()
-                .GetFetchClientSettingsObject(),
-            /*bundle_url_for_uuid_resources=*/KURL(), request_context,
-            *GetFetchContext(), fetch_parameters);
-    EXPECT_EQ(std::nullopt, block_reason);
-    EXPECT_EQ(origin, fetch_parameters.GetResourceRequest().TopFrameOrigin());
-  }
+  std::optional<ResourceRequestBlockedReason> block_reason =
+      PrepareResourceRequestForCacheAccess(
+          ResourceType::kImage,
+          GetFetchContext()
+              ->GetResourceFetcherProperties()
+              .GetFetchClientSettingsObject(),
+          /*bundle_url_for_uuid_resources=*/KURL(), request_context,
+          *GetFetchContext(), fetch_parameters);
+  EXPECT_EQ(std::nullopt, block_reason);
+  EXPECT_EQ(origin, fetch_parameters.GetResourceRequest().TopFrameOrigin());
 }
 
 // Tests that CanRequestCanRequestBasedOnSubresourceFilterOnly will block ads
@@ -1780,11 +1756,10 @@
 
 class FrameFetchContextDisableReduceAcceptLanguageTest
     : public FrameFetchContextTestBase,
-      public testing::WithParamInterface<std::tuple<bool, bool, bool>> {
+      public testing::WithParamInterface<std::tuple<bool, bool>> {
  public:
   FrameFetchContextDisableReduceAcceptLanguageTest()
-      : preload_link_rel_data_urls_(std::get<1>(GetParam())),
-        bypass_csp_for_preloads_(std::get<2>(GetParam())) {
+      : preload_link_rel_data_urls_(std::get<1>(GetParam())) {
     scoped_feature_list_.InitWithFeatures(
         /*enabled_features=*/{},
         /*disabled_features=*/{network::features::kReduceAcceptLanguage});
@@ -1808,13 +1783,11 @@
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
   ScopedPreloadLinkRelDataUrlsForTest preload_link_rel_data_urls_;
-  ScopedBypassCSPForPreloadsForTest bypass_csp_for_preloads_;
 };
 
 INSTANTIATE_TEST_SUITE_P(FrameFetchContextDisableReduceAcceptLanguageTest,
                          FrameFetchContextDisableReduceAcceptLanguageTest,
                          testing::Combine(testing::Bool(),
-                                          testing::Bool(),
                                           testing::Bool()));
 
 TEST_P(FrameFetchContextDisableReduceAcceptLanguageTest,
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.cc b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
index b1112b6..35a6517 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.cc
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.cc
@@ -247,9 +247,7 @@
 
 void WorkerFetchContext::PopulateResourceRequestBeforeCacheAccess(
     const ResourceLoaderOptions& options,
-    ResourceRequest& request,
-    FetchParameters::HasPreloadedResponseCandidate
-        has_preloaded_response_candidate) {
+    ResourceRequest& request) {
   ModifyRequestForMixedContentUpgrade(request);
   request.SetTopFrameOrigin(GetTopFrameOrigin());
 }
diff --git a/third_party/blink/renderer/core/loader/worker_fetch_context.h b/third_party/blink/renderer/core/loader/worker_fetch_context.h
index 1d9f680a..3aaadbb 100644
--- a/third_party/blink/renderer/core/loader/worker_fetch_context.h
+++ b/third_party/blink/renderer/core/loader/worker_fetch_context.h
@@ -85,9 +85,7 @@
   void ModifyRequestForMixedContentUpgrade(ResourceRequest&) override;
   void PopulateResourceRequestBeforeCacheAccess(
       const ResourceLoaderOptions& options,
-      ResourceRequest& request,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) override;
+      ResourceRequest& request) override;
   void WillSendRequest(ResourceRequest& request) override;
   void UpgradeResourceRequestForLoader(
       ResourceType,
diff --git a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
index d854764..485973e 100644
--- a/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
+++ b/third_party/blink/renderer/core/speculation_rules/document_speculation_rules.cc
@@ -645,7 +645,7 @@
   }
 
   HeapVector<Member<SpeculationCandidate>> candidates;
-  auto push_candidates = [&candidates, &document](
+  auto push_candidates = [&candidates, &document, this](
                              mojom::blink::SpeculationAction action,
                              SpeculationRuleSet* rule_set,
                              const HeapVector<Member<SpeculationRule>>& rules) {
@@ -675,6 +675,10 @@
           // Put the default value.
           if (tags.empty()) {
             tags.push_back(g_null_atom);
+          } else {
+            // Record that the valid tag is specified by the page.
+            UseCounter::Count(GetSupplementable(),
+                              WebFeature::kSpeculationRulesTags);
           }
         }
 
diff --git a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
index c109a46e..43f14cd 100644
--- a/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
+++ b/third_party/blink/renderer/core/speculation_rules/speculation_rule_set_test.cc
@@ -997,9 +997,13 @@
   }
 }
 
-// Tests that prefetch rules are ignored unless SpeculationRulesPrefetchProxy
-// is enabled.
-TEST_F(SpeculationRuleSetTest, PrerenderIgnorePrefetchRules) {
+// Tests that prefetch_with_subresources rules are ignored unless
+// SpeculationRulesPrefetchWithSubresources is enabled.
+TEST_F(SpeculationRuleSetTest, PrerenderIgnorePrefetchWithSubresourcesRules) {
+  // Overwrite the feature flag.
+  ScopedSpeculationRulesPrefetchWithSubresourcesForTest
+      enable_prefetch_with_subresources{false};
+
   DummyPageHolder page_holder;
   StubSpeculationHost speculation_host;
   const String speculation_script =
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 9177c89c..c95cd60 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.cc
@@ -173,9 +173,9 @@
 
   // If there is a current texture, create a snapshot from it.
   if (texture_ && !texture_->IsDestroyed()) {
-    return SnapshotInternal(texture_->GetHandle(), swap_buffers_->Size());
+    return SnapshotInternal(texture_->GetHandle());
   } else if (swap_texture_) {
-    return SnapshotInternal(swap_texture_->GetHandle(), swap_buffers_->Size());
+    return SnapshotInternal(swap_texture_->GetHandle());
   }
 
   // If there is no current texture, return a snapshot of the front buffer if
@@ -185,10 +185,7 @@
     return nullptr;
   }
 
-  return SnapshotInternal(
-      front_buffer_texture->GetTexture(),
-      gfx::Size(front_buffer_texture->GetTexture().GetWidth(),
-                front_buffer_texture->GetTexture().GetHeight()));
+  return SnapshotInternal(front_buffer_texture->GetTexture());
 }
 
 bool GPUCanvasContext::PaintRenderingResultsToCanvas(
@@ -244,9 +241,7 @@
     return false;
   }
 
-  return CopyTextureToResourceProvider(
-      texture, gfx::Size(texture.GetWidth(), texture.GetHeight()),
-      resource_provider);
+  return CopyTextureToResourceProvider(texture, resource_provider);
 }
 
 bool GPUCanvasContext::CopyRenderingResultsToVideoFrame(
@@ -825,9 +820,10 @@
 
 bool GPUCanvasContext::CopyTextureToResourceProvider(
     const wgpu::Texture& texture,
-    const gfx::Size& size,
     CanvasResourceProvider* resource_provider) const {
   DCHECK(resource_provider);
+
+  gfx::Size size(texture.GetWidth(), texture.GetHeight());
   DCHECK_EQ(resource_provider->Size(), size);
 
   // This method will copy the contents of `texture` to `resource_provider`'s
@@ -952,8 +948,9 @@
 }
 
 scoped_refptr<StaticBitmapImage> GPUCanvasContext::SnapshotInternal(
-    const wgpu::Texture& texture,
-    const gfx::Size& size) const {
+    const wgpu::Texture& texture) const {
+  gfx::Size size(texture.GetWidth(), texture.GetHeight());
+
   // We tag the SharedImage inside the WebGPUImageProvider with display usages
   // since there are uncommon paths which may use this snapshot for compositing.
   // These paths are usually related to either printing or either video and
@@ -965,8 +962,9 @@
   if (!resource_provider)
     return nullptr;
 
-  if (!CopyTextureToResourceProvider(texture, size, resource_provider.get()))
+  if (!CopyTextureToResourceProvider(texture, resource_provider.get())) {
     return nullptr;
+  }
 
   return resource_provider->Snapshot(FlushReason::kNone);
 }
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 37cae74..8fe2224 100644
--- a/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
+++ b/third_party/blink/renderer/modules/webgpu/gpu_canvas_context.h
@@ -121,12 +121,10 @@
   void FinalizeFrame(FlushReason) override;
 
   scoped_refptr<StaticBitmapImage> SnapshotInternal(
-      const wgpu::Texture& texture,
-      const gfx::Size& size) const;
+      const wgpu::Texture& texture) const;
 
   bool CopyTextureToResourceProvider(
       const wgpu::Texture& texture,
-      const gfx::Size& size,
       CanvasResourceProvider* resource_provider) const;
 
   void CopyToSwapTexture();
diff --git a/third_party/blink/renderer/platform/exported/url_conversion.cc b/third_party/blink/renderer/platform/exported/url_conversion.cc
index 6df79e19..b5344961 100644
--- a/third_party/blink/renderer/platform/exported/url_conversion.cc
+++ b/third_party/blink/renderer/platform/exported/url_conversion.cc
@@ -25,7 +25,7 @@
   }
 
   // GURL can consume UTF-16 directly.
-  return GURL(std::u16string_view(str.Characters16(), str.length()));
+  return GURL(str.View16());
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
index 49195248..d9d02f1 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider.cc
@@ -246,35 +246,6 @@
 
   return current_swap_buffer_->mailbox_texture;
 }
-scoped_refptr<WebGPUMailboxTexture>
-WebGPUSwapBufferProvider::GetLastWebGPUMailboxTexture() const {
-  // It's possible this is called after the canvas context current texture has
-  // been destroyed, but `current_swap_buffer_` is still available e.g. when the
-  // context is used offscreen only.
-  auto latest_swap_buffer =
-      current_swap_buffer_ ? current_swap_buffer_ : last_swap_buffer_;
-  auto context_provider = GetContextProviderWeakPtr();
-  if (!latest_swap_buffer || !context_provider) {
-    return nullptr;
-  }
-
-  wgpu::DawnTextureInternalUsageDescriptor internal_usage;
-  internal_usage.internalUsage = internal_usage_;
-  wgpu::TextureDescriptor desc = {
-      .nextInChain = &internal_usage,
-      .usage = usage_,
-      .size = {static_cast<uint32_t>(
-                   latest_swap_buffer->GetSharedImage()->size().width()),
-               static_cast<uint32_t>(
-                   latest_swap_buffer->GetSharedImage()->size().height())},
-      .format = format_,
-  };
-
-  return WebGPUMailboxTexture::FromExistingSharedImage(
-      dawn_control_client_, device_, desc, latest_swap_buffer->GetSharedImage(),
-      latest_swap_buffer->GetSyncToken(), gpu::webgpu::WEBGPU_MAILBOX_NONE);
-}
-
 base::WeakPtr<WebGraphicsContext3DProviderWrapper>
 WebGPUSwapBufferProvider::GetContextProviderWeakPtr() const {
   return dawn_control_client_->GetContextProviderWeakPtr();
@@ -390,11 +361,7 @@
   if (lost_resource)
     return;
 
-  if (last_swap_buffer_) {
-    swap_buffer_pool_->ReleaseImage(std::move(last_swap_buffer_));
-  }
-
-  last_swap_buffer_ = std::move(swap_buffer);
+  swap_buffer_pool_->ReleaseImage(std::move(swap_buffer));
 }
 
 WebGPUSwapBufferProvider::SwapBuffer::SwapBuffer(
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 f996605..f01f95c8 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
@@ -98,8 +98,6 @@
       const gfx::ColorSpace& dst_color_space,
       WebGraphicsContext3DVideoFramePool::FrameReadyCallback callback);
 
-  scoped_refptr<WebGPUMailboxTexture> GetLastWebGPUMailboxTexture() const;
-
   base::WeakPtr<WebGraphicsContext3DProviderWrapper> GetContextProviderWeakPtr()
       const;
 
@@ -176,7 +174,6 @@
   // Pool of SwapBuffers which manages creation, release and recycling of
   // SwapBuffer resources.
   std::unique_ptr<gpu::SharedImagePool<SwapBuffer>> swap_buffer_pool_;
-  scoped_refptr<SwapBuffer> last_swap_buffer_;
   scoped_refptr<SwapBuffer> current_swap_buffer_;
 
   scoped_refptr<gpu::ClientSharedImage> front_buffer_shared_image_;
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
index e06f987..70e2e54 100644
--- a/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgpu_swap_buffer_provider_test.cc
@@ -733,18 +733,19 @@
   EXPECT_EQ(nullptr, provider_->GetNewTexture(kZeroHeight));
 }
 
-// Verifies that GetLastWebGPUMailboxTexture() returns empty information if no
+// Verifies that GetFrontBufferSharedImage() returns empty information if no
 // swapbuffer has been created.
 TEST_F(WebGPUSwapBufferProviderTest,
-       GetLastWebGPUMailboxTextureReturnsEmptyWithoutSwapBuffer) {
-  auto mailbox_texture = provider_->GetLastWebGPUMailboxTexture();
-  EXPECT_EQ(mailbox_texture, nullptr);
+       GetFrontBufferSharedImageReturnsEmptyWithoutSwapBuffer) {
+  auto front_buffer_si = provider_->GetFrontBufferSharedImage();
+  EXPECT_EQ(front_buffer_si, nullptr);
 }
 
-// Verifies that GetLastWebGPUMailboxTexture() returns a correctly-configured
-// texture if a swapbuffer has been created.
+// Verifies that GetFrontBufferSharedImage() returns a correctly-configured
+// SharedImage if the contents of the swapbuffer have been sent to the
+// compositor.
 TEST_F(WebGPUSwapBufferProviderTest,
-       GetLastWebGPUMailboxTextureReturnsValidTextureWithSwapBuffer) {
+       GetFrontBufferSharedImageReturnsValidSharedImageAfterSwap) {
   const gfx::Size kSize(10, 20);
 
   EXPECT_CALL(*webgpu_, ReserveTexture(device_.Get(), _))
@@ -754,18 +755,15 @@
           }));
   provider_->GetNewTexture(kSize);
 
-  auto mailbox_texture = provider_->GetLastWebGPUMailboxTexture();
-  EXPECT_NE(mailbox_texture, nullptr);
+  viz::TransferableResource resource;
+  viz::ReleaseCallback release_callback;
+  EXPECT_TRUE(
+      provider_->PrepareTransferableResource(&resource, &release_callback));
 
-  auto texture = mailbox_texture->GetTexture();
-  EXPECT_EQ(texture.GetUsage(), kUsage);
-  EXPECT_EQ(texture.GetFormat(), kFormat);
-  EXPECT_EQ(texture.GetDepthOrArrayLayers(), 1u);
-  EXPECT_EQ(texture.GetDimension(), wgpu::TextureDimension::e2D);
-  EXPECT_EQ(texture.GetMipLevelCount(), 1u);
-  EXPECT_EQ(texture.GetSampleCount(), 1u);
-  EXPECT_EQ(texture.GetHeight(), static_cast<uint32_t>(kSize.height()));
-  EXPECT_EQ(texture.GetWidth(), static_cast<uint32_t>(kSize.width()));
+  auto front_buffer_si = provider_->GetFrontBufferSharedImage();
+  EXPECT_NE(front_buffer_si, nullptr);
+  EXPECT_EQ(front_buffer_si->size(), kSize);
+  EXPECT_EQ(front_buffer_si->format(), resource.format);
 }
 
 // Verifies that GetNewTexture() passes client-specified internal usages to
@@ -791,28 +789,4 @@
             kInternalUsage | wgpu::TextureUsage::RenderAttachment);
 }
 
-// Verifies that GetLastMailboxTexture() passes client-specified internal usages
-// to AssociateMailbox() and doesn't additionally add RenderAttachment (since
-// it does not instruct the decoder to do lazy clearing on this texture).
-TEST_F(WebGPUSwapBufferProviderTest,
-       GetLastMailboxTexturePassesClientSpecifiedInternalUsage) {
-  ASSERT_EQ(kInternalUsage & wgpu::TextureUsage::RenderAttachment, 0);
-
-  const gfx::Size kSize(10, 20);
-
-  EXPECT_EQ(webgpu_->internal_usage_from_most_recent_associate_mailbox_call,
-            wgpu::TextureUsage::None);
-
-  EXPECT_CALL(*webgpu_, ReserveTexture(device_.Get(), _))
-      .WillRepeatedly(Invoke(
-          [&](WGPUDevice device, const WGPUTextureDescriptor* desc) -> auto {
-            return ReserveTextureImpl(device, desc);
-          }));
-  provider_->GetNewTexture(kSize);
-
-  provider_->GetLastWebGPUMailboxTexture();
-  EXPECT_EQ(webgpu_->internal_usage_from_most_recent_associate_mailbox_call,
-            kInternalUsage);
-}
-
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/language_detection/language_detection_model.cc b/third_party/blink/renderer/platform/language_detection/language_detection_model.cc
index 4cca000..d1fc038 100644
--- a/third_party/blink/renderer/platform/language_detection/language_detection_model.cc
+++ b/third_party/blink/renderer/platform/language_detection/language_detection_model.cc
@@ -61,8 +61,8 @@
     DetectLanguageCallback on_complete) {
   WTF::String text_16 = text;
   text_16.Ensure16Bit();
-  auto score_by_language = language_detection_model_.PredictWithScan(
-      std::u16string_view(text_16.Characters16(), text_16.length()));
+  auto score_by_language =
+      language_detection_model_.PredictWithScan(text_16.View16());
 
   WTF::Vector<LanguagePrediction> predictions;
   predictions.reserve(static_cast<wtf_size_t>(score_by_language.size()));
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
index 0c318a26..6eefd1cd 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_context.h
@@ -117,9 +117,8 @@
       const KURL&,
       const ResourceLoaderOptions&,
       ReportingDisposition,
-      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) const {
+      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+      const {
     return ResourceRequestBlockedReason::kOther;
   }
   // In derived classes, performs *only* a SubresourceFilter check for whether
@@ -171,9 +170,7 @@
   // called.
   virtual void PopulateResourceRequestBeforeCacheAccess(
       const ResourceLoaderOptions& options,
-      ResourceRequest& request,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) {}
+      ResourceRequest& request) {}
 
   // Called after csp checks to potentially override the URL of the request.
   virtual void WillSendRequest(ResourceRequest& request) {}
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
index 19d1776..8312946 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.h
@@ -69,9 +69,6 @@
                        // ResourceFetcher::non_blocking_loaders_.
   };
 
-  using HasPreloadedResponseCandidate =
-      base::StrongAlias<class HasPreloadedResponseCandidateTag, bool>;
-
   static FetchParameters CreateForTest(ResourceRequest);
 
   FetchParameters(ResourceRequest, ResourceLoaderOptions);
@@ -224,16 +221,6 @@
     return is_potentially_lcp_influencer_;
   }
 
-  void SetIsPreloadedResponseCandidatePresent(bool flag) {
-    is_preloaded_response_candidate_present_ =
-        FetchParameters::HasPreloadedResponseCandidate(flag);
-  }
-
-  FetchParameters::HasPreloadedResponseCandidate
-  IsPreloadedResponseCandidatePresent() const {
-    return is_preloaded_response_candidate_present_;
-  }
-
   void Trace(Visitor* visitor) const { visitor->Trace(options_); }
 
  private:
@@ -256,8 +243,6 @@
       RenderBlockingBehavior::kUnset;
   bool is_potentially_lcp_element_ = false;
   bool is_potentially_lcp_influencer_ = false;
-  HasPreloadedResponseCandidate is_preloaded_response_candidate_present_ =
-      HasPreloadedResponseCandidate(false);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
index 56e5d984..3e1f865e 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -1390,6 +1390,7 @@
   }
 
   auto preloads_list_iterator = preloads_.end();
+  bool is_preloaded_response_candidate_present = false;
   bool is_stale_revalidation = params.IsStaleRevalidation();
 
   if (RuntimeEnabledFeatures::PreloadLinkRelDataUrlsEnabled()) {
@@ -1397,8 +1398,8 @@
     if (!is_stale_revalidation && !archive_) {
       preloads_list_iterator =
           preloads_.find(PreloadKey(params.Url(), resource_type));
-      params.SetIsPreloadedResponseCandidatePresent(preloads_list_iterator !=
-                                                    preloads_.end());
+      is_preloaded_response_candidate_present =
+          preloads_list_iterator != preloads_.end();
     }
   }
 
@@ -1414,7 +1415,7 @@
 
   if (!is_stale_revalidation &&
       (archive_ || (is_data_url && defer_policy != DeferPolicy::kDefer))) {
-    if (!(is_data_url && params.IsPreloadedResponseCandidatePresent())) {
+    if (!(is_data_url && is_preloaded_response_candidate_present)) {
       prepare_helper.UpgradeForLoaderIfNecessary(pauser);
       resource = CreateResourceForStaticData(params, factory);
       if (resource) {
@@ -1436,7 +1437,7 @@
 
   if (!is_stale_revalidation && !resource) {
     if (!prepare_helper.WasUpgradeForLoaderCalled() &&
-        (params.IsPreloadedResponseCandidatePresent() ||
+        (is_preloaded_response_candidate_present ||
          (!RuntimeEnabledFeatures::PreloadLinkRelDataUrlsEnabled() &&
           preloads_.find(PreloadKey(params.Url(), resource_type)) !=
               preloads_.end()))) {
@@ -2993,8 +2994,7 @@
   Context().CanRequest(resource->GetType(), last_resource_request,
                        last_resource_request.Url(), params.Options(),
                        ReportingDisposition::kReport,
-                       last_resource_request.GetRedirectInfo(),
-                       params.IsPreloadedResponseCandidatePresent());
+                       last_resource_request.GetRedirectInfo());
   if (resource->GetStatus() == ResourceStatus::kNotStarted ||
       resource->GetStatus() == ResourceStatus::kPending) {
     // If the loading has not started, then we return here because loading
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
index d325448..4324434 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader.cc
@@ -671,10 +671,9 @@
         ResourceRequest::RedirectStatus::kFollowedRedirect);
 
     std::optional<ResourceRequestBlockedReason> blocked_reason =
-        Context().CanRequest(
-            resource_type, *new_request, new_url, options,
-            reporting_disposition, new_request->GetRedirectInfo(),
-            FetchParameters::HasPreloadedResponseCandidate(false));
+        Context().CanRequest(resource_type, *new_request, new_url, options,
+                             reporting_disposition,
+                             new_request->GetRedirectInfo());
 
     if (Context().CalculateIfAdSubresource(
             *new_request, std::nullopt /* alias_url */, resource_type,
@@ -972,10 +971,9 @@
         ResourceRequest::RedirectStatus::kFollowedRedirect);
 
     std::optional<ResourceRequestBlockedReason> blocked_reason =
-        Context().CanRequest(
-            resource_type, ResourceRequest(initial_request), response_url,
-            options, ReportingDisposition::kReport, redirect_info,
-            FetchParameters::HasPreloadedResponseCandidate(false));
+        Context().CanRequest(resource_type, ResourceRequest(initial_request),
+                             response_url, options,
+                             ReportingDisposition::kReport, redirect_info);
     if (blocked_reason) {
       HandleError(ResourceError::CancelledDueToAccessCheckError(
           response_url, blocked_reason.value()));
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc
index ce40926..fefdf5f 100644
--- a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc
@@ -220,38 +220,33 @@
   const ReportingDisposition reporting_disposition =
       CalculateReportingDisposition(params);
 
-  if (!params.IsPreloadedResponseCandidatePresent() ||
-      !RuntimeEnabledFeatures::PreloadLinkRelDataUrlsEnabled() ||
-      !RuntimeEnabledFeatures::BypassCSPForPreloadsEnabled()) {
-    // Note that resource_request.GetRedirectInfo() may be non-null here since
-    // e.g. ThreadableLoader may create a new Resource from a ResourceRequest
-    // that originates from the ResourceRequest passed to the redirect handling
-    // callback.
+  // Note that resource_request.GetRedirectInfo() may be non-null here since
+  // e.g. ThreadableLoader may create a new Resource from a ResourceRequest
+  // that originates from the ResourceRequest passed to the redirect handling
+  // callback.
 
-    // Before modifying the request for CSP, evaluate report-only headers. This
-    // allows site owners to learn about requests that are being modified
-    // (e.g. mixed content that is being upgraded by upgrade-insecure-requests).
-    const std::optional<ResourceRequest::RedirectInfo>& redirect_info =
-        resource_request.GetRedirectInfo();
-    const KURL& url_before_redirects =
-        redirect_info ? redirect_info->original_url : params.Url();
-    const ResourceRequestHead::RedirectStatus redirect_status =
-        redirect_info ? ResourceRequestHead::RedirectStatus::kFollowedRedirect
-                      : ResourceRequestHead::RedirectStatus::kNoRedirect;
-    context.CheckCSPForRequest(
-        resource_request.GetRequestContext(),
-        resource_request.GetRequestDestination(), resource_request.GetMode(),
-        MemoryCache::RemoveFragmentIdentifierIfNeeded(
-            bundle_url_for_uuid_resources.IsValid()
-                ? bundle_url_for_uuid_resources
-                : params.Url()),
-        options, reporting_disposition,
-        MemoryCache::RemoveFragmentIdentifierIfNeeded(url_before_redirects),
-        redirect_status);
-  }
+  // Before modifying the request for CSP, evaluate report-only headers. This
+  // allows site owners to learn about requests that are being modified
+  // (e.g. mixed content that is being upgraded by upgrade-insecure-requests).
+  const std::optional<ResourceRequest::RedirectInfo>& redirect_info =
+      resource_request.GetRedirectInfo();
+  const KURL& url_before_redirects =
+      redirect_info ? redirect_info->original_url : params.Url();
+  const ResourceRequestHead::RedirectStatus redirect_status =
+      redirect_info ? ResourceRequestHead::RedirectStatus::kFollowedRedirect
+                    : ResourceRequestHead::RedirectStatus::kNoRedirect;
+  context.CheckCSPForRequest(
+      resource_request.GetRequestContext(),
+      resource_request.GetRequestDestination(), resource_request.GetMode(),
+      MemoryCache::RemoveFragmentIdentifierIfNeeded(
+          bundle_url_for_uuid_resources.IsValid()
+              ? bundle_url_for_uuid_resources
+              : params.Url()),
+      options, reporting_disposition,
+      MemoryCache::RemoveFragmentIdentifierIfNeeded(url_before_redirects),
+      redirect_status);
 
-  context.PopulateResourceRequestBeforeCacheAccess(
-      options, resource_request, params.IsPreloadedResponseCandidatePresent());
+  context.PopulateResourceRequestBeforeCacheAccess(options, resource_request);
   if (!resource_request.Url().IsValid()) {
     return ResourceRequestBlockedReason::kOther;
   }
@@ -297,8 +292,7 @@
                                  ? bundle_url_for_uuid_resources
                                  : params.Url()),
                          options, reporting_disposition,
-                         resource_request.GetRedirectInfo(),
-                         params.IsPreloadedResponseCandidatePresent());
+                         resource_request.GetRedirectInfo());
   if (context.CalculateIfAdSubresource(resource_request,
                                        std::nullopt /* alias_url */,
                                        resource_type, options.initiator_info)) {
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
index 4dd2344..a0c4d26 100644
--- a/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
+++ b/third_party/blink/renderer/platform/loader/testing/mock_fetch_context.h
@@ -53,9 +53,8 @@
       const KURL&,
       const ResourceLoaderOptions&,
       ReportingDisposition,
-      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info,
-      FetchParameters::HasPreloadedResponseCandidate
-          has_preloaded_response_candidate) const override {
+      base::optional_ref<const ResourceRequest::RedirectInfo> redirect_info)
+      const override {
     return std::nullopt;
   }
   std::optional<ResourceRequestBlockedReason>
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 74dc808..9ae5256 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -655,12 +655,6 @@
       ]
     },
     {
-      // Enables bypassing CSP checks when we consume a preload.
-      // https://crbug.com/348442535
-      name: "BypassCSPForPreloads",
-      status: "experimental",
-    },
-    {
       // Bypasses the enforcement of the Page Embedded Permission Control
       // security checks. This flag is disabled by default and should only be
       // enabled in automated tests in order to allow them to avoid needing to
diff --git a/third_party/blink/renderer/platform/wtf/text/wtf_string.h b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
index b64a932..f1cf6bd4c 100644
--- a/third_party/blink/renderer/platform/wtf/text/wtf_string.h
+++ b/third_party/blink/renderer/platform/wtf/text/wtf_string.h
@@ -186,6 +186,15 @@
       Utf8ConversionMode mode = Utf8ConversionMode::kLenient) const {
     return StringView(*this).Utf8(mode);
   }
+  // Returns a std::u16string_view pointing this string.
+  // This should be called only if !Is8Bit().
+  //
+  // This function should be removed after enabling C++23 because
+  // std::u16string_view(Span16()) will work with C++23.
+  std::u16string_view View16() const LIFETIME_BOUND {
+    auto chars = Span16();
+    return std::u16string_view(chars.begin(), chars.end());
+  }
 
   UChar operator[](wtf_size_t index) const {
     if (!impl_ || index >= impl_->length())
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index cb6559a..4be17b6 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -8929,9 +8929,6 @@
 crbug.com/393175977 [ Debug Mac14 ] http/tests/devtools/network/preview-searchable.js [ Failure Pass Timeout ]
 crbug.com/393175977 [ Debug Mac14 ] http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-xhr.js [ Failure Pass Timeout ]
 
-# Temporarily disable for landing crrev.com/c/6372540
-crbug.com/375387301 http/tests/devtools/webaudio/audio-context-selector-test.js [ Failure Pass ]
-
 # Gardener 2025-01-21
 crbug.com/391126821 [ Win11-arm64 ] fast/ruby/base-shorter-than-text.html [ Failure Pass ]
 crbug.com/390565845 [ Win ] virtual/media-foundation-for-clear-dcomp/external/wpt/media-source/waiting-for-audio.html [ Crash Failure Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 0361013..12ca913f 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -4332,35 +4332,7 @@
       "external/wpt/upgrade-insecure-requests/gen/top.meta/upgrade"
     ],
     "args": [
-      "--disable-features=PreloadLinkRelDataUrls,BypassCSPForPreloads"
-    ],
-    "expires": "Jul 3, 2025"
-   },
-   {
-    "prefix": "bypass-csp-for-preloads-disabled",
-    "owners": ["nidhijaju@chromium.org"],
-    "platforms": ["Linux", "Mac", "Win"],
-    "bases": [
-      "wpt_internal/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub.html",
-      "wpt_internal/content-security-policy/securitypolicyviolation/input-time.https.html",
-      "external/wpt/content-security-policy/inside-worker",
-      "external/wpt/content-security-policy/reporting-api/reporting-api-report-only-sends-reports-on-violation.https.sub.html",
-      "external/wpt/content-security-policy/reporting",
-      "external/wpt/content-security-policy/script-src/script-src-report-only-policy-works-with-external-hash-policy.html",
-      "external/wpt/content-security-policy/securitypolicyviolation/upgrade-insecure-requests-reporting.https.html",
-      "http/tests/inspector-protocol/issues/content-security-policy-issue-report-only.js",
-      "http/tests/inspector-protocol/issues/mixed-content-issue-creation-img.js",
-      "http/tests/inspector-protocol/no-crash-with-stack-id-and-stale-while-revalidate.js",
-      "http/tests/security/contentSecurityPolicy/nonces/style-reportonly-allowed.php",
-      "external/wpt/upgrade-insecure-requests/gen/iframe-blank-inherit.meta/upgrade",
-      "external/wpt/upgrade-insecure-requests/gen/sharedworker-classic-data.http-rp/upgrade",
-      "external/wpt/upgrade-insecure-requests/gen/srcdoc-inherit.meta/upgrade",
-      "external/wpt/upgrade-insecure-requests/gen/top.http-rp/upgrade",
-      "external/wpt/upgrade-insecure-requests/gen/top.meta/upgrade"
-    ],
-    "args": [
-      "--enable-features=PreloadLinkRelDataUrls",
-      "--disable-features=BypassCSPForPreloads"
+      "--disable-features=PreloadLinkRelDataUrls"
     ],
     "expires": "Jul 3, 2025"
    },
diff --git a/third_party/blink/web_tests/external/wpt/css/css-anchor-position/vertical-aligned-table-cell.html b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/vertical-aligned-table-cell.html
new file mode 100644
index 0000000..9b16621
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-anchor-position/vertical-aligned-table-cell.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<title>Anchor inside table cell with non-top alignment</title>
+<link rel="author" title="Morten Stenshorne" href="mailto:mstensho@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-anchor-position-1/#positioning">
+<link rel="help" href="https://www.w3.org/TR/css-inline-3/#transverse-alignment">
+<link rel="help" href="https://issues.chromium.org/issues/406288652">
+<link rel="match" href="../reference/ref-filled-green-100px-square.xht">
+<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
+<div style="width:100px; height:100px; position:relative; overflow:clip; background:red;">
+  <div style="display:table-cell;">
+    <div id="anchor" style="anchor-name:--a; width:50px; height:100px;"></div>
+  </div>
+  <div style="display:table-cell;">
+    <div style="width:10px; height:200px;"></div>
+  </div>
+  <div style="position:absolute; position-anchor:--a; bottom:anchor(top); width:100px; height:100px; background:green;"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/speculation-tags-utils.js b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/speculation-tags-utils.js
index 9b10fab..07dba0ab 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/speculation-tags-utils.js
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/resources/speculation-tags-utils.js
@@ -13,7 +13,20 @@
     return level;
   }
 
-  function testRulesetTag(tag, expectedTag, description) {
+  // Retrieves a preloading type variant from URLSearchParams of the current
+  // window and returns it. Throw an Error if it doesn't have the valid
+  // preloading type param.
+  function getPreloadingType() {
+    const params = new URLSearchParams(window.location.search);
+    const level = params.get('type');
+    if (level === null)
+      throw new Error('window.location does not have a preloading type param');
+    if (level !== 'prefetch' && level !== 'prerender')
+      throw new Error('window.location does not have a valid preloading type param');
+    return level;
+  }
+
+  function testPrefetchRulesetTag(tag, expectedTag, description) {
     promise_test(async t => {
         const agent = await spawnWindow(t);
         const nextUrl = agent.getExecutorURL({ page: 2 });
@@ -29,11 +42,11 @@
     }, "Sec-Speculation-Tags [ruleset-based]: " + description);
   }
 
-  function testInvalidRulesetTag(tag, description) {
-    testRulesetTag(tag, 'null', description);
+  function testPrefetchInvalidRulesetTag(tag, description) {
+    testPrefetchRulesetTag(tag, 'null', description);
   }
 
-  function testRuleTag(tag, expectedTag, description) {
+  function testPrefetchRuleTag(tag, expectedTag, description) {
     promise_test(async t => {
         const agent = await spawnWindow(t);
         const nextUrl = agent.getExecutorURL({ page: 2 });
@@ -48,7 +61,7 @@
     }, "Sec-Speculation-Tags [rule-based]: " + description);
   }
 
-  function testInvalidRuleTag(tag, description) {
+  function testPrefetchInvalidRuleTag(tag, description) {
     promise_test(async t => {
         const agent = await spawnWindow(t);
         const nextUrl = agent.getExecutorURL({ page: 2 });
@@ -63,21 +76,146 @@
     }, "Sec-Speculation-Tags [rule-based]: " + description);
   }
 
-  // Runs the test function for valid tag cases based on the tag level.
+  function testPrerenderRulesetTag(tag, expectedTag, description) {
+    promise_test(async t => {
+        const rcHelper = new RemoteContextHelper();
+        const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+
+        const extraConfig = {};
+        const prerenderedRC = await referrerRC.helper.createContext({
+            executorCreator(url) {
+              return referrerRC.executeScript((tag, url) => {
+                  const script = document.createElement("script");
+                  script.type = "speculationrules";
+                  script.textContent = JSON.stringify({
+                      tag,
+                      prerender: [
+                        {
+                          source: "list",
+                          urls: [url]
+                        }
+                      ]
+                  });
+                  document.head.append(script);
+              }, [tag, url]);
+            }, extraConfig
+        });
+
+        // Check the prerender request headers embedded in the prerendered page.
+        // Don't need to activate the page.
+        const headers = await prerenderedRC.getRequestHeaders();
+        assert_equals(headers.get("sec-purpose"), "prefetch;prerender");
+        assert_equals(headers.get("sec-speculation-tags"), expectedTag);
+    }, "Sec-Speculation-Tags [ruleset-based]: " + description);
+  }
+
+  function testPrerenderInvalidRulesetTag(tag, description) {
+    testPrerenderRulesetTag(tag, 'null', description);
+  }
+
+  function testPrerenderRuleTag(tag, expectedTag, description) {
+    promise_test(async t => {
+        const rcHelper = new RemoteContextHelper();
+        const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+
+        const extraConfig = {};
+        const prerenderedRC = await referrerRC.helper.createContext({
+            executorCreator(url) {
+              return referrerRC.executeScript((tag, url) => {
+                  const script = document.createElement("script");
+                  script.type = "speculationrules";
+                  script.textContent = JSON.stringify({
+                      prerender: [
+                        {
+                          tag,
+                          source: "list",
+                          urls: [url]
+                        }
+                      ]
+                  });
+                  document.head.append(script);
+              }, [tag, url]);
+            }, extraConfig
+        });
+
+        // Check the prerender request headers embedded in the prerendered page.
+        // Don't need to activate the page.
+        const headers = await prerenderedRC.getRequestHeaders();
+        assert_equals(headers.get("sec-purpose"), "prefetch;prerender");
+        assert_equals(headers.get("sec-speculation-tags"), expectedTag);
+    }, "Sec-Speculation-Tags [rule-based]: " + description);
+  }
+
+  function testPrerenderInvalidRuleTag(tag, description) {
+    promise_test(async t => {
+        const rcHelper = new RemoteContextHelper();
+        const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+
+        const extraConfig = {};
+        const prerenderedRC = await referrerRC.helper.createContext({
+            executorCreator(url) {
+              return referrerRC.executeScript((tag, url) => {
+                  const script = document.createElement("script");
+                  script.type = "speculationrules";
+                  script.textContent = JSON.stringify({
+                      prerender: [
+                        {
+                          tag,
+                          source: "list",
+                          urls: [url]
+                        }
+                      ]
+                  });
+                  document.head.append(script);
+              }, [tag, url]);
+            }, extraConfig
+        });
+
+        // Prerender should fail when an invalid tag is specified, and this
+        // navigation should fall back to network.
+        await referrerRC.navigateTo(prerenderedRC.url);
+
+        // Confirm that the page was loaded from network, not activated, by
+        // checking the prerender request headers.
+        const headers = await prerenderedRC.getRequestHeaders();
+        assert_false(headers.has("sec-purpose"));
+        assert_false(headers.has("sec-speculation-tags"));
+    }, "Sec-Speculation-Tags [rule-based]: " + description);
+  }
+
+  // Runs the test function for valid tag cases based on the tag level and the
+  // preloading type.
   globalThis.testTag = (tag, expectedTag, description) => {
     if (getTagLevel() === 'ruleset') {
-      testRulesetTag(tag, expectedTag, description);
+      if (getPreloadingType() === 'prefetch') {
+        testPrefetchRulesetTag(tag, expectedTag, description);
+      } else {
+        testPrerenderRulesetTag(tag, expectedTag, description);
+      }
     } else {
-      testRuleTag(tag, expectedTag, description);
+      if (getPreloadingType() === ' prefetch') {
+        testPrefetchRuleTag(tag, expectedTag, description);
+      } else {
+        testPrerenderRuleTag(tag, expectedTag, description);
+      }
     }
   };
 
-  // Runs the test function for invalid tag cases based on the tag level.
+  // Runs the test function for invalid tag cases based on the tag level and the
+  // preloading type.
   globalThis.testInvalidTag = (tag, description) => {
     if (getTagLevel() === 'ruleset') {
-      testInvalidRulesetTag(tag, description);
+      if (getPreloadingType() === 'prefetch') {
+        testPrefetchInvalidRulesetTag(tag, description);
+      } else {
+        testPrerenderInvalidRulesetTag(tag, description);
+      }
     } else {
-      testInvalidRuleTag(tag, description);
+      if (getPreloadingType() === 'prefetch') {
+        testPrefetchInvalidRuleTag(tag, description);
+      } else {
+        testPrerenderInvalidRuleTag(tag, description);
+      }
     }
   };
 }
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-invalid.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-invalid.https.html
index e35bab0..3ebf55fb 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-invalid.https.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-invalid.https.html
@@ -1,12 +1,15 @@
 <!DOCTYPE html>
 <title>Prefetch request's Sec-Speculation-Tags request headers</title>
-<meta name="variant" content="?tag-level=ruleset">
-<meta name="variant" content="?tag-level=rule">
+<meta name="variant" content="?tag-level=ruleset&type=prefetch">
+<meta name="variant" content="?tag-level=ruleset&type=prerender">
+<meta name="variant" content="?tag-level=rule&type=prefetch">
+<meta name="variant" content="?tag-level=rule&type=prerender">
 <meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/dispatcher/dispatcher.js"></script>
 <script src="/common/utils.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
 <script src="../resources/utils.js"></script>
 <script src="resources/utils.sub.js"></script>
 <script src="resources/speculation-tags-utils.js"></script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-no-tags.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-no-tags.https.html
index d96bca8..d241613 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-no-tags.https.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-no-tags.https.html
@@ -5,6 +5,8 @@
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/dispatcher/dispatcher.js"></script>
 <script src="/common/utils.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
+<script src="/speculation-rules/prerender/resources/utils.js"></script>
 <script src="../resources/utils.js"></script>
 <script src="resources/utils.sub.js"></script>
 <script src="resources/speculation-tags-utils.js"></script>
@@ -28,5 +30,16 @@
   const headers = await agent.getRequestHeaders();
   assert_prefetched(headers, "must be prefetched");
   assert_equals(headers.sec_speculation_tags, "null", "Sec-Speculation-Tags");
-}, "Sec-Speculation-Tags: no tags");
+}, "Sec-Speculation-Tags: no tags (prefetch)");
+
+promise_test(async t => {
+  const rcHelper = new RemoteContextHelper();
+  const referrerRC = await rcHelper.addWindow(undefined, { features: 'noopener' });
+
+  const prerenderedRC = await addPrerenderRC(referrerRC);
+  const headers = await prerenderedRC.getRequestHeaders();
+  assert_equals(headers.get("sec-purpose"), "prefetch;prerender");
+  assert_equals(headers.get("sec-speculation-tags"), "null");
+}, "Sec-Speculation-Tags: no tags (prerender)");
+
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-valid.https.html b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-valid.https.html
index e5eb7050..4b580e7d 100644
--- a/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-valid.https.html
+++ b/third_party/blink/web_tests/external/wpt/speculation-rules/prefetch/speculation-tags-valid.https.html
@@ -1,12 +1,15 @@
 <!DOCTYPE html>
 <title>Prefetch request's Sec-Speculation-Tags request headers</title>
-<meta name="variant" content="?tag-level=ruleset">
-<meta name="variant" content="?tag-level=rule">
+<meta name="variant" content="?tag-level=ruleset&type=prefetch">
+<meta name="variant" content="?tag-level=ruleset&type=prerender">
+<meta name="variant" content="?tag-level=rule&type=prefetch">
+<meta name="variant" content="?tag-level=rule&type=prerender">
 <meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/dispatcher/dispatcher.js"></script>
 <script src="/common/utils.js"></script>
+<script src="/html/browsers/browsing-the-web/remote-context-helper/resources/remote-context-helper.js"></script>
 <script src="../resources/utils.js"></script>
 <script src="resources/utils.sub.js"></script>
 <script src="resources/speculation-tags-utils.js"></script>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-open-url.js b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-open-url.js
index 41e86a92..7b531465 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-open-url.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/fedcm/fedcm-open-url.js
@@ -1,16 +1,15 @@
 (async function(/** @type {import('test_runner').TestRunner} */ testRunner) {
   const {page, session, dp} =
-      await testRunner.startBlank(
-          "Check that opening account URLs works");
+      await testRunner.startBlank('Check that opening account URLs works');
 
   await page.navigate(
-      "https://devtools.test:8443/inspector-protocol/fedcm/resources/dialog-shown-event.https.html");
+      'https://devtools.test:8443/inspector-protocol/fedcm/resources/dialog-shown-event.https.html');
 
   // Enable FedCM domain
   await dp.FedCm.enable({disableRejectionDelay: true});
 
   // Trigger FedCM dialog
-  const dialogPromise = session.evaluateAsync("triggerDialog()");
+  const dialogPromise = session.evaluateAsync('triggerDialog()');
 
   let msg = await dp.FedCm.onceDialogShown();
   if (msg.error) {
@@ -18,23 +17,31 @@
     return;
   }
 
-  testRunner.log(msg.params, "msg.params: ", ["dialogId"]);
+  testRunner.log(msg.params, 'msg.params: ', ['dialogId']);
 
   await dp.Target.setDiscoverTargets({discover: true});
   // This should fail because this account has no URLs.
-  let result = await dp.FedCm.openUrl({dialogId: msg.params.dialogId,
-                                       accountIndex: 0,
-                                       accountUrlType: "TermsOfService"});
+  let result = await dp.FedCm.openUrl({
+    dialogId: msg.params.dialogId,
+    accountIndex: 0,
+    accountUrlType: 'TermsOfService'
+  });
   testRunner.log(result.error);
 
   // This should succeed.
-  dp.FedCm.openUrl({dialogId: msg.params.dialogId,
-                    accountIndex: 1,
-                    accountUrlType: "TermsOfService"});
+  dp.FedCm.openUrl({
+    dialogId: msg.params.dialogId,
+    accountIndex: 1,
+    accountUrlType: 'TermsOfService'
+  });
 
-  await dp.Target.onceTargetCreated();
-  const pageTargets = (await dp.Target.getTargets()).result.targetInfos.filter(target => target.type === 'page');
-  testRunner.log("Opened URL: " + pageTargets[0].url);
+  const targetCreatedEvent = await dp.Target.onceTargetCreated();
+  const pageTargets =
+      (await dp.Target.getTargets())
+          .result.targetInfos.filter(
+              target => target.targetId ===
+                  targetCreatedEvent.params.targetInfo.targetId);
+  testRunner.log('Opened URL: ' + pageTargets[0].url);
 
   dp.FedCm.dismissDialog({dialogId: msg.params.dialogId});
   testRunner.completeTest();
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash-expected.txt b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash-expected.txt
new file mode 100644
index 0000000..7b5d2fea
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash-expected.txt
@@ -0,0 +1,16 @@
+Tests CSS.getMatchedStylesForNode() under @layer rules.
+Dumping inline style: 
+{
+}
+Dumping matched rules: 
+@layer base
+    *:where(#inspected)* {    regular
+    }
+@media (width > 0px)
+    @layer base
+         {    regular
+            color: green; @[5:14-5:27]
+            color: green; @[undefined-undefined]
+        }
+Dumping inherited rules: 
+
diff --git a/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash.js b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash.js
new file mode 100644
index 0000000..48b806b
--- /dev/null
+++ b/third_party/blink/web_tests/inspector-protocol/css/css-get-styles-for-node-layer-crash.js
@@ -0,0 +1,27 @@
+(async function(/** @type {import('test_runner').TestRunner} */ testRunner) {
+  // crbug.com/408401203
+  var {page, session, dp} = await testRunner.startHTML(`
+      <style>
+        @layer base, utilities;
+        @layer base {
+          :where(#inspected) {
+            @media (width > 0px) {
+              color: green;
+            }
+          }
+        }
+      </style>
+      <div id='inspected'></div>`,
+      `Tests CSS.getMatchedStylesForNode() under @layer rules.`);
+
+  await dp.DOM.enable();
+  await dp.CSS.enable();
+
+  const CSSHelper = await testRunner.loadScript('../resources/css-helper.js');
+  const cssHelper = new CSSHelper(testRunner, dp);
+  const documentNodeId = await cssHelper.requestDocumentNodeId();
+
+  // Don't crash:
+  await cssHelper.loadAndDumpInlineAndMatchingRules(documentNodeId, '#inspected');
+  testRunner.completeTest();
+});
diff --git a/third_party/blink/web_tests/virtual/bypass-csp-for-preloads-disabled/README.md b/third_party/blink/web_tests/virtual/bypass-csp-for-preloads-disabled/README.md
deleted file mode 100644
index 02ebd321..0000000
--- a/third_party/blink/web_tests/virtual/bypass-csp-for-preloads-disabled/README.md
+++ /dev/null
@@ -1,8 +0,0 @@
-# virtual/bypass-csp-for-preloads-disabled
-
-This directory is for tests that need the BypassCSPForPreloads feature flag
-disabled to match the experimental behavior where CSP is not bypassed for
-preloads.
-Tests under `virtual/bypass-csp-for-preloads-disabled` are run with
-`--disable-features=BypassCSPForPreloads` and
-`--enable-features=PreloadLinkRelDataUrls`.
diff --git a/third_party/blink/web_tests/virtual/preload-link-rel-dataurls-disabled/README.md b/third_party/blink/web_tests/virtual/preload-link-rel-dataurls-disabled/README.md
index 6219712..ac90e4f 100644
--- a/third_party/blink/web_tests/virtual/preload-link-rel-dataurls-disabled/README.md
+++ b/third_party/blink/web_tests/virtual/preload-link-rel-dataurls-disabled/README.md
@@ -4,4 +4,4 @@
 disabled to match the experimental behavior where we do not support preloading
 data URLs.
 Tests under `virtual/preload-link-rel-dataurls-disabled` are run with
-`--disable-features=PreloadLinkRelDataUrls,BypassCSPForPreloads`.
+`--disable-features=PreloadLinkRelDataUrls`.
diff --git a/third_party/dawn b/third_party/dawn
index 4cfedf0..33862a3 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 4cfedf0f36940477134b3eff352cf396b74e8e3b
+Subproject commit 33862a3ffc8a511d320fbf938c3e956c27e5c6a0
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index e8b639c..c1bd58c 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit e8b639c4812cbc6276f37fb393da8537422844f8
+Subproject commit c1bd58ca07fe70f4b425597ee5e345d2fb57bc44
diff --git a/third_party/libc++/src b/third_party/libc++/src
index 4e8b01e..c79b671 160000
--- a/third_party/libc++/src
+++ b/third_party/libc++/src
@@ -1 +1 @@
-Subproject commit 4e8b01e3c1c22a50f8eb5290f6a65859d5886205
+Subproject commit c79b6718f6f27bd3576c719ee2989767e8fac5ad
diff --git a/third_party/protobuf/proto_library.gni b/third_party/protobuf/proto_library.gni
index 57e6d228..3839fe4fd 100644
--- a/third_party/protobuf/proto_library.gni
+++ b/third_party/protobuf/proto_library.gni
@@ -641,7 +641,8 @@
       }
     }
 
-    deps = [ ":$action_name" ]
+    public_deps += [ ":$action_name" ]
+    deps = []
 
     # This will link any libraries in the deps (the use of invoker.deps in the
     # action won't link it).
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock
index 6b1d3765..5885327 100644
--- a/third_party/rust/chromium_crates_io/Cargo.lock
+++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -84,7 +84,7 @@
 
 [[package]]
 name = "cc"
-version = "1.2.17"
+version = "1.2.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "shlex",
diff --git a/third_party/rust/chromium_crates_io/supply-chain/config.toml b/third_party/rust/chromium_crates_io/supply-chain/config.toml
index 05b71b03..f896c22 100644
--- a/third_party/rust/chromium_crates_io/supply-chain/config.toml
+++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -80,7 +80,7 @@
 [policy."calendrical_calculations:0.1.3"]
 criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
 
-[policy."cc:1.2.17"]
+[policy."cc:1.2.18"]
 criteria = []
 
 [policy."cfg-if:1.0.0"]
diff --git a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
index e607aea..f8f939d6 100644
--- a/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
+++ b/third_party/rust/chromium_crates_io/vendor/cc-v1/Cargo.toml
@@ -10,7 +10,7 @@
 
 [package]
 name = "cc"
-version = "1.2.17"
+version = "1.2.18"
 
 [features]
 "jobserver" = []
diff --git a/third_party/skia b/third_party/skia
index 245d2b8..515eb62 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 245d2b8fb04212b4b7f122f02438a1f0ac62141e
+Subproject commit 515eb6238867bf965b4f28e2348bae1b4e25e380
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index ddb9ba0..d04dafb 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit ddb9ba0fdcc3193af3c60f811fa4524d54943890
+Subproject commit d04dafb08ac68d0ed86ef37455bcea22e77eca5a
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 5cf5ba4..6ebe266 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 5cf5ba49fd12c048e4192b150eb7528253a887ba
+Subproject commit 6ebe2666e8d9ec374657066d0834560ed8551acc
diff --git a/third_party/webgpu-cts/src b/third_party/webgpu-cts/src
index 75af759..d3ac578 160000
--- a/third_party/webgpu-cts/src
+++ b/third_party/webgpu-cts/src
@@ -1 +1 @@
-Subproject commit 75af759c3c6bc4cb77a0df7c735a8a2061acaa37
+Subproject commit d3ac5784fb25afe1a9605af57112b854bb8206c7
diff --git a/third_party/webrtc b/third_party/webrtc
index 74b5100..7bb8425 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit 74b51006acd2bd9f533c3c309a73cdf2479057c4
+Subproject commit 7bb84253eab7c6c607fe7141815fbd7d4fa326b7
diff --git a/third_party/webrtc_overrides/BUILD.gn b/third_party/webrtc_overrides/BUILD.gn
index 2be0bcb..f19511d 100644
--- a/third_party/webrtc_overrides/BUILD.gn
+++ b/third_party/webrtc_overrides/BUILD.gn
@@ -159,7 +159,6 @@
   "//third_party/webrtc/rtc_base/network:ecn_marking",
   "//third_party/webrtc/rtc_base/network:received_packet",
   "//third_party/webrtc/rtc_base/system:rtc_export",
-  "//third_party/webrtc/rtc_base/third_party/base64",
   "//third_party/webrtc/rtc_base/third_party/sigslot",
   "//third_party/webrtc/rtc_base/third_party/sigslot:sigslot",
   "//third_party/webrtc/stats",
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 3b69c0c..b2e9fd3 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -12435,6 +12435,7 @@
   <int value="-711890895" label="enable-website-settings-manager"/>
   <int value="-711422585" label="kSignInProfileCreationEnterprise:disabled"/>
   <int value="-710794209" label="PersonalizationJelly:enabled"/>
+  <int value="-710538344" label="AAudioPerStreamDeviceSelection:disabled"/>
   <int value="-709058455" label="ui-slow-animations"/>
   <int value="-708482536" label="Cormorant:disabled"/>
   <int value="-707548346" label="MediaAppLens:enabled"/>
@@ -15432,6 +15433,7 @@
   <int value="448463569" label="NewShortcutMapping:disabled"/>
   <int value="449793694" label="OmniboxNumWebZpsRelatedSearches:disabled"/>
   <int value="450440544" label="ShowKiteForSupervisedUsers:enabled"/>
+  <int value="451132705" label="AAudioPerStreamDeviceSelection:enabled"/>
   <int value="451196246" label="disable-impl-side-painting"/>
   <int value="452139294" label="VrShellExperimentalRendering:enabled"/>
   <int value="452395990" label="EnablePixDetection:disabled"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index bab7dd3..b40ed0e 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -1633,7 +1633,7 @@
 </histogram>
 
 <histogram name="Accessibility.FaceGaze.AverageFaceLandmarkerLatency"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>akihiroota@chromium.org</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
@@ -3912,7 +3912,7 @@
 </histogram>
 
 <histogram name="SodaInstaller.Language.{SodaLanguageCode}.InstallationResult"
-    enum="BooleanSuccess" expires_after="2025-07-28">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>abigailbklein@google.com</owner>
   <owner>evliu@google.com</owner>
   <owner>yilkal@chromium.org</owner>
@@ -3928,7 +3928,7 @@
 
 <histogram
     name="SodaInstaller.Language.{SodaLanguageCode}.Installation{Result}Time"
-    units="ms" expires_after="2025-07-28">
+    units="ms" expires_after="2025-10-05">
   <owner>abigailbklein@google.com</owner>
   <owner>evliu@google.com</owner>
   <owner>yilkal@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/android/enums.xml b/tools/metrics/histograms/metadata/android/enums.xml
index e0372ff..66e735d 100644
--- a/tools/metrics/histograms/metadata/android/enums.xml
+++ b/tools/metrics/histograms/metadata/android/enums.xml
@@ -2346,6 +2346,16 @@
   <int value="8" label="Text dark, night mode off"/>
 </enum>
 
+<!-- LINT.IfChange(WebViewSendIntentState) -->
+
+<enum name="WebViewSendIntentState">
+  <int value="0" label="Did not invoke sendBrowsingIntent"/>
+  <int value="1" label="Invoked sendBrowsingIntent"/>
+  <int value="2" label="New activity started"/>
+</enum>
+
+<!-- LINT.ThenChange(//android_webview/java/src/org/chromium/android_webview/AwContentsClient.java:SendIntentState) -->
+
 <enum name="WebViewShouldInterceptRequestOverridden">
   <int value="0"
       label="shouldInterceptRequest is not overridden by WebViewClient."/>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 1324cb2..01eaddd 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -907,7 +907,7 @@
 </histogram>
 
 <histogram name="Android.BackPress.Backfalsing2" enum="NavigationDirection"
-    expires_after="2025-07-27">
+    expires_after="2025-10-05">
   <owner>eleanorlee@google.com</owner>
   <owner>lazzzis@chromium.org</owner>
   <owner>clank-app-team@google.com</owner>
@@ -973,7 +973,7 @@
 </histogram>
 
 <histogram name="Android.BackPress.Intercept{Direction}"
-    enum="BackPressConsumer" expires_after="2025-08-03">
+    enum="BackPressConsumer" expires_after="2025-10-05">
   <owner>lazzzis@chromium.org</owner>
   <owner>src/chrome/browser/back_press/android/OWNERS</owner>
   <summary>
@@ -2183,7 +2183,7 @@
 </histogram>
 
 <histogram name="Android.Hub.PaneFocused" enum="HubPaneId"
-    expires_after="2025-06-29">
+    expires_after="2025-10-05">
   <owner>ckitagawa@chromium.org</owner>
   <owner>clank-hub-dev@google.com</owner>
   <summary>
@@ -2625,7 +2625,7 @@
 
 <histogram
     name="Android.IsolatedSplits.PreloadWaitTime{AndroidFeatureModuleName}"
-    units="ms" expires_after="2025-08-06">
+    units="ms" expires_after="2025-10-05">
   <owner>cduvall@chromium.org</owner>
   <owner>agrieve@chromium.org</owner>
   <owner>smaier@chromium.org</owner>
@@ -2753,7 +2753,7 @@
 </histogram>
 
 <histogram name="Android.Messages.Enqueued" enum="MessageIdentifier"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lazzzis@chromium.org</owner>
   <owner>src/components/messages/OWNERS</owner>
   <summary>
@@ -2791,7 +2791,7 @@
 </histogram>
 
 <histogram name="Android.Messages.Enqueued.Visible" enum="MessageIdentifier"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lazzzis@chromium.org</owner>
   <owner>src/components/messages/OWNERS</owner>
   <summary>
@@ -6884,7 +6884,7 @@
 </histogram>
 
 <histogram name="Android.WebView.NonEmbeddedMetrics.HistogramRecordAge"
-    units="minutes" expires_after="2025-08-03">
+    units="minutes" expires_after="2025-10-05">
   <owner>ntfschr@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <summary>
@@ -6897,7 +6897,7 @@
 </histogram>
 
 <histogram name="Android.WebView.NonEmbeddedMetrics.NumHistograms"
-    units="histograms" expires_after="2025-08-03">
+    units="histograms" expires_after="2025-10-05">
   <owner>ntfschr@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <summary>
@@ -6909,7 +6909,7 @@
 
 <histogram name="Android.WebView.NonEmbeddedMetrics.ParsingLogResult"
     enum="AndroidWebViewNonEmbeddedMetricsParsingLogResult"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>ntfschr@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <summary>
@@ -6921,7 +6921,7 @@
 </histogram>
 
 <histogram name="Android.WebView.NonEmbeddedMetrics.TransmissionResult"
-    enum="AndroidWebViewDevUiMetricsTransmission" expires_after="2025-08-03">
+    enum="AndroidWebViewDevUiMetricsTransmission" expires_after="2025-10-05">
   <owner>ntfschr@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <summary>
@@ -7359,6 +7359,24 @@
   </summary>
 </histogram>
 
+<histogram name="Android.WebView.SendBrowsingIntent"
+    enum="WebViewSendIntentState" expires_after="2026-04-01">
+  <owner>pbirk@google.com</owner>
+  <owner>src/android_webview/OWNERS</owner>
+  <summary>
+    Records whether WebView handled a navigation by sending a browsing intent or
+    not. The default behavior is to send a browsing intent for navigations and
+    redirects, but this behavior is disabled if the application provides a
+    WebViewClient of any kind.
+
+    The aim of this histogram is to determine if any applications use the
+    default behavior.
+
+    This histogram is emitted when WebViewClient.shouldOverrideUrlLoading is
+    called.
+  </summary>
+</histogram>
+
 <histogram name="Android.WebView.SetAcceptThirdPartyCookies"
     enum="BooleanAccepted" expires_after="2025-06-13">
   <owner>jdeabreu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/arc/histograms.xml b/tools/metrics/histograms/metadata/arc/histograms.xml
index 464c949..ee109f9 100644
--- a/tools/metrics/histograms/metadata/arc/histograms.xml
+++ b/tools/metrics/histograms/metadata/arc/histograms.xml
@@ -335,7 +335,7 @@
 </histogram>
 
 <histogram name="Arc.Anr.{AnrPeriod}.{ArcBootType}" units="ANRs"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>khmel@google.com</owner>
   <owner>arc-performance@google.com</owner>
   <summary>
@@ -346,7 +346,7 @@
   <token key="ArcBootType" variants="ArcBootTypes"/>
 </histogram>
 
-<histogram name="Arc.Anr.{AnrSource}" enum="ArcAnr" expires_after="2025-08-03">
+<histogram name="Arc.Anr.{AnrSource}" enum="ArcAnr" expires_after="2025-10-05">
   <owner>khmel@google.com</owner>
   <owner>arc-performance@google.com</owner>
   <summary>
@@ -680,7 +680,7 @@
 </histogram>
 
 <histogram name="Arc.ArcOnDemandV2.ActivationShouldBeDelayed" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>yuholong@google.com</owner>
   <owner>arcvm-eng@google.com</owner>
   <summary>
@@ -1409,7 +1409,7 @@
 </histogram>
 
 <histogram name="Arc.KeyMint.KeyMintError.{ArcKeyMintLoggedOperation}"
-    enum="ArcKeyMintError" expires_after="2025-08-03">
+    enum="ArcKeyMintError" expires_after="2025-10-05">
   <owner>batoon@google.com</owner>
   <owner>arc-commercial@google.com</owner>
   <summary>
@@ -1730,7 +1730,7 @@
 </histogram>
 
 <histogram name="Arc.OptinTosLoadResult" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jhorwich@google.com</owner>
   <owner>arc-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml
index 275971f..b21149b 100644
--- a/tools/metrics/histograms/metadata/ash/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -794,7 +794,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthClosedDuringAuth" enum="Boolean"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -805,7 +805,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthClosedWithSuccess"
-    enum="BooleanSuccess" expires_after="2025-08-02">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -815,7 +815,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthFailed" enum="AuthInputType"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -825,7 +825,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthFingerprintAttempt" units="attempts"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -835,7 +835,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthOpenDuration" units="ms"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -845,7 +845,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthPasswordAttempt" units="attempts"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -855,7 +855,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionAuthPinAttempt" units="attempts"
-    expires_after="2025-08-02">
+    expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -895,7 +895,7 @@
 </histogram>
 
 <histogram name="Ash.Auth.ActiveSessionShowReason"
-    enum="ActiveSessionAuthControllerReason" expires_after="2025-08-02">
+    enum="ActiveSessionAuthControllerReason" expires_after="2025-10-05">
   <owner>iscsi@google.com</owner>
   <owner>cros-lurs@google.com</owner>
   <summary>
@@ -1085,7 +1085,7 @@
 </histogram>
 
 <histogram name="Ash.Birch.Coral.ClusterExpanded" enum="Boolean"
-    expires_after="2025-06-22">
+    expires_after="2025-10-05">
   <owner>zxdan@chromium.org</owner>
   <owner>cros-coral@google.com</owner>
   <summary>
@@ -1095,7 +1095,7 @@
 </histogram>
 
 <histogram name="Ash.Birch.Coral.ClusterItemRemoved" units="count"
-    expires_after="2025-07-13">
+    expires_after="2025-10-05">
   <owner>zxdan@chromium.org</owner>
   <owner>cros-coral@google.com</owner>
   <summary>
@@ -2629,7 +2629,7 @@
 </histogram>
 
 <histogram name="Ash.Desks.DesksSwitchScreenshotResult" enum="BooleanSuccess"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>dandersson@chromium.org</owner>
   <owner>chromeos-wm@google.com</owner>
   <summary>
@@ -3469,7 +3469,7 @@
 </histogram>
 
 <histogram name="Ash.EventLatency.TotalLatency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>yichenz@chromium.org</owner>
   <owner>cros-sw-perf@google.com</owner>
@@ -5011,7 +5011,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.AutoRestore.AllBrowserWindowsCreated" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5024,7 +5024,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.AutoRestore.AllBrowserWindowsPresented"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5051,7 +5051,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.ManualRestore.{UIFlow}.TotalDuration" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>junis@google.com</owner>
   <owner>xiyuan@chromium.org</owner>
   <owner>zxdan@chromium.org</owner>
@@ -5079,7 +5079,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.{RestoreMode}.AllShelfIconsLoaded" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5103,7 +5103,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.{RestoreMode}.DeferredTasksStarted" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5158,7 +5158,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.{RestoreMode}.ShelfLoginAnimationEnd" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5170,7 +5170,7 @@
 </histogram>
 
 <histogram name="Ash.LoginPerf.{RestoreMode}.TotalDuration" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>xiyuan@chromium.org</owner>
   <owner>junis@google.com</owner>
   <owner>cros-sw-perf@google.org</owner>
@@ -5302,7 +5302,7 @@
 </histogram>
 
 <histogram name="Ash.MantaService.{MantaMetricType}.StatusCode"
-    enum="MantaStatusCode" expires_after="2025-08-03">
+    enum="MantaStatusCode" expires_after="2025-10-05">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <summary>Record the status code of {MantaMetricType} requests.</summary>
@@ -5310,7 +5310,7 @@
 </histogram>
 
 <histogram name="Ash.MantaService.{MantaMetricType}.TimeCost" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <summary>
@@ -7713,7 +7713,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.Api.Thumbnails.Count" units="count"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thuongphan@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -7733,7 +7733,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.Api.{Type}.Latency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thuongphan@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -7745,7 +7745,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.Api.{Type}.MantaStatusCode"
-    enum="MantaStatusCode" expires_after="2025-08-03">
+    enum="MantaStatusCode" expires_after="2025-10-05">
   <owner>thuongphan@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -7785,7 +7785,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.Suggestion.Clicked" enum="BooleanClicked"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>ericamlee@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -7803,7 +7803,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.Tab.Clicked" enum="SeaPenFreeformTab"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>ericamlee@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>Emitted when the user clicks on a freeform tab.</summary>
@@ -7821,7 +7821,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.Freeform.{AppName}.Visited" enum="BooleanHit"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>ericamlee@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -7907,7 +7907,7 @@
 </histogram>
 
 <histogram name="Ash.SeaPen.{TemplateName}.UserFeedback" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>pzliu@google.com</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -9133,7 +9133,7 @@
 </histogram>
 
 <histogram name="Ash.Wallpaper.Collection" enum="WallpaperCollection"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jasontt@chromium.org</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
@@ -9393,7 +9393,7 @@
 </histogram>
 
 <histogram name="Ash.Wallpaper.{Type}.Result2" enum="SetWallpaperResult"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thuongphan@chromium.org</owner>
   <owner>cros-p13n-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/ash_growth/histograms.xml b/tools/metrics/histograms/metadata/ash_growth/histograms.xml
index 44e88c0..c6e1be56 100644
--- a/tools/metrics/histograms/metadata/ash_growth/histograms.xml
+++ b/tools/metrics/histograms/metadata/ash_growth/histograms.xml
@@ -84,7 +84,7 @@
 </histogram>
 
 <histogram name="Ash.Growth.CampaignsManager.GetCampaignBySlot.Attempt"
-    enum="CampaignSlot" expires_after="2025-08-03">
+    enum="CampaignSlot" expires_after="2025-10-05">
   <owner>llin@google.com</owner>
   <owner>cros-growth@google.com</owner>
   <summary>
@@ -94,7 +94,7 @@
 </histogram>
 
 <histogram name="Ash.Growth.CampaignsManager.GetCampaignBySlot.Campaigns500"
-    units="int" expires_after="2025-08-03">
+    units="int" expires_after="2025-10-05">
   <owner>wutao@chromium.org</owner>
   <owner>cros-growth@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
index 5c2ed42..7ed5851 100644
--- a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
+++ b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
@@ -305,7 +305,7 @@
 </histogram>
 
 <histogram name="Conversions.AndroidOperationResult2.{Operation}"
-    enum="ConversionAndroidOperationResult" expires_after="2025-08-03">
+    enum="ConversionAndroidOperationResult" expires_after="2025-10-05">
   <owner>linnan@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
   <summary>
@@ -1228,7 +1228,7 @@
 </histogram>
 
 <histogram name="Conversions.SourceRegistrationTimeConfig"
-    enum="SourceRegistrationTimeConfig" expires_after="2025-08-03">
+    enum="SourceRegistrationTimeConfig" expires_after="2025-10-05">
   <owner>csharrison@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/autofill/enums.xml b/tools/metrics/histograms/metadata/autofill/enums.xml
index d2defac76..c1de77e90 100644
--- a/tools/metrics/histograms/metadata/autofill/enums.xml
+++ b/tools/metrics/histograms/metadata/autofill/enums.xml
@@ -2983,6 +2983,14 @@
 
 <!-- LINT.ThenChange(/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc:Result) -->
 
+<!-- LINT.IfChange(BnplFormEvent) -->
+
+<enum name="BnplFormEvent">
+  <int value="0" label="Suggestions shown (once)"/>
+</enum>
+
+<!-- LINT.ThenChange(/components/autofill/core/browser/metrics/payments/bnpl_metrics.h:BnplFormEvent) -->
+
 <!-- LINT.IfChange(BnplPopupWindowResult) -->
 
 <enum name="BnplPopupWindowResult">
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml
index 2235fc7..41a63a28 100644
--- a/tools/metrics/histograms/metadata/autofill/histograms.xml
+++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -1441,7 +1441,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.OptInCalled.FromCheckoutFlow"
-    enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2025-07-01">
+    enum="AutofillCreditCardWebauthnOptInParameters" expires_after="2025-10-05">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -1454,7 +1454,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.OptInPromoNotOfferedReason"
-    enum="WebauthnOptInPromoNotOfferedReason" expires_after="2025-07-01">
+    enum="WebauthnOptInPromoNotOfferedReason" expires_after="2025-10-05">
   <owner>vinnypersky@google.com</owner>
   <owner>shgar@google.com</owner>
   <summary>
@@ -1467,7 +1467,7 @@
 </histogram>
 
 <histogram name="Autofill.BetterAuth.OptInPromoShown.FromCheckoutFlow"
-    enum="BooleanHit" expires_after="2025-07-01">
+    enum="BooleanHit" expires_after="2025-10-05">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -1501,7 +1501,7 @@
 
 <histogram
     name="Autofill.BetterAuth.PreflightCallResponseReceivedOnCardSelection.{AutofillFidoAuthenticationEnabledState}.{CardType}"
-    enum="AutofillCreditCardPreflightCallEvent" expires_after="2025-07-01">
+    enum="AutofillCreditCardPreflightCallEvent" expires_after="2025-10-05">
   <owner>junhuihe@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
   <summary>
@@ -1520,7 +1520,7 @@
 
 <histogram
     name="Autofill.BetterAuth.UserPerceivedLatencyOnCardSelection.OptedIn.Duration"
-    units="ms" expires_after="2025-07-01">
+    units="ms" expires_after="2025-10-05">
   <owner>jsaul@google.com</owner>
   <owner>siyua@chromium.org</owner>
   <owner>autofill-auth-team@google.com</owner>
@@ -1720,7 +1720,7 @@
 
 <histogram name="Autofill.CardUnmaskAuthenticationSelectionDialog.Result"
     enum="AutofillCardUnmaskAuthenticationSelectionDialogResult"
-    expires_after="2025-07-01">
+    expires_after="2025-10-05">
   <owner>siyua@chromium.org</owner>
   <owner>jsaul@google.com</owner>
   <owner>siashah@chromium.org</owner>
@@ -2983,6 +2983,19 @@
   </summary>
 </histogram>
 
+<histogram name="Autofill.FormEvents.CreditCard.Bnpl" enum="BnplFormEvent"
+    expires_after="2025-07-01">
+  <owner>yiwenqian@google.com</owner>
+  <owner>payments-autofill-team@google.com</owner>
+  <summary>
+    This histogram records events related to Buy Now Pay Later (BNPL)
+    suggestions on credit card forms of BNPL-eligible merchant sites. It tracks
+    when the BNPL suggestion is shown, selected, filled, and submitted. Each
+    event log is emitted when the action occurs (suggestion shown, selected,
+    etc.)
+  </summary>
+</histogram>
+
 <histogram name="Autofill.FormEvents.CreditCard.CardInfoRetrievalEnrolled"
     enum="CardInfoRetrievalEnrolledLoggingEvent" expires_after="2025-08-31">
   <owner>jialihuang@google.com</owner>
@@ -3439,7 +3452,7 @@
 </histogram>
 
 <histogram name="Autofill.Iban.UnmaskIbanResult" enum="Boolean"
-    expires_after="2025-07-01">
+    expires_after="2025-10-05">
   <owner>qihuizhao@google.com</owner>
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
@@ -3473,7 +3486,7 @@
 </histogram>
 
 <histogram name="Autofill.IbanUploadEnabled.{AutofillPaymentsSigninState}"
-    enum="IbanUploadEnabledStatus" expires_after="2025-07-01">
+    enum="IbanUploadEnabledStatus" expires_after="2025-10-05">
   <owner>qihuizhao@google.com</owner>
   <owner>jsaul@google.com</owner>
   <owner>payments-autofill-team@google.com</owner>
@@ -3837,7 +3850,7 @@
 </histogram>
 
 <histogram name="Autofill.LocalHeuristics.MatchedAttribute"
-    enum="AutofillMatchAttribute" expires_after="2025-08-03">
+    enum="AutofillMatchAttribute" expires_after="2025-10-05">
   <owner>fleimgruber@google.com</owner>
   <owner>chrome-autofill-alerts@google.com</owner>
   <summary>
@@ -4524,7 +4537,7 @@
 </histogram>
 
 <histogram name="Autofill.PaymentMethodsSettingsPage.ScanCardResult"
-    enum="AutofillScanCreditCardResult" expires_after="2025-08-03">
+    enum="AutofillScanCreditCardResult" expires_after="2025-10-05">
   <owner>darwinyang@google.com</owner>
   <owner>chrome-payments-team@google.com</owner>
   <summary>
@@ -4537,7 +4550,7 @@
 </histogram>
 
 <histogram name="Autofill.PaymentsDataManager.LocalCardAdded" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>npnavarro@google.com</owner>
   <owner>darwinyang@google.com</owner>
   <owner>chrome-payments-eng@google.com</owner>
@@ -4773,7 +4786,7 @@
 </histogram>
 
 <histogram name="Autofill.ProfileImport.NewProfileDecision2.{UserGroup}"
-    enum="AutofillProfileImportDecision" expires_after="2025-08-03">
+    enum="AutofillProfileImportDecision" expires_after="2025-10-05">
   <owner>koerber@google.com</owner>
   <owner>src/components/autofill/OWNERS</owner>
   <summary>
@@ -5071,7 +5084,7 @@
 </histogram>
 
 <histogram name="Autofill.ProgressDialog.{FlowType}.Result"
-    enum="BooleanCanceled" expires_after="2025-07-01">
+    enum="BooleanCanceled" expires_after="2025-10-05">
   <owner>siashah@chromium.org</owner>
   <owner>siyua@chromium.org</owner>
   <owner>jsaul@google.com</owner>
@@ -5090,7 +5103,7 @@
 </histogram>
 
 <histogram name="Autofill.ProgressDialog.{FlowType}.Shown" enum="BooleanShown"
-    expires_after="2025-07-01">
+    expires_after="2025-10-05">
   <owner>siashah@chromium.org</owner>
   <owner>siyua@chromium.org</owner>
   <owner>jsaul@google.com</owner>
@@ -6274,7 +6287,7 @@
 </histogram>
 
 <histogram name="Autofill.ThirdPartyModeDisabled.Provider"
-    enum="AutofillProviderPackageName" expires_after="2025-08-03">
+    enum="AutofillProviderPackageName" expires_after="2025-10-05">
   <owner>friedrichh@chromium.org</owner>
   <owner>izuzic@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml
index 59e1c05..40abc09 100644
--- a/tools/metrics/histograms/metadata/blink/enums.xml
+++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -6103,6 +6103,7 @@
   <int value="5476" label="CustomHighlightPseudoElement"/>
   <int value="5477" label="SpellingErrorPseudoElement"/>
   <int value="5478" label="GrammarErrorPseudoElement"/>
+  <int value="5479" label="SpeculationRulesTags"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml
index dcd3697..e302a31 100644
--- a/tools/metrics/histograms/metadata/blink/histograms.xml
+++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -431,7 +431,7 @@
 </histogram>
 
 <histogram name="Blink.Canvas.RasterDuration{BlinkCanvasRasterDurationType}"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>aaronhk@chromium.org</owner>
   <owner>fserb@chromium.org</owner>
   <summary>
@@ -689,7 +689,7 @@
 </histogram>
 
 <histogram name="Blink.CommitDocumentLoaderTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>nidhijaju@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2529,7 +2529,7 @@
 
 <histogram
     name="Blink.HitTestDocumentUpdate.UpdateTime{BlinkUpdateTimeSuffixes}"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>pdr@chromium.org</owner>
   <owner>paint-dev@chromium.org</owner>
   <summary>
@@ -4646,7 +4646,7 @@
 </histogram>
 
 <histogram name="Blink.ScanAndPreloadTime2{Task}.{FrameType}.{IsInitial}"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>sisidovski@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml
index 170c836..c5a8da4f 100644
--- a/tools/metrics/histograms/metadata/browser/histograms.xml
+++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -128,7 +128,7 @@
 </histogram>
 
 <histogram name="Browser.ERP.CachedEventsCountExp" units="events"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -258,7 +258,7 @@
 </histogram>
 
 <histogram name="Browser.ERP.EventsUploadCountExp" units="uploads"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -277,7 +277,7 @@
 </histogram>
 
 <histogram name="Browser.ERP.EventUploadSizeAdjustment.{Param}" units="bytes"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -501,7 +501,7 @@
 </histogram>
 
 <histogram name="Browser.ERP.{ManagementStatus}UploadEncryptedReport"
-    enum="EnterpriseDMServerRequestSuccess" expires_after="2025-08-03">
+    enum="EnterpriseDMServerRequestSuccess" expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>src/components/reporting/OWNERS</owner>
   <summary>
@@ -1884,7 +1884,7 @@
   </summary>
 </histogram>
 
-<histogram name="SidePanel.ResizedWidth" units="px" expires_after="2025-08-03">
+<histogram name="SidePanel.ResizedWidth" units="px" expires_after="2025-10-05">
   <owner>emshack@chromium.org</owner>
   <owner>top-chrome-desktop-ui@google.com</owner>
   <summary>
@@ -1894,7 +1894,7 @@
 </histogram>
 
 <histogram name="SidePanel.ResizedWidthPercentage" units="% of window width"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>emshack@chromium.org</owner>
   <owner>top-chrome-desktop-ui@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/chromeos/histograms.xml b/tools/metrics/histograms/metadata/chromeos/histograms.xml
index 342a6f9e..99d8739 100644
--- a/tools/metrics/histograms/metadata/chromeos/histograms.xml
+++ b/tools/metrics/histograms/metadata/chromeos/histograms.xml
@@ -1322,7 +1322,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Debugd.Perf.{FunctionName}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>enlightened@google.com</owner>
   <owner>jorgelo@google.com</owner>
   <owner>chromeos-security-core@google.com</owner>
@@ -1577,7 +1577,7 @@
 
 <histogram
     name="ChromeOS.FirmwareUpdateUi.RequestSucceededWithDuration.RequestId{DeviceRequestId}"
-    units="ms" expires_after="2025-06-28">
+    units="ms" expires_after="2025-10-05">
   <owner>cambickel@google.com</owner>
   <owner>jimmyxgong@chromium.org</owner>
   <owner>cros-device-enablement@google.com</owner>
@@ -1656,7 +1656,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Gaia.CreateAccount.IsFirstUser" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thv@google.com</owner>
   <owner>cros-growth@google.com</owner>
   <summary>
@@ -1668,7 +1668,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Gaia.Done.ElapsedTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>bchikhaoui@google.com</owner>
   <owner>cros-oac@google.com</owner>
   <summary>
@@ -1678,7 +1678,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Gaia.Done.Oobe.NewAccount" enum="BooleanNewAccount"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thv@google.com</owner>
   <owner>cros-growth@google.com</owner>
   <summary>
@@ -1689,7 +1689,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Gaia.Message.{GaiaAuthFlow}.{MessageName}"
-    enum="BooleanReceived" expires_after="2025-08-03">
+    enum="BooleanReceived" expires_after="2025-10-05">
   <owner>ayag@chromium.org</owner>
   <owner>cros-3pidp@google.com</owner>
   <summary>
@@ -1799,7 +1799,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Healthd.DiagnosticResult.{Routine}"
-    enum="CrosHealthdDiagnosticResult" expires_after="2025-08-03">
+    enum="CrosHealthdDiagnosticResult" expires_after="2025-10-05">
   <owner>weiluanwang@google.com</owner>
   <owner>dennyh@google.com</owner>
   <owner>cros-tdm-tpe-eng@google.com</owner>
@@ -1881,7 +1881,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Healthd.TelemetryResult.{Category}"
-    enum="CrosHealthdTelemetryResult" expires_after="2025-08-03">
+    enum="CrosHealthdTelemetryResult" expires_after="2025-10-05">
   <owner>weiluanwang@google.com</owner>
   <owner>dennyh@google.com</owner>
   <owner>cros-tdm-tpe-eng@google.com</owner>
@@ -2812,7 +2812,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Mahi.CacheStateOnAccess" enum="MahiCacheHit"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thanhdng@chromium.org</owner>
   <owner>chrome-knowledge-eng@google.com</owner>
   <summary>
@@ -2883,7 +2883,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Mahi.ProviderCreationStatus"
-    enum="MahiProviderCreationStatus" expires_after="2025-08-03">
+    enum="MahiProviderCreationStatus" expires_after="2025-10-05">
   <owner>alanlxl@chromium.org</owner>
   <owner>thanhdng@chromium.org</owner>
   <owner>chrome-knowledge-eng@google.com</owner>
@@ -2896,7 +2896,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Mahi.ResponseStatusOnRequest"
-    enum="MahiResponseStatus" expires_after="2025-08-03">
+    enum="MahiResponseStatus" expires_after="2025-10-05">
   <owner>thanhdng@chromium.org</owner>
   <owner>chrome-knowledge-eng@google.com</owner>
   <summary>
@@ -2906,7 +2906,7 @@
 </histogram>
 
 <histogram name="ChromeOS.Mahi.Used" enum="MahiFeature"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thanhdng@chromium.org</owner>
   <owner>chrome-knowledge-eng@google.com</owner>
   <summary>
@@ -3222,7 +3222,7 @@
 </histogram>
 
 <histogram name="ChromeOS.SAML.InSessionPasswordSyncEvent"
-    enum="SamlInSessionPasswordSyncEvent" expires_after="2025-08-03">
+    enum="SamlInSessionPasswordSyncEvent" expires_after="2025-10-05">
   <owner>mslus@chromium.org</owner>
   <owner>cros-3pidp@google.com</owner>
   <summary>
@@ -4632,7 +4632,7 @@
 </histogram>
 
 <histogram name="ChromeOS.TelemetryExtension.RoutineCreation"
-    enum="TelemetryExtensionRoutineCategory" expires_after="2025-08-03">
+    enum="TelemetryExtensionRoutineCategory" expires_after="2025-10-05">
   <owner>weiluanwang@google.com</owner>
   <owner>dennyh@google.com</owner>
   <owner>cros-tdm-tpe-eng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml
index 250b7f5..f76663e9 100644
--- a/tools/metrics/histograms/metadata/commerce/histograms.xml
+++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -303,7 +303,7 @@
 
 <histogram
     name="Commerce.Discounts.DiscountsPageActionIconIsExpandedWhenClicked"
-    enum="BooleanYesNo" expires_after="2025-07-27">
+    enum="BooleanYesNo" expires_after="2025-10-05">
   <owner>meiliang@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
   <summary>
@@ -323,7 +323,7 @@
 </histogram>
 
 <histogram name="Commerce.Discounts.PageActionIcon.TypeOnClick"
-    enum="DiscountClusterType" expires_after="2025-07-27">
+    enum="DiscountClusterType" expires_after="2025-10-05">
   <owner>meiliang@chromium.org</owner>
   <owner>chrome-shopping@google.com</owner>
   <summary>
@@ -841,7 +841,7 @@
 </histogram>
 
 <histogram name="Commerce.ProductInfo.OnDemandRequest.Success" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mdjones@chromium.org</owner>
   <owner>ayman@chromium.org</owner>
   <summary>
@@ -853,7 +853,7 @@
 </histogram>
 
 <histogram name="Commerce.ShoppingService.ProductInfo.FallbackDataContent"
-    enum="ShoppingDataProviderFallback" expires_after="2025-07-27">
+    enum="ShoppingDataProviderFallback" expires_after="2025-10-05">
   <owner>ayman@chromium.org</owner>
   <owner>mdjones@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml
index f421012..208e189e 100644
--- a/tools/metrics/histograms/metadata/compositing/histograms.xml
+++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -754,7 +754,7 @@
 </histogram>
 
 <histogram name="Compositing.SurfaceAggregator.AggregateUs"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>kylechar@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1055,7 +1055,7 @@
 </histogram>
 
 <histogram name="CompositorLatency{ReportType}{InteractionType}.{StageType}"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1227,7 +1227,7 @@
 </histogram>
 
 <histogram name="Graphics.Smoothness.CheckerboardingNeedRecord4.AllSequences"
-    units="%" expires_after="2025-08-03">
+    units="%" expires_after="2025-10-05">
   <owner>wangxianzhu@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1275,7 +1275,7 @@
 </histogram>
 
 <histogram name="Graphics.Smoothness.Checkerboarding{Version}.{Sequence}"
-    units="%" expires_after="2025-08-03">
+    units="%" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1439,7 +1439,7 @@
 </histogram>
 
 <histogram name="Graphics.Smoothness.PercentDroppedFrames3.{Sequence}"
-    units="%" expires_after="2025-08-03">
+    units="%" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1491,7 +1491,7 @@
 </histogram>
 
 <histogram name="Graphics.Smoothness.PercentDroppedFrames3.{Thread}{Sequence}"
-    units="%" expires_after="2025-08-03">
+    units="%" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml
index 7be0f0f..e3feb29 100644
--- a/tools/metrics/histograms/metadata/content/histograms.xml
+++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -395,7 +395,7 @@
 </histogram>
 
 <histogram name="ContentSettings.Popups.StrongBlockerActions"
-    enum="StrongPopupBlockerAction" expires_after="2025-08-03">
+    enum="StrongPopupBlockerAction" expires_after="2025-10-05">
   <owner>csharrison@chromium.org</owner>
   <summary>
     Counts of various events related to the strong popup blocker (aka abusive
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml
index c3cfe0e5..0cdac2fd 100644
--- a/tools/metrics/histograms/metadata/cookie/histograms.xml
+++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -272,7 +272,7 @@
 </histogram>
 
 <histogram name="Cookie.DomainSet.Subsampled" enum="Boolean"
-    expires_after="2025-06-08">
+    expires_after="2025-10-05">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -328,7 +328,7 @@
 </histogram>
 
 <histogram name="Cookie.Experimental.CookiesAllowedForUrlsUsage"
-    enum="CookiesAllowedForUrlsUsage" expires_after="2025-06-29">
+    enum="CookiesAllowedForUrlsUsage" expires_after="2025-10-05">
   <owner>dylancutler@google.com</owner>
   <owner>sandormajor@chromium.org</owner>
   <summary>
@@ -497,7 +497,7 @@
 </histogram>
 
 <histogram name="Cookie.FirstPartySets.{Context}.MostDelayedQueryDelta"
-    units="ms" expires_after="M140">
+    units="ms" expires_after="2025-10-05">
   <owner>cfredric@chromium.org</owner>
   <owner>kaustubhag@chromium.org</owner>
   <summary>
@@ -564,7 +564,7 @@
 </histogram>
 
 <histogram name="Cookie.IncludedRequestEffectiveSameSite.Subsampled"
-    enum="CookieEffectiveSameSite" expires_after="2025-07-13">
+    enum="CookieEffectiveSameSite" expires_after="2025-10-05">
   <owner>bingler@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <summary>
@@ -1163,7 +1163,7 @@
 </histogram>
 
 <histogram name="Cookie.TimeDatabaseMigrationToV24" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>wfh@chromium.org</owner>
   <owner>src/net/cookies/OWNERS</owner>
   <summary>
@@ -1179,7 +1179,7 @@
 </histogram>
 
 <histogram name="Cookie.TimeOpsBlockedDueToGlobalOp" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>morlovich@chromium.org</owner>
   <owner>src/net/cookies/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml
index 8fe2127..54051a8 100644
--- a/tools/metrics/histograms/metadata/cras/histograms.xml
+++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -123,7 +123,7 @@
 </variants>
 
 <histogram name="Cras.A2dp100msFailureOverStream" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -134,7 +134,7 @@
 </histogram>
 
 <histogram name="Cras.A2dp20msFailureOverStream" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>hychao@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -312,7 +312,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceOpenStatus.Input{Device}"
-    enum="CrasDeviceOpenStatus" expires_after="2025-08-03">
+    enum="CrasDeviceOpenStatus" expires_after="2025-10-05">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
@@ -322,7 +322,7 @@
 </histogram>
 
 <histogram name="Cras.DeviceOpenStatus.Output{Device}"
-    enum="CrasDeviceOpenStatus" expires_after="2025-08-03">
+    enum="CrasDeviceOpenStatus" expires_after="2025-10-05">
   <owner>yuhsuan@chromium.org</owner>
   <owner>chromeos-audio@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cros_ml/histograms.xml b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
index e5fe815..e7a0247 100644
--- a/tools/metrics/histograms/metadata/cros_ml/histograms.xml
+++ b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
@@ -246,7 +246,7 @@
 </histogram>
 
 <histogram name="MachineLearningService.PeakTotalMemoryKb" units="KB"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>alanlxl@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/cryptohome/histograms.xml b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
index d486f938..29fde4a0 100644
--- a/tools/metrics/histograms/metadata/cryptohome/histograms.xml
+++ b/tools/metrics/histograms/metadata/cryptohome/histograms.xml
@@ -494,7 +494,7 @@
 </histogram>
 
 <histogram name="Cryptohome.TimeToInitPkcs11" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>apronin@chromium.org</owner>
   <owner>cros-hwsec+uma@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
index 4a2a2ba..ca9a6fd6 100644
--- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
+++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -267,7 +267,7 @@
 </histogram>
 
 <histogram name="CustomTabs.DetachedResourceRequest.FinalStatus"
-    enum="NetErrorCodes" expires_after="2025-08-03">
+    enum="NetErrorCodes" expires_after="2025-10-05">
   <owner>lizeb@chromium.org</owner>
   <owner>cct-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/enterprise/histograms.xml b/tools/metrics/histograms/metadata/enterprise/histograms.xml
index e833977..21e0336 100644
--- a/tools/metrics/histograms/metadata/enterprise/histograms.xml
+++ b/tools/metrics/histograms/metadata/enterprise/histograms.xml
@@ -624,7 +624,7 @@
 </histogram>
 
 <histogram name="Enterprise.DeviceLocalAccountPolicyRefresh3"
-    enum="EnterprisePolicyRefresh" expires_after="2025-06-01">
+    enum="EnterprisePolicyRefresh" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -658,7 +658,7 @@
 </histogram>
 
 <histogram name="Enterprise.DevicePolicyInvalidations2"
-    enum="EnterprisePolicyInvalidations" expires_after="2025-08-03">
+    enum="EnterprisePolicyInvalidations" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -674,7 +674,7 @@
 </histogram>
 
 <histogram name="Enterprise.DevicePolicyRefresh3"
-    enum="EnterprisePolicyRefresh" expires_after="2025-08-03">
+    enum="EnterprisePolicyRefresh" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -758,7 +758,7 @@
 </histogram>
 
 <histogram name="Enterprise.DeviceRemoteCommand.Received"
-    enum="RemoteCommandReceivedStatus" expires_after="2025-08-03">
+    enum="RemoteCommandReceivedStatus" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -770,7 +770,7 @@
 </histogram>
 
 <histogram name="Enterprise.DeviceRemoteCommandInvalidations"
-    enum="EnterprisePolicyInvalidations" expires_after="2025-08-03">
+    enum="EnterprisePolicyInvalidations" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -1274,7 +1274,7 @@
 </histogram>
 
 <histogram name="Enterprise.Dlp.ActiveFileEventsCount" units="entries"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>accorsi@google.com</owner>
   <owner>chromeos-dlp@google.com</owner>
   <summary>
@@ -1315,7 +1315,7 @@
 </histogram>
 
 <histogram name="Enterprise.Dlp.ConfidentialContentsCount" units="entries"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>aidazolic@chromium.org</owner>
   <owner>chromeos-dlp@google.com</owner>
   <summary>
@@ -1978,7 +1978,7 @@
 </histogram>
 
 <histogram name="Enterprise.Enrollment" enum="EnterpriseEnrollmentType"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>sergiyb@chromium.org</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
@@ -1988,7 +1988,7 @@
 </histogram>
 
 <histogram name="Enterprise.EnrollmentAttestationBased"
-    enum="EnterpriseEnrollmentType" expires_after="2025-08-03">
+    enum="EnterpriseEnrollmentType" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>sergiyb@chromium.org</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
@@ -2012,7 +2012,7 @@
 </histogram>
 
 <histogram name="Enterprise.EnrollmentForcedAttestationBased"
-    enum="EnterpriseEnrollmentType" expires_after="2025-08-03">
+    enum="EnterpriseEnrollmentType" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>sergiyb@chromium.org</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
@@ -2034,7 +2034,7 @@
 </histogram>
 
 <histogram name="Enterprise.EnrollmentForcedInitialAttestationBased"
-    enum="EnterpriseEnrollmentType" expires_after="2025-08-03">
+    enum="EnterpriseEnrollmentType" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>sergiyb@chromium.org</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
@@ -2235,7 +2235,7 @@
 </histogram>
 
 <histogram name="Enterprise.ExtensibleEnterpriseSSO.Supported.Result"
-    enum="Boolean" expires_after="2025-08-01">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>ydago@chromium.org</owner>
   <owner>cec-growth@google.com</owner>
   <summary>
@@ -2245,7 +2245,7 @@
 </histogram>
 
 <histogram name="Enterprise.ExtensibleEnterpriseSSO.{Status}.Duration"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>ydago@chromium.org</owner>
   <owner>cec-growth@google.com</owner>
   <summary>
@@ -2680,7 +2680,7 @@
 </histogram>
 
 <histogram name="Enterprise.PolicyInvalidations"
-    enum="EnterprisePolicyInvalidations" expires_after="2025-08-03">
+    enum="EnterprisePolicyInvalidations" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
   <summary>
@@ -2712,7 +2712,7 @@
 </histogram>
 
 <histogram name="Enterprise.PolicyPromotionBannerDisplayed" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>austinzzr@chromium.org</owner>
   <owner>esalma@google.com</owner>
   <summary>
@@ -3620,7 +3620,7 @@
 </histogram>
 
 <histogram name="Enterprise.UserPolicyChromeOS.ChildUser.OAuthTokenError"
-    enum="GoogleServiceAuthError" expires_after="2025-08-03">
+    enum="GoogleServiceAuthError" expires_after="2025-10-05">
   <owner>agawronska@chromium.org</owner>
   <owner>michaelpg@chromium.org</owner>
   <summary>Failure reason for OAuth token fetch for child user.</summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml
index 96f282d..512a196 100644
--- a/tools/metrics/histograms/metadata/event/histograms.xml
+++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -603,7 +603,7 @@
 </histogram>
 
 <histogram name="Event.ScrollJank.MissedVsyncsPercentage.FixedWindow" units="%"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>woa-performance-team@google.com</owner>
   <summary>
@@ -681,7 +681,7 @@
 </histogram>
 
 <histogram name="Event.ScrollJank.MissedVsyncsPercentage.PerScroll{Length}"
-    units="%" expires_after="2025-08-03">
+    units="%" expires_after="2025-10-05">
   <owner>kartarsingh@google.com</owner>
   <owner>jonross@chromium.org</owner>
   <owner>woa-performance-team@google.com</owner>
@@ -762,7 +762,7 @@
 </histogram>
 
 <histogram name="Event.ScrollJank.MissedVsyncs{Operator}.FixedWindow"
-    units="counts" expires_after="2025-08-03">
+    units="counts" expires_after="2025-10-05">
   <owner>kartarsingh@google.com</owner>
   <owner>jonross@chromium.org</owner>
   <owner>woa-performance-team@google.com</owner>
@@ -811,7 +811,7 @@
 </histogram>
 
 <histogram name="Event.ScrollJank.MissedVsyncs{Operator}.PerScroll{Length}"
-    units="counts" expires_after="2025-08-03">
+    units="counts" expires_after="2025-10-05">
   <owner>kartarsingh@google.com</owner>
   <owner>jonross@chromium.org</owner>
   <owner>woa-performance-team@google.com</owner>
@@ -908,7 +908,7 @@
 </histogram>
 
 <histogram name="EventLatency.GestureScrollUpdate.Touchscreen.TotalLatency2"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1001,7 +1001,7 @@
 </histogram>
 
 <histogram name="EventLatency.{NonScrollPinchEventType}.TotalLatency"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>jonross@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml
index f6f1a058..5d67c26f 100644
--- a/tools/metrics/histograms/metadata/extensions/histograms.xml
+++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -740,7 +740,7 @@
 
 <histogram
     name="Extensions.ContentVerification.VerifyFailedOnFileTypeMV3.GoogleDocsOffline"
-    enum="VerifiedFileType" expires_after="2025-08-01">
+    enum="VerifiedFileType" expires_after="2025-10-05">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -2806,7 +2806,7 @@
 </histogram>
 
 <histogram name="Extensions.Functions.SynchronousExecutionTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -3921,7 +3921,7 @@
 </histogram>
 
 <histogram name="Extensions.ManifestVersionPopulationSplit.{ManifestLocation}"
-    enum="ManifestVersionPopulationSplit" expires_after="2025-08-01">
+    enum="ManifestVersionPopulationSplit" expires_after="2025-10-05">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
@@ -4083,7 +4083,7 @@
 
 <histogram
     name="Extensions.MV2Deprecation.MV2ExtensionState.{ManifestLocation}"
-    enum="MV2ExtensionState" expires_after="2025-08-03">
+    enum="MV2ExtensionState" expires_after="2025-10-05">
   <owner>rdevlin.cronin@chromium.org</owner>
   <owner>src/extensions/OWNERS</owner>
   <summary>
@@ -4405,6 +4405,16 @@
   </summary>
 </histogram>
 
+<histogram name="Extensions.Printing.UsesSupportedPrintScaling" enum="Boolean"
+    expires_after="2026-04-01">
+  <owner>nmuggli@google.com</owner>
+  <owner>msisov@igalia.com</owner>
+  <summary>
+    Records whether users of the chrome.printing extension API are using print
+    scaling values that are supported by the printer.
+  </summary>
+</histogram>
+
 <histogram name="Extensions.RuntimeHostPermissions.ExtensionHasWithheldHosts"
     enum="BooleanHasWithheldHosts" expires_after="2023-07-07">
   <owner>rdevlin.cronin@chromium.org</owner>
@@ -5085,7 +5095,7 @@
 </histogram>
 
 <histogram name="Extensions.Toolbar.ExtensionsActivatedFromRequestAccessButton"
-    units="Extension Count" expires_after="2025-08-03">
+    units="Extension Count" expires_after="2025-10-05">
   <owner>emiliapaz@chromium.org</owner>
   <owner>extensions-core@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/fastpair/histograms.xml b/tools/metrics/histograms/metadata/fastpair/histograms.xml
index 45dac49..c9b072b 100644
--- a/tools/metrics/histograms/metadata/fastpair/histograms.xml
+++ b/tools/metrics/histograms/metadata/fastpair/histograms.xml
@@ -36,7 +36,7 @@
 </histogram>
 
 <histogram name="FastPair.GattConnection" enum="FastPairGattConnectionSteps"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
@@ -75,7 +75,7 @@
 </histogram>
 
 <histogram name="FastPair.Handshake.EffectiveSuccessRate" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
@@ -88,7 +88,7 @@
 </histogram>
 
 <histogram name="FastPair.InitialPairing"
-    enum="FastPairInitialSuccessFunnelEvent" expires_after="2025-08-03">
+    enum="FastPairInitialSuccessFunnelEvent" expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
@@ -155,7 +155,7 @@
 </histogram>
 
 <histogram name="FastPair.RetroactivePairing"
-    enum="FastPairRetroactiveSuccessFunnelEvent" expires_after="2025-08-03">
+    enum="FastPairRetroactiveSuccessFunnelEvent" expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
@@ -170,7 +170,7 @@
 </histogram>
 
 <histogram name="FastPair.SubsequentPairing"
-    enum="FastPairSubsequentSuccessFunnelEvent" expires_after="2025-08-03">
+    enum="FastPairSubsequentSuccessFunnelEvent" expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
@@ -183,7 +183,7 @@
 </histogram>
 
 <histogram name="FastPair.{FastPairPairingProtocol}.Pairing"
-    enum="FastPairProtocolPairingSteps" expires_after="2025-08-03">
+    enum="FastPairProtocolPairingSteps" expires_after="2025-10-05">
   <owner>jackshira@google.com</owner>
   <owner>dclasson@google.com</owner>
   <owner>brandosocarras@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/fingerprint/histograms.xml b/tools/metrics/histograms/metadata/fingerprint/histograms.xml
index 6382fbc7..38e861e 100644
--- a/tools/metrics/histograms/metadata/fingerprint/histograms.xml
+++ b/tools/metrics/histograms/metadata/fingerprint/histograms.xml
@@ -116,7 +116,7 @@
 </histogram>
 
 <histogram name="Fingerprint.FingerprintScanDone" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>emaamari@google.com</owner>
   <owner>chromeos-commercial-identity@google.com</owner>
   <owner>chromeos-fingerprint@google.com</owner>
@@ -242,7 +242,7 @@
 </histogram>
 
 <histogram name="Fingerprint.SensorError.NoIrq" enum="BooleanError"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>fsammoura@google.com</owner>
   <owner>chromeos-fingerprint@google.com</owner>
   <summary>
@@ -252,7 +252,7 @@
 </histogram>
 
 <histogram name="Fingerprint.SensorError.SpiCommunication" enum="BooleanError"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>fsammoura@google.com</owner>
   <owner>chromeos-fingerprint@google.com</owner>
   <summary>
@@ -286,7 +286,7 @@
 </histogram>
 
 <histogram name="Fingerprint.SetContext.Success" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>fsammoura@google.com</owner>
   <owner>chromeos-fingerprint@google.com</owner>
   <summary>Whether setting FPMCU mode succeeded.</summary>
@@ -522,7 +522,7 @@
 </histogram>
 
 <histogram name="Fingerprint.{ContextFunction}" enum="FingerprintSensorMode"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>tomhughes@chromium.org</owner>
   <owner>chromeos-fingerprint@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/fingerprinting_protection/histograms.xml b/tools/metrics/histograms/metadata/fingerprinting_protection/histograms.xml
index d5b4e83..0588446 100644
--- a/tools/metrics/histograms/metadata/fingerprinting_protection/histograms.xml
+++ b/tools/metrics/histograms/metadata/fingerprinting_protection/histograms.xml
@@ -247,7 +247,7 @@
 </histogram>
 
 <histogram name="FingerprintingProtection.PageLoad.ActivationLevel"
-    enum="FingerprintingProtectionActivationLevel" expires_after="2025-06-29">
+    enum="FingerprintingProtectionActivationLevel" expires_after="2025-10-05">
   <owner>thesalsa@google.com</owner>
   <owner>trishalfonso@google.com</owner>
   <owner>rizvis@google.com</owner>
@@ -262,7 +262,7 @@
 
 <histogram
     name="FingerprintingProtection.PageLoad.NumSubresourceLoads.Disallowed"
-    units="resource loads" expires_after="2025-08-05">
+    units="resource loads" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
@@ -292,7 +292,7 @@
 
 <histogram
     name="FingerprintingProtection.PageLoad.NumSubresourceLoads.Evaluated"
-    units="resource loads" expires_after="2025-08-05">
+    units="resource loads" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
@@ -323,7 +323,7 @@
 
 <histogram
     name="FingerprintingProtection.PageLoad.NumSubresourceLoads.MatchedRules"
-    units="resource loads" expires_after="2025-08-05">
+    units="resource loads" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
@@ -352,7 +352,7 @@
 </histogram>
 
 <histogram name="FingerprintingProtection.PageLoad.NumSubresourceLoads.Total"
-    units="resource loads" expires_after="2025-08-05">
+    units="resource loads" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
@@ -443,7 +443,7 @@
 
 <histogram
     name="FingerprintingProtection.PageLoad.SubresourceEvaluation.TotalCPUDuration"
-    units="microseconds" expires_after="2025-08-05">
+    units="microseconds" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
@@ -460,7 +460,7 @@
 
 <histogram
     name="FingerprintingProtection.PageLoad.SubresourceEvaluation.TotalWallDuration"
-    units="microseconds" expires_after="2025-08-05">
+    units="microseconds" expires_after="2025-10-05">
   <owner>rizvis@google.com</owner>
   <owner>thesalsa@google.com</owner>
   <owner>tanub@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml
index dd18741..60bcfa7 100644
--- a/tools/metrics/histograms/metadata/gpu/histograms.xml
+++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -1117,7 +1117,7 @@
 </histogram>
 
 <histogram name="GPU.OutputSurface.InsertRenderPassRecording" enum="Boolean"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>kylechar@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
@@ -1757,7 +1757,7 @@
 </histogram>
 
 <histogram name="Viz.CreateFallbackImageResult"
-    enum="CreateFallbackImageResult" expires_after="2025-08-01">
+    enum="CreateFallbackImageResult" expires_after="2025-10-05">
   <owner>kylechar@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml
index cd10712..1e5ab73 100644
--- a/tools/metrics/histograms/metadata/history/histograms.xml
+++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1771,7 +1771,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseCachedPassageHitCount"
-    units="passages" expires_after="2025-07-31">
+    units="passages" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -1782,7 +1782,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseCachedPassageRatio" units="%"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -1796,7 +1796,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseCachedPassageTryCount"
-    units="passages" expires_after="2025-07-31">
+    units="passages" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -1819,7 +1819,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseInitialized" enum="Boolean"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -1897,7 +1897,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseStoredAsciiPassages"
-    units="passages" expires_after="2025-07-31">
+    units="passages" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -1911,7 +1911,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseStoredNonAsciiPassageRatio"
-    units="%" expires_after="2025-07-31">
+    units="%" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -1925,7 +1925,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.DatabaseStoredNonAsciiPassages"
-    units="passages" expires_after="2025-07-31">
+    units="passages" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -1939,7 +1939,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.CacheHit" enum="Boolean"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -1951,7 +1951,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.CpuUsage2" units="1/100 %"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -1963,7 +1963,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.CpuUsage2.NotRunning"
-    units="1/100 %" expires_after="2025-07-31">
+    units="1/100 %" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <owner>orinj@chromium.org</owner>
@@ -1976,7 +1976,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.CpuUsage2.Running" units="1/100 %"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <owner>orinj@chromium.org</owner>
@@ -1989,7 +1989,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.CpuUsage2.RunningPartial"
-    units="1/100 %" expires_after="2025-07-31">
+    units="1/100 %" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <owner>orinj@chromium.org</owner>
@@ -2002,7 +2002,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.EmbeddingsGenerationSucceeded"
-    enum="Boolean" expires_after="2025-07-31">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2012,7 +2012,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.EmbeddingsModelLoadDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2022,7 +2022,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.EmbeddingsModelLoadSucceeded"
-    enum="Boolean" expires_after="2025-07-31">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2042,7 +2042,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.ModelInfoStatus"
-    enum="EmbeddingsModelInfoStatus" expires_after="2025-07-31">
+    enum="EmbeddingsModelInfoStatus" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2054,7 +2054,7 @@
 
 <histogram
     name="History.Embeddings.Embedder.PassageEmbeddingsGenerationDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2065,7 +2065,7 @@
 
 <histogram
     name="History.Embeddings.Embedder.PassageEmbeddingsGenerationThreadDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2076,7 +2076,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.PassageTokenCount" units="tokens"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2086,7 +2086,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.QueryEmbeddingsGenerationDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2098,7 +2098,7 @@
 
 <histogram
     name="History.Embeddings.Embedder.QueryEmbeddingsGenerationThreadDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2109,7 +2109,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.SentencePieceModelLoadDuration"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2129,7 +2129,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Embedder.TokenizationDuration" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2149,7 +2149,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.EmbeddingScoreSufficient" enum="Boolean"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2163,7 +2163,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.ExtractionCancelled"
-    enum="EmbeddingsExtractionCancelled" expires_after="2025-07-31">
+    enum="EmbeddingsExtractionCancelled" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>sophiechang@chromium.org</owner>
   <summary>
@@ -2185,7 +2185,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.NumMatchedUrlsVisible" units="counts"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2207,7 +2207,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.NumUrlsDiscardedForLowScore" units="counts"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>orinj@chromium.org</owner>
   <summary>
@@ -2245,7 +2245,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Passages.ExtractionTime" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2257,7 +2257,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Passages.PassageCount" units="passages"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2277,7 +2277,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Passages.TotalTextSize" units="bytes"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2308,7 +2308,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.QueryEmbeddingSucceeded" enum="Boolean"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>zekunjiang@google.com</owner>
   <summary>
@@ -2337,7 +2337,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.ScheduledJobDuration{PassagePriority}"
-    units="ms" expires_after="2025-07-31">
+    units="ms" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2381,7 +2381,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.Duration" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2391,7 +2391,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.EmbeddingCount" units="embeddings"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2415,7 +2415,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.PassageScanningTime" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2427,7 +2427,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.ScoringTime" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2438,7 +2438,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.SkippedNonAsciiPassageCount"
-    units="passages" expires_after="2025-07-31">
+    units="passages" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2449,7 +2449,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.TotalSearchTime" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2459,7 +2459,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.Search.UrlCount" units="urls"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
@@ -2469,7 +2469,7 @@
 </histogram>
 
 <histogram name="History.Embeddings.UserActions{UiSurface}"
-    enum="EmbeddingsUserActions" expires_after="2025-07-31">
+    enum="EmbeddingsUserActions" expires_after="2025-10-05">
   <owner>orinj@chromium.org</owner>
   <owner>src/components/history_embeddings/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/holding_space/histograms.xml b/tools/metrics/histograms/metadata/holding_space/histograms.xml
index 59ce430..26b3b189 100644
--- a/tools/metrics/histograms/metadata/holding_space/histograms.xml
+++ b/tools/metrics/histograms/metadata/holding_space/histograms.xml
@@ -130,7 +130,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Item.Action.All" enum="HoldingSpaceItemAction"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -190,7 +190,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Item.Action.{action}" enum="HoldingSpaceItemType"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -212,7 +212,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Item.Action.{action}.FileSystemType"
-    enum="HoldingSpaceFileSystemType" expires_after="2025-08-01">
+    enum="HoldingSpaceFileSystemType" expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -223,7 +223,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Item.TotalCountV2.{type}" units="items"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -236,7 +236,7 @@
 
 <histogram
     name="HoldingSpace.Item.TotalCountV2.{type}.FileSystemType.{fs_type}"
-    units="items" expires_after="2025-08-01">
+    units="items" expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -250,7 +250,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Item.VisibleCount.{type}" units="items"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -262,7 +262,7 @@
 
 <histogram
     name="HoldingSpace.Item.VisibleCount.{type}.FileSystemType.{fs_type}"
-    units="items" expires_after="2025-08-01">
+    units="items" expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
@@ -285,7 +285,7 @@
 </histogram>
 
 <histogram name="HoldingSpace.Suggestions.Action.All"
-    enum="HoldingSpaceSuggestionsAction" expires_after="2025-08-01">
+    enum="HoldingSpaceSuggestionsAction" expires_after="2025-10-05">
   <owner>dmblack@google.com</owner>
   <owner>alexandrahill@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/image/histograms.xml b/tools/metrics/histograms/metadata/image/histograms.xml
index 88c3fde..b74b0b9 100644
--- a/tools/metrics/histograms/metadata/image/histograms.xml
+++ b/tools/metrics/histograms/metadata/image/histograms.xml
@@ -107,7 +107,7 @@
 </variants>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.CacheHit"
-    enum="BooleanCacheHit" expires_after="2025-07-31">
+    enum="BooleanCacheHit" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -123,7 +123,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.ClientResult"
-    enum="ImageAnnotationServiceClientResult" expires_after="2025-07-31">
+    enum="ImageAnnotationServiceClientResult" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -138,7 +138,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.DescFailure"
-    enum="DescFailureReason" expires_after="2025-07-31">
+    enum="DescFailureReason" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -150,7 +150,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.DescType"
-    enum="ImageAnnotationServiceDescType" expires_after="2025-07-31">
+    enum="ImageAnnotationServiceDescType" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -165,7 +165,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.EncodedJpegSizeKB"
-    units="KB" expires_after="2025-07-31">
+    units="KB" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -265,7 +265,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.ServerHttpResponseCode"
-    enum="HttpResponseCode" expires_after="2025-07-31">
+    enum="HttpResponseCode" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -310,7 +310,7 @@
 </histogram>
 
 <histogram name="ImageAnnotationService.AccessibilityV1.ServerRequestSizeKB"
-    units="KB" expires_after="2025-07-31">
+    units="KB" expires_after="2025-10-05">
   <owner>dtseng@chromium.org</owner>
   <owner>amoylan@chromium.org</owner>
   <owner>mschillaci@google.com</owner>
@@ -529,7 +529,7 @@
 
 <histogram
     name="ImageFetcher.ImageLoadFromNetworkAfterCacheHit{ImageFetcherClients}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>fgorski@chromium.org</owner>
   <owner>wylieb@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/installer/histograms.xml b/tools/metrics/histograms/metadata/installer/histograms.xml
index f8d3b52..8afaa577 100644
--- a/tools/metrics/histograms/metadata/installer/histograms.xml
+++ b/tools/metrics/histograms/metadata/installer/histograms.xml
@@ -202,7 +202,7 @@
 </histogram>
 
 <histogram name="Setup.Install.LzmaUnPackStatus_{UnPackConsumer}"
-    enum="UnPackStatus" expires_after="2025-08-03">
+    enum="UnPackStatus" expires_after="2025-10-05">
   <owner>zmin@chromium.org</owner>
   <owner>grt@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/invalidation/histograms.xml b/tools/metrics/histograms/metadata/invalidation/histograms.xml
index 9290b66..bbf4c2d 100644
--- a/tools/metrics/histograms/metadata/invalidation/histograms.xml
+++ b/tools/metrics/histograms/metadata/invalidation/histograms.xml
@@ -25,7 +25,7 @@
 
 <histogram
     name="FCMInvalidations.DirectInvalidation.RegistrationTokenRetrievalStatus"
-    enum="InstanceIDResult" expires_after="2025-05-25">
+    enum="InstanceIDResult" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>rbock@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
@@ -44,7 +44,7 @@
 </histogram>
 
 <histogram name="FCMInvalidations.FCMMessageStatus{FCMInvalidationSenders}"
-    enum="FCMInvalidationMessageStatus" expires_after="2025-06-08">
+    enum="FCMInvalidationMessageStatus" expires_after="2025-10-05">
   <owner>asumaneev@google.com</owner>
   <owner>rbock@google.com</owner>
   <owner>chromeos-commercial-remote-management@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index 9f3a253a..b88d2ec 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -1066,7 +1066,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoAllTabs"
-    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-10-05">
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1076,7 +1076,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoMadeForIOS"
-    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-10-05">
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1086,7 +1086,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoStaySafe"
-    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2025-10-05">
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1096,7 +1096,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.DaysSinceLastPromoInteraction"
-    units="count" expires_after="2025-08-05">
+    units="count" expires_after="2025-10-05">
   <owner>gayane@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1117,7 +1117,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.GenericPromoDisplayCount"
-    units="count" expires_after="2025-08-05">
+    units="count" expires_after="2025-10-05">
   <owner>gayane@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1128,7 +1128,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.NonModal.OnScreenTime" units="ms"
-    expires_after="2025-08-05">
+    expires_after="2025-10-05">
   <owner>rkgibson@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1137,7 +1137,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.NonModal.{Impression}"
-    enum="IOSDefaultBrowserPromoNonModalAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserPromoNonModalAction" expires_after="2025-10-05">
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1159,7 +1159,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.NonModal.{PromoType}"
-    enum="IOSDefaultBrowserPromoNonModalAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserPromoNonModalAction" expires_after="2025-10-05">
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1186,7 +1186,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserPromo.Shown"
-    enum="IOSDefaultBrowserPromoType" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserPromoType" expires_after="2025-10-05">
   <owner>gayane@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>The default browser promo type shown to the user.</summary>
@@ -1250,7 +1250,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserSettingsPageUsage{Source}"
-    enum="IOSDefaultBrowserSettingsPageUsage" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserSettingsPageUsage" expires_after="2025-10-05">
   <owner>gayane@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1275,7 +1275,7 @@
 </histogram>
 
 <histogram name="IOS.DefaultBrowserVideoPromo.Fullscreen"
-    enum="IOSDefaultBrowserVideoPromoAction" expires_after="2025-08-05">
+    enum="IOSDefaultBrowserVideoPromoAction" expires_after="2025-10-05">
   <owner>cheickcisse@google.com</owner>
   <owner>sebsg@chromium.org</owner>
   <owner>bling-mony-pod@google.com</owner>
@@ -1469,7 +1469,7 @@
 </histogram>
 
 <histogram name="IOS.Desktop.{PromoType}.Shown"
-    enum="DesktopIOSPromoImpression" expires_after="2025-08-05">
+    enum="DesktopIOSPromoImpression" expires_after="2025-10-05">
   <owner>nicolasmacbeth@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -1486,7 +1486,7 @@
 </histogram>
 
 <histogram name="IOS.Desktop.{PromoType}.{Impression}.Action"
-    enum="DesktopIOSPromoAction" expires_after="2025-08-05">
+    enum="DesktopIOSPromoAction" expires_after="2025-10-05">
   <owner>nicolasmacbeth@google.com</owner>
   <owner>bling-mony-pod@google.com</owner>
   <summary>
@@ -2422,7 +2422,7 @@
 </histogram>
 
 <histogram name="IOS.JavaScript.ScriptExecutionFailed" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>michaeldo@google.com</owner>
   <owner>bling-fundamentals@google.com</owner>
   <summary>
@@ -3757,7 +3757,7 @@
 </histogram>
 
 <histogram name="IOS.PartialTranslate.Outcome" enum="PartialTranslateOutcome"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>olivierrobin@chromium.org</owner>
   <owner>bling-squid-squad@google.com</owner>
   <summary>The outcome of the partial translate feature.</summary>
@@ -5184,7 +5184,7 @@
   </summary>
 </histogram>
 
-<histogram name="IOS.Snapshots.CacheSize" units="KB" expires_after="2025-08-04">
+<histogram name="IOS.Snapshots.CacheSize" units="KB" expires_after="2025-10-05">
   <owner>asamidoi@chromium.org</owner>
   <owner>edchin@chromium.org</owner>
   <summary>
@@ -5351,7 +5351,7 @@
 </histogram>
 
 <histogram name="IOS.Start.Impression" enum="IOSNTPImpressionType"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>thegreenfrog@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
@@ -5488,7 +5488,7 @@
 </histogram>
 
 <histogram name="IOS.TabSwitcher.DragDropGroups"
-    enum="IOSTabSwitcherDragDropTabs" expires_after="2025-07-09">
+    enum="IOSTabSwitcherDragDropTabs" expires_after="2025-10-05">
   <owner>ewannpv@chromium.org</owner>
   <owner>chromeleon@google.com</owner>
   <summary>
@@ -5778,7 +5778,7 @@
 </histogram>
 
 <histogram name="IOS.Variations.FirstRun.SeedApplicationStage"
-    enum="VariationsFirstRunSeedApplicationStage" expires_after="2025-08-03">
+    enum="VariationsFirstRunSeedApplicationStage" expires_after="2025-10-05">
   <owner>ginnyhuang@chromium.org</owner>
   <owner>huitingyu@google.com</owner>
   <owner>bling-get-set-up@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/kerberos/histograms.xml b/tools/metrics/histograms/metadata/kerberos/histograms.xml
index 77423fcf..fdc7f77 100644
--- a/tools/metrics/histograms/metadata/kerberos/histograms.xml
+++ b/tools/metrics/histograms/metadata/kerberos/histograms.xml
@@ -23,7 +23,7 @@
 <histograms>
 
 <histogram name="Kerberos.AcquireKerberosTgtTime" units="ms"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -33,7 +33,7 @@
 </histogram>
 
 <histogram name="Kerberos.DailyActiveUsers" enum="KerberosUserType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -45,7 +45,7 @@
 </histogram>
 
 <histogram name="Kerberos.EncryptionTypesAcquireKerberosTgt"
-    enum="KerberosEncryptionTypes" expires_after="M140">
+    enum="KerberosEncryptionTypes" expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -56,7 +56,7 @@
 </histogram>
 
 <histogram name="Kerberos.NumberOfAccounts.Managed" units="units"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -67,7 +67,7 @@
 </histogram>
 
 <histogram name="Kerberos.NumberOfAccounts.RememberedPassword" units="units"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -79,7 +79,7 @@
 </histogram>
 
 <histogram name="Kerberos.NumberOfAccounts.Total" units="units"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -89,7 +89,7 @@
 </histogram>
 
 <histogram name="Kerberos.NumberOfAccounts.Unmanaged" units="units"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -100,7 +100,7 @@
 </histogram>
 
 <histogram name="Kerberos.NumberOfAccounts.UseLoginPassword" units="units"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -112,7 +112,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.AcquireKerberosTgt" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -122,7 +122,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.AddAccount" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -132,7 +132,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.ClearAccounts" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -143,7 +143,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.GetKerberosFiles" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -154,7 +154,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.ListAccounts" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -164,7 +164,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.RemoveAccount" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -174,7 +174,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.SetConfig" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -184,7 +184,7 @@
 </histogram>
 
 <histogram name="Kerberos.Result.ValidateConfig" enum="KerberosErrorType"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
@@ -195,7 +195,7 @@
 </histogram>
 
 <histogram name="Kerberos.ValidateConfigErrorCode"
-    enum="KerberosConfigErrorCode" expires_after="M140">
+    enum="KerberosConfigErrorCode" expires_after="2025-10-05">
   <owner>fsandrade@chromium.org</owner>
   <owner>src/chrome/browser/ash/kerberos/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/lens/histograms.xml b/tools/metrics/histograms/metadata/lens/histograms.xml
index c39a210..e049bcaa 100644
--- a/tools/metrics/histograms/metadata/lens/histograms.xml
+++ b/tools/metrics/histograms/metadata/lens/histograms.xml
@@ -259,7 +259,7 @@
 
 <histogram
     name="Lens.Overlay.ContextualSearchBox.ByPageContentType.{PageContentType}.FocusedInSession"
-    enum="Boolean" expires_after="2025-08-03">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>niharm@google.com</owner>
   <owner>lens-chrome@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/mac/histograms.xml b/tools/metrics/histograms/metadata/mac/histograms.xml
index 91ceb6f1..2ee7509 100644
--- a/tools/metrics/histograms/metadata/mac/histograms.xml
+++ b/tools/metrics/histograms/metadata/mac/histograms.xml
@@ -33,7 +33,7 @@
 </histogram>
 
 <histogram name="Mac.AppCodeSignCloneCount" units="count"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>bur@google.com</owner>
   <owner>src/ui/base/cocoa/OWNERS</owner>
   <summary>
@@ -74,7 +74,7 @@
 </histogram>
 
 <histogram name="Mac.AppHardLinkError" enum="MacErrno"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>bur@google.com</owner>
   <owner>src/ui/base/cocoa/OWNERS</owner>
   <summary>
@@ -157,7 +157,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.CurrentProcessValid"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -167,7 +167,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.FallbackValidationCategory.Result"
-    enum="CodeSigningOSStatus" expires_after="2025-08-03">
+    enum="CodeSigningOSStatus" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -189,7 +189,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.Timing.{Operation}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -206,7 +206,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.ValidationCategory.Result"
-    enum="MacErrno" expires_after="2025-08-03">
+    enum="MacErrno" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -217,7 +217,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.ValidationRequired"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -228,7 +228,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.ValidationResult"
-    enum="CodeSigningOSStatus" expires_after="2025-08-03">
+    enum="CodeSigningOSStatus" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
@@ -238,7 +238,7 @@
 </histogram>
 
 <histogram name="Mac.ProcessRequirement.{Field}.HasExpectedValue"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>markrowe@chromium.org</owner>
   <owner>src/base/mac/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/magic_stack/histograms.xml b/tools/metrics/histograms/metadata/magic_stack/histograms.xml
index b6af68a..36b81110e 100644
--- a/tools/metrics/histograms/metadata/magic_stack/histograms.xml
+++ b/tools/metrics/histograms/metadata/magic_stack/histograms.xml
@@ -240,7 +240,7 @@
 
 <histogram
     name="MagicStack.Clank.NewTabPage.{HostSurfaceState}.Module.{ModuleType}.Impression"
-    enum="ModulePosition" expires_after="2025-08-03">
+    enum="ModulePosition" expires_after="2025-10-05">
   <owner>hanxi@chromium.org</owner>
   <owner>xinyiji@chromium.org</owner>
   <summary>
@@ -255,7 +255,7 @@
 
 <histogram
     name="MagicStack.Clank.NewTabPage.{HostSurfaceState}.Module.{ModuleType}.ImpressionCountBeforeInteraction"
-    units="count" expires_after="2025-08-03">
+    units="count" expires_after="2025-10-05">
   <owner>hanxi@chromium.org</owner>
   <owner>xinyiji@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml
index bd502fd..270bdcfe 100644
--- a/tools/metrics/histograms/metadata/media/histograms.xml
+++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -491,7 +491,7 @@
 </histogram>
 
 <histogram name="Media.Android.MediaPlayerSuccess" enum="MediaPlayerExitStatus"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>tguilbert@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>Android: Whether MediaPlayer exited without errors.</summary>
@@ -1407,7 +1407,7 @@
 </histogram>
 
 <histogram name="Media.Audio.{Type}.Glitches2" units="glitches"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>olka@chromium.org</owner>
   <owner>saza@chromium.org</owner>
   <owner>webrtc-audio-uma@google.com</owner>
@@ -4071,7 +4071,7 @@
 </histogram>
 
 <histogram name="Media.MediaDevices.EnumerateDevices.Latency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toprice@chromium.org</owner>
   <owner>agpalak@chromium.org</owner>
   <summary>
@@ -4083,7 +4083,7 @@
 </histogram>
 
 <histogram name="Media.MediaDevices.EnumerateDevices.Result"
-    enum="EnumerateDevicesResult" expires_after="2025-08-03">
+    enum="EnumerateDevicesResult" expires_after="2025-10-05">
   <owner>toprice@chromium.org</owner>
   <owner>agpalak@chromium.org</owner>
   <summary>
@@ -4153,7 +4153,7 @@
 </histogram>
 
 <histogram name="Media.MediaDevices.GetUserMedia.Latency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toprice@chromium.org</owner>
   <owner>agpalak@chromium.org</owner>
   <owner>video-cmi-apis@google.com</owner>
@@ -5586,7 +5586,7 @@
 </histogram>
 
 <histogram name="Media.Session.PictureInPicture.TotalTimeForSession" units="ms"
-    expires_after="2025-07-13">
+    expires_after="2025-10-05">
   <owner>bkeen@google.com</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -6080,7 +6080,7 @@
 </histogram>
 
 <histogram name="Media.Video.Roughness{VideoFrameRateRange}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>eugene@chromium.org</owner>
   <owner>media-dev-uma@chromium.org</owner>
   <summary>
@@ -6345,7 +6345,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Mac.ValidColorSpaceAfterTransform"
-    enum="Boolean" expires_after="2025-08-03">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>kron@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -6516,7 +6516,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.CapturePixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2025-05-19">
+    enum="VideoPixelFormatUnion" expires_after="2026-05-19">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -6526,7 +6526,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.InternalPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2025-06-04">
+    enum="VideoPixelFormatUnion" expires_after="2026-06-04">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -6547,7 +6547,7 @@
 </histogram>
 
 <histogram name="Media.VideoCapture.Win.Device.RequestedPixelFormat"
-    enum="VideoPixelFormatUnion" expires_after="2025-05-18">
+    enum="VideoPixelFormatUnion" expires_after="2026-05-18">
   <owner>ilnik@google.com</owner>
   <owner>video-cmi-mpp@google.com</owner>
   <summary>
@@ -7426,7 +7426,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Cast.Channel.ConnectResult" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>muyaoxu@google.com</owner>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
@@ -7573,14 +7573,14 @@
 </histogram>
 
 <histogram name="MediaRouter.CastStreaming.Session.Length.Screen" units="ms"
-    expires_after="2025-08-05">
+    expires_after="2025-10-05">
   <owner>muyaoxu@google.com</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>Total length of a Cast Streaming Screen mirror session.</summary>
 </histogram>
 
 <histogram name="MediaRouter.CastStreaming.Session.Length.Tab" units="ms"
-    expires_after="2025-08-05">
+    expires_after="2025-10-05">
   <owner>muyaoxu@google.com</owner>
   <owner>openscreen-eng@google.com</owner>
   <summary>
@@ -7773,7 +7773,7 @@
 </histogram>
 
 <histogram name="MediaRouter.Provider.CreateRoute.Result{MediaRouteProvider}"
-    enum="MediaRouteProviderResult" expires_after="2025-08-05">
+    enum="MediaRouteProviderResult" expires_after="2025-10-05">
   <owner>muyaoxu@google.com</owner>
   <owner>mfoltz@chromium.org</owner>
   <owner>openscreen-eng@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml
index 3c5575a..582e1c5e 100644
--- a/tools/metrics/histograms/metadata/memory/histograms.xml
+++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -2255,7 +2255,7 @@
 </histogram>
 
 <histogram name="Memory.ParkableString.Compression.Latency"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>lizeb@chromium.org</owner>
   <owner>thiabaud@google.com</owner>
   <summary>
@@ -2267,7 +2267,7 @@
 </histogram>
 
 <histogram name="Memory.ParkableString.Compression.SizeKb" units="KB"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lizeb@chromium.org</owner>
   <owner>thiabaud@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml
index 1e4d743..4a215d9 100644
--- a/tools/metrics/histograms/metadata/navigation/histograms.xml
+++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -611,7 +611,7 @@
 </histogram>
 
 <histogram name="BackForwardCache.Restore.NavigationToFirstPaint" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>sreejakshetty@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -1073,7 +1073,7 @@
 </histogram>
 
 <histogram name="Navigation.GestureTransition.AnimationAbortReason"
-    enum="AnimationAbortReason" expires_after="M140">
+    enum="AnimationAbortReason" expires_after="2025-10-05">
   <owner>liuwilliam@google.com</owner>
   <owner>baranerf@google.com</owner>
   <owner>chrome-seamless-core@google.com</owner>
@@ -1084,7 +1084,7 @@
 </histogram>
 
 <histogram name="Navigation.GestureTransition.CacheHitOrMissReason"
-    enum="NavigationTransitionCacheHitOrMissReason" expires_after="M140">
+    enum="NavigationTransitionCacheHitOrMissReason" expires_after="2025-10-05">
   <owner>liuwilliam@google.com</owner>
   <owner>baranerf@google.com</owner>
   <owner>chrome-seamless-core@google.com</owner>
@@ -1108,7 +1108,7 @@
 
 <histogram
     name="Navigation.GestureTransition.IgnoredInputCount.{Reason}.{Position}"
-    units="count" expires_after="M140">
+    units="count" expires_after="2025-10-05">
   <owner>liuwilliam@google.com</owner>
   <owner>baranerf@google.com</owner>
   <owner>chrome-seamless-core@google.com</owner>
@@ -1128,7 +1128,7 @@
 </histogram>
 
 <histogram name="Navigation.GestureTransition.ScreenshotCacheSize" units="MB"
-    expires_after="M140">
+    expires_after="2025-10-05">
   <owner>liuwilliam@google.com</owner>
   <owner>baranerf@google.com</owner>
   <owner>chrome-seamless-core@google.com</owner>
@@ -1608,7 +1608,7 @@
 
 <histogram
     name="Navigation.OnBeforeUnloadOverheadTime.NoBeforeUnloadHandlerRegistered"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>hayato@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1876,7 +1876,7 @@
 
 <histogram
     name="Navigation.Prerender.NoVarySearchCommitDeferTime.{NVSTriggerType}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>lingqi@chromium.org</owner>
   <owner>chrome-prerendering@chromium.org</owner>
   <summary>
@@ -2307,7 +2307,7 @@
 </histogram>
 
 <histogram name="Navigation.StartToCommit{NavigationProcessType}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>nasko@chromium.org</owner>
   <owner>csharrison@chromium.org</owner>
   <summary>
@@ -2353,7 +2353,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleCount" units="throttles"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2364,7 +2364,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleDeferredEvent"
-    enum="NavigationThrottleEvent" expires_after="2025-08-03">
+    enum="NavigationThrottleEvent" expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2375,7 +2375,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleDeferTime.{Event}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>cduvall@chromium.org</owner>
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
@@ -2390,7 +2390,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleEventDurationTime.{Event}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2403,7 +2403,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleEventExecutionTime.{Event}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2415,7 +2415,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleExecutionTime.{Event}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>cduvall@chromium.org</owner>
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
@@ -2430,7 +2430,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleTotalDeferCount{Condition}"
-    units="throttles" expires_after="2025-08-03">
+    units="throttles" expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2442,7 +2442,7 @@
 </histogram>
 
 <histogram name="Navigation.ThrottleTotalDeferTime{Condition}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>toyoshim@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -2959,7 +2959,7 @@
 </histogram>
 
 <histogram name="Navigation{Initiator}.DuplicateNavIsUnderThreshold"
-    enum="Boolean" expires_after="2025-08-03">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>rakina@chromium.org</owner>
   <owner>chrome-navigation@google.com</owner>
   <summary>
@@ -2976,7 +2976,7 @@
 </histogram>
 
 <histogram name="Navigation{Initiator}.DuplicateNavStartTimeDiff" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>rakina@chromium.org</owner>
   <owner>bfcache-dev@chromium.org</owner>
   <summary>
@@ -3360,7 +3360,7 @@
 </histogram>
 
 <histogram name="Prerender.FinalStatus" enum="PrerenderFinalStatus"
-    expires_after="2025-07-13">
+    expires_after="2025-10-05">
   <owner>ryansturm@chromium.org</owner>
   <owner>tbansal@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index d24c5225..b313a4c5 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -190,7 +190,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMDuration.{Operation}{SignatureAlgorithm}" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>kristianm@chromium.org</owner>
   <owner>wfh@chromium.org</owner>
   <summary>
@@ -251,7 +251,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMOperation.Virtual.{Operation}{SignatureAlgorithm}"
-    enum="BooleanSuccess" expires_after="2025-08-01">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>kristianm@chromium.org</owner>
   <owner>agl@chromium.org</owner>
   <summary>
@@ -273,7 +273,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMOperation.Win.WrappedKeyCreation.Error"
-    enum="Win32TpmErrorCodes" expires_after="2025-08-01">
+    enum="Win32TpmErrorCodes" expires_after="2025-10-05">
   <owner>seblalancette@chromium.org</owner>
   <owner>kristianm@chromium.org</owner>
   <owner>src/crypto/OWNERS</owner>
@@ -285,7 +285,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMOperation.Win.{Operation}{SignatureAlgorithm}.Error"
-    enum="Win32TpmErrorCodes" expires_after="2025-08-01">
+    enum="Win32TpmErrorCodes" expires_after="2025-10-05">
   <owner>seblalancette@chromium.org</owner>
   <owner>kristianm@chromium.org</owner>
   <owner>src/crypto/OWNERS</owner>
@@ -306,7 +306,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMOperation.{Operation}{SignatureAlgorithm}"
-    enum="BooleanSuccess" expires_after="2025-08-01">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>kristianm@chromium.org</owner>
   <owner>wfh@chromium.org</owner>
   <summary>
@@ -339,7 +339,7 @@
 </histogram>
 
 <histogram name="Crypto.TPMSupportType" enum="TPMType"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>kristianm@chromium.org</owner>
   <owner>agl@chromium.org</owner>
   <summary>
@@ -1144,7 +1144,7 @@
 </histogram>
 
 <histogram name="Net.ConnectionInfo.SubResource" enum="ConnectionInfo"
-    expires_after="2025-07-13">
+    expires_after="2025-10-05">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -2198,7 +2198,7 @@
 </histogram>
 
 <histogram name="Net.ErrorCodesForIsolatedAppScheme" enum="NetErrorCodes"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -2556,7 +2556,7 @@
 </histogram>
 
 <histogram name="Net.HttpJob.StorageAccessNetRequest2"
-    enum="StorageAccessNetRequestKind" expires_after="2025-08-01">
+    enum="StorageAccessNetRequestKind" expires_after="2025-10-05">
   <owner>cfredric@chromium.org</owner>
   <owner>johannhof@chromium.org</owner>
   <summary>
@@ -2571,7 +2571,7 @@
 </histogram>
 
 <histogram name="Net.HttpJob.StorageAccessRedirect"
-    enum="StorageAccessRedirectKind" expires_after="2025-08-01">
+    enum="StorageAccessRedirectKind" expires_after="2025-10-05">
   <owner>cfredric@chromium.org</owner>
   <owner>johannhof@chromium.org</owner>
   <summary>
@@ -3039,6 +3039,17 @@
   </summary>
 </histogram>
 
+<histogram name="Net.NetworkTransaction.ConnectedCallbackDelay" units="ms"
+    expires_after="2025-10-01">
+  <owner>hayato@chromium.org</owner>
+  <owner>blink-network-stack@google.com</owner>
+  <summary>
+    Measures the time taken to call http network transaction connected callback.
+    Recorded every time the connected callback is called and completed. Emitted
+    when the callback is completed.
+  </summary>
+</histogram>
+
 <histogram
     name="Net.NetworkTransaction.Create{StreamType}Time{HostType}.{Protocol}"
     units="ms" expires_after="2025-09-14">
@@ -3340,7 +3351,7 @@
 
 <histogram
     name="Net.QuicChromiumClientStream.Http3DatagramDroppedOnWriteConnectUdpPayload"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>ciaramcmullin@google.com</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -3420,7 +3431,7 @@
 
 <histogram
     name="Net.QuicConnectivityMonitor.NumActiveQuicSessionsAtNetworkChange"
-    units="sessions" expires_after="2025-07-01">
+    units="sessions" expires_after="2025-10-05">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3756,7 +3767,7 @@
 </histogram>
 
 <histogram name="Net.QuicProxyDatagramClientSocket.MaxQueueSizeReached"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>ciaramcmullin@google.com</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -3791,7 +3802,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.AcceptChForOrigin" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>bnc@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -3803,7 +3814,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.AcceptChFrameReceivedViaAlps"
-    enum="AcceptChEntries" expires_after="2025-08-03">
+    enum="AcceptChEntries" expires_after="2025-10-05">
   <owner>bnc@chromium.org</owner>
   <owner>src/net/OWNERS</owner>
   <summary>
@@ -4938,7 +4949,7 @@
 </histogram>
 
 <histogram name="Net.QuicSession.PacketRetransmitsPerMille" units="permille"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>dschinazi@chromium.org</owner>
   <owner>src/net/quic/OWNERS</owner>
   <summary>
@@ -5985,7 +5996,7 @@
 
 <histogram
     name="Net.RestrictedCookieManager.GetCookiesString.Duration.Subsampled"
-    units="microseconds" expires_after="2025-07-30">
+    units="microseconds" expires_after="2025-10-05">
   <owner>acondor@chromium.org</owner>
   <owner>clank-performance-team@google.com</owner>
   <summary>
@@ -6070,7 +6081,7 @@
 </histogram>
 
 <histogram name="Net.SafeSearch.CacheHit" enum="CacheAccessStatus"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>tju@google.com</owner>
   <owner>chrome-kids-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/network/histograms.xml b/tools/metrics/histograms/metadata/network/histograms.xml
index 285471f..98f429f 100644
--- a/tools/metrics/histograms/metadata/network/histograms.xml
+++ b/tools/metrics/histograms/metadata/network/histograms.xml
@@ -2400,7 +2400,7 @@
 </histogram>
 
 <histogram name="Network.SharedDictionary.EncodingType"
-    enum="SharedDictionaryEncodingType" expires_after="2025-08-03">
+    enum="SharedDictionaryEncodingType" expires_after="2025-10-05">
   <owner>nidhijaju@chromium.org</owner>
   <owner>blink-network-stack@google.com</owner>
   <summary>
@@ -4807,7 +4807,7 @@
 </histogram>
 
 <histogram name="Network.Wifi.Synced.Connection.Result" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jonmann@chromium.org</owner>
   <owner>crisrael@google.com</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -5077,7 +5077,7 @@
 </histogram>
 
 <histogram name="NetworkService.IpProtection.EmptyTokenCache2"
-    enum="IpProtectionProxyLayer" expires_after="2025-07-06">
+    enum="IpProtectionProxyLayer" expires_after="2025-10-05">
   <owner>djmitche@chromium.org</owner>
   <owner>ashleynewson@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
@@ -5452,7 +5452,7 @@
 </histogram>
 
 <histogram name="NetworkService.IpProtection.TryGetAuthTokensErrors"
-    enum="IpProtectionTokenBatchRequestError" expires_after="2025-08-03">
+    enum="IpProtectionTokenBatchRequestError" expires_after="2025-10-05">
   <owner>linxinan@chromium.org</owner>
   <owner>src/chrome/browser/ip_protection/OWNERS</owner>
   <summary>
@@ -5612,7 +5612,7 @@
 
 <histogram
     name="NetworkService.Requests.{Multiplexed}.{RequestType}.{Method}.{Result}.TotalHeadersSize"
-    units="bytes" expires_after="2025-08-01">
+    units="bytes" expires_after="2025-10-05">
   <owner>ortuno@chromium.org</owner>
   <owner>navtracking-team@google.com</owner>
   <summary>
@@ -5629,7 +5629,7 @@
 
 <histogram
     name="NetworkService.Requests.{Multiplexed}.{RequestType}.{Method}.{Result}.TotalRequestSize"
-    units="bytes" expires_after="2025-08-01">
+    units="bytes" expires_after="2025-10-05">
   <owner>ortuno@chromium.org</owner>
   <owner>navtracking-team@google.com</owner>
   <summary>
@@ -5646,7 +5646,7 @@
 
 <histogram
     name="NetworkService.Requests.{Multiplexed}.{RequestType}.{Method}.{Result}.TotalUrlSize"
-    units="bytes" expires_after="2025-08-01">
+    units="bytes" expires_after="2025-10-05">
   <owner>ortuno@chromium.org</owner>
   <owner>navtracking-team@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
index 0150083..a4f7bf9 100644
--- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -510,7 +510,7 @@
 </histogram>
 
 <histogram name="NewTabPage.GoogleCalendar.EventClickIndex" units="count"
-    expires_after="2025-08-06">
+    expires_after="2025-10-05">
   <owner>rtatum@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -535,7 +535,7 @@
 </histogram>
 
 <histogram name="NewTabPage.GoogleCalendar.ShownEvents" units="count"
-    expires_after="2025-08-06">
+    expires_after="2025-10-05">
   <owner>rtatum@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -548,7 +548,7 @@
 </histogram>
 
 <histogram name="NewTabPage.GoogleCalendar.UserAction" enum="NTPCalendarAction"
-    expires_after="2025-08-06">
+    expires_after="2025-10-05">
   <owner>rtatum@google.com</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -978,7 +978,7 @@
 </histogram>
 
 <histogram name="NewTabPage.Modules.ImpressionRatio{NewTabPageModules}"
-    units="perdecage" expires_after="2025-07-13">
+    units="perdecage" expires_after="2025-10-05">
   <owner>romanarora@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1379,7 +1379,7 @@
 
 <histogram
     name="NewTabPage.OneGoogleBar.RequestLatency{NewTabPage_OneGoogleBar_RequestLatency}"
-    units="ms" expires_after="2025-08-04">
+    units="ms" expires_after="2025-10-05">
   <owner>romanarora@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
@@ -1396,7 +1396,7 @@
 </histogram>
 
 <histogram name="NewTabPage.OneGoogleBar.ShownTime" units="ms"
-    expires_after="2025-08-04">
+    expires_after="2025-10-05">
   <owner>romanarora@chromium.org</owner>
   <owner>tiborg@chromium.org</owner>
   <owner>chrome-desktop-ntp@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml
index 6fcd1f7..7007e69e 100644
--- a/tools/metrics/histograms/metadata/omnibox/histograms.xml
+++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -502,7 +502,7 @@
 </histogram>
 
 <histogram name="Omnibox.AutocompletionTime.UpdateResult{Slice}"
-    units="microseconds" expires_after="2025-07-13">
+    units="microseconds" expires_after="2025-10-05">
   <owner>manukh@chromium.org</owner>
   <owner>jdonnelly@chromium.org</owner>
   <owner>chrome-desktop-search@google.com</owner>
@@ -1117,7 +1117,7 @@
 
 <histogram
     name="Omnibox.FocusToOpenTimeAnyPopupState3.ByPageContext.{OmniboxPageContext}"
-    units="ms" expires_after="2025-06-23">
+    units="ms" expires_after="2025-10-05">
   <owner>khalidpeer@chromium.org</owner>
   <owner>chrome-desktop-search@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/oobe/histograms.xml b/tools/metrics/histograms/metadata/oobe/histograms.xml
index 4a166b8d..a2b31bec 100644
--- a/tools/metrics/histograms/metadata/oobe/histograms.xml
+++ b/tools/metrics/histograms/metadata/oobe/histograms.xml
@@ -946,7 +946,7 @@
 </histogram>
 
 <histogram name="OOBE.MetricsClientIdReset" enum="Boolean"
-    expires_after="2025-07-27">
+    expires_after="2025-10-05">
   <owner>osamafathy@google.com</owner>
   <owner>cros-oobe@google.com</owner>
   <summary>
@@ -961,7 +961,7 @@
 </histogram>
 
 <histogram name="OOBE.MetricsClientIdReset2"
-    enum="OobeMetricsClientIdResetState" expires_after="2025-08-01">
+    enum="OobeMetricsClientIdResetState" expires_after="2025-10-05">
   <owner>osamafathy@google.com</owner>
   <owner>cros-oobe@google.com</owner>
   <summary>
@@ -1240,7 +1240,7 @@
 </histogram>
 
 <histogram name="OOBE.StatsReportingControllerReportedReset" enum="Boolean"
-    expires_after="2025-07-27">
+    expires_after="2025-10-05">
   <owner>osamafathy@google.com</owner>
   <owner>cros-oobe@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml
index 6427045..f398e9a 100644
--- a/tools/metrics/histograms/metadata/optimization/histograms.xml
+++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -551,7 +551,7 @@
 </histogram>
 
 <histogram name="OptimizationGuide.ApplyDecision.{OptimizationType}"
-    enum="OptimizationGuideOptimizationTypeDecision" expires_after="2025-08-03">
+    enum="OptimizationGuideOptimizationTypeDecision" expires_after="2025-10-05">
   <owner>sophiechang@chromium.org</owner>
   <owner>mcrouse@chromium.org</owner>
   <summary>
@@ -1781,7 +1781,7 @@
 
 <histogram
     name="OptimizationGuide.PredictionManager.ModelDeliveryEvents.{OptimizationTarget}"
-    enum="OptimizationGuideModelDeliveryEvent" expires_after="2025-08-03">
+    enum="OptimizationGuideModelDeliveryEvent" expires_after="2025-10-05">
   <owner>rajendrant@chromium.org</owner>
   <owner>chrome-intelligence-core@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml
index f7b35e2..fa37fdae 100644
--- a/tools/metrics/histograms/metadata/others/histograms.xml
+++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -911,7 +911,7 @@
 </histogram>
 
 <histogram name="Ads.InterestGroup.Auction.HttpCachedTrustedBiddingSignalsAge2"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>abigailkatcoff@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
   <summary>
@@ -3328,7 +3328,7 @@
 </histogram>
 
 <histogram name="ClientHints.AcceptCHFrame" enum="AcceptCHFrameRestart"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>victortan@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <owner>katabolism-finch@google.com</owner>
@@ -3341,7 +3341,7 @@
 </histogram>
 
 <histogram name="ClientHints.CriticalCHRestart" enum="CriticalCHRestart"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>victortan@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <owner>katabolism-finch@google.com</owner>
@@ -3351,7 +3351,7 @@
 </histogram>
 
 <histogram name="ClientHints.FetchLatency{OperationType}" units="microseconds"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>victortan@chromium.org</owner>
   <owner>miketaylr@chromium.org</owner>
   <owner>katabolism-finch@google.com</owner>
@@ -3392,7 +3392,7 @@
 </histogram>
 
 <histogram name="ClientHints.UpdateSize" units="count"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>victortan@chromium.org</owner>
   <owner>katabolism-finch@google.com</owner>
   <summary>
@@ -4310,7 +4310,7 @@
 </histogram>
 
 <histogram name="Eche.AppListUpdate.Latency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>crisrael@google.com</owner>
   <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -4323,7 +4323,7 @@
 </histogram>
 
 <histogram name="Eche.AppStream.LaunchAttempt" enum="AppStreamLaunchEntryPoint"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>crisrael@google.com</owner>
   <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -4381,7 +4381,7 @@
 </histogram>
 
 <histogram name="Eche.MultiDeviceFeatureState" enum="MultiDevice_FeatureState"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>jonmann@chromium.org</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
   <summary>
@@ -4425,7 +4425,7 @@
 </histogram>
 
 <histogram name="Eche.StreamEvent" enum="StreamState"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>crisrael@google.com</owner>
   <owner>exo-core-eng@google.com</owner>
   <owner>chromeos-cross-device-eng@google.com</owner>
@@ -6221,7 +6221,7 @@
 </histogram>
 
 <histogram name="Mojo.EndToEndLatencyUs.{ThreadName}" units="microseconds"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>lizeb@chromium.org</owner>
   <owner>rockot@google.com</owner>
   <owner>mthiesse@chromium.org</owner>
@@ -6839,7 +6839,7 @@
 </histogram>
 
 <histogram name="OriginTrials.PersistentOriginTrial.LevelDbLoadTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>pbirk@chromium.org</owner>
   <owner>src/components/origin_trials/OWNERS</owner>
   <summary>
@@ -6852,7 +6852,7 @@
 </histogram>
 
 <histogram name="OriginTrials.PersistentOriginTrial.OriginLookupsBeforeDbLoad"
-    units="origins" expires_after="2025-08-03">
+    units="origins" expires_after="2025-10-05">
   <owner>pbirk@chromium.org</owner>
   <owner>src/components/origin_trials/OWNERS</owner>
   <summary>
@@ -10122,7 +10122,7 @@
 </histogram>
 
 <histogram name="VoiceInteraction.StartEventSource"
-    enum="VoiceInteractionEventSource" expires_after="2025-08-03">
+    enum="VoiceInteractionEventSource" expires_after="2025-10-05">
   <owner>basiaz@google.com</owner>
   <owner>chrome-language@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml
index 50300e3..57b7cc6e 100644
--- a/tools/metrics/histograms/metadata/page/histograms.xml
+++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -1088,7 +1088,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.GoogleSearch.ConnectionReuseStatus{Profile}"
-    enum="ConnectionReuseStatus" expires_after="2025-08-01">
+    enum="ConnectionReuseStatus" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1216,7 +1216,7 @@
 
 <histogram
     name="PageLoad.Clients.GoogleSearch.DomainLookupTiming.NavigationToDomainLookupEnd2.{NavigationCountType}{BrowserInitializationStatus}{TabInitializationStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1237,7 +1237,7 @@
 
 <histogram
     name="PageLoad.Clients.GoogleSearch.DomainLookupTiming.NavigationToDomainLookupStart2.{NavigationCountType}{BrowserInitializationStatus}{TabInitializationStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1257,7 +1257,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.GoogleSearch.IsFirstNavigationForGWS"
-    enum="Boolean" expires_after="2025-08-01">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1296,7 +1296,7 @@
 
 <histogram
     name="PageLoad.Clients.GoogleSearch.NavigationSourceType{ConnectionReuseStatus}"
-    enum="NavigationSourceTypeEnum" expires_after="2025-08-01">
+    enum="NavigationSourceTypeEnum" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1315,6 +1315,19 @@
 </histogram>
 
 <histogram
+    name="PageLoad.Clients.GoogleSearch.NavigationTiming.ConnectedCallbackDelay"
+    units="ms" expires_after="2025-10-01">
+  <owner>hayato@chromium.org</owner>
+  <owner>chrome-loading@google.com</owner>
+  <summary>
+    Measures the time taken to call http network transaction connected callback,
+    for Google Search page loads. Recorded every time the connected callback is
+    called and completed, for Google Search page loads. Emitted when the
+    navigation is completed or the app is backgrounded on Android.
+  </summary>
+</histogram>
+
+<histogram
     name="PageLoad.Clients.GoogleSearch.NavigationTiming.CreateStreamDelay"
     units="ms" expires_after="2025-10-01">
   <owner>hayato@chromium.org</owner>
@@ -1439,7 +1452,7 @@
 
 <histogram
     name="PageLoad.Clients.GoogleSearch.NavigationTiming.NavigationToConnectStart2.{NavigationCountType}{BrowserInitializationStatus}{TabInitializationStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>suzukikeita@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1473,7 +1486,7 @@
 </histogram>
 
 <histogram name="PageLoad.Clients.GoogleSearch.PaintTiming.{MileStone}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>sisidovski@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1498,7 +1511,7 @@
 
 <histogram
     name="PageLoad.Clients.GoogleSearch.ParseTiming.NavigationToParseStart"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>kouhei@chromium.org</owner>
   <owner>chrome-loading@google.com</owner>
   <summary>
@@ -1535,7 +1548,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.ImageLoadingPriority.ConfidenceOfActual{PositiveOrNegative}.2"
-    units="%" expires_after="2025-08-01">
+    units="%" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1555,7 +1568,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.ImageLoadingPriority.ConfidenceOfActual{PositiveOrNegative}.PerTotalFrequency.2"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1596,7 +1609,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.ImageLoadingPriority.TotalFrequencyOfActual{PositiveOrNegative}.PerConfidence.3"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1750,7 +1763,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.Subresource.ConfidenceOfActual{PositiveOrNegative}.PerTotalFrequency{Site}.3"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1776,7 +1789,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.Subresource.ConfidenceOfActual{PositiveOrNegative}{Site}.2"
-    units="%" expires_after="2025-08-01">
+    units="%" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1869,7 +1882,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.Subresource.FrequencyOfActual{PositiveOrNegative}{Site}.2"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1894,7 +1907,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.Subresource.TotalFrequencyOfActual{PositiveOrNegative}.PerConfidence{Site}.3"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -1920,7 +1933,7 @@
 
 <histogram
     name="PageLoad.Clients.LCPP.Subresource.TotalFrequencyOfActual{PositiveOrNegative}.WithConfidence{Range}{Site}.2"
-    units="Count" expires_after="2025-08-01">
+    units="Count" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>
     src/third_party/blink/renderer/core/lcp_critical_path_predictor/OWNERS
@@ -2352,7 +2365,7 @@
 
 <histogram
     name="PageLoad.Clients.ThirdParty.Frames.NavigationToFirstContentfulPaint3"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>jkarlin@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
@@ -3682,7 +3695,7 @@
 </histogram>
 
 <histogram name="PageLoad.Internal.ErrorCode" enum="InternalErrorLoadEvent"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>csharrison@chromium.org</owner>
   <owner>bmcquade@chromium.org</owner>
   <summary>
@@ -3833,7 +3846,7 @@
 
 <histogram
     name="PageLoad.Internal.Prerender2.MainResourceParseStartToActivation{PreloadingTriggerType}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>lingqi@chromium.org</owner>
   <owner>chrome-prerendering@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/password/enums.xml b/tools/metrics/histograms/metadata/password/enums.xml
index 624ced2..d2b2cf3 100644
--- a/tools/metrics/histograms/metadata/password/enums.xml
+++ b/tools/metrics/histograms/metadata/password/enums.xml
@@ -1623,23 +1623,6 @@
   <int value="1" label="The sheet was dismissed"/>
 </enum>
 
-<enum name="PrefilledUsernameFillOutcome">
-  <int value="0" label="Prefilled placeholder username overridden">
-    1) the page has a username input element whose value was prefilled by the
-    website itself. 2) the prefilled value was found in a list of known
-    placeholder values (e.g. &quot;username or email&quot;). 3) the user had a
-    credential stored and the field content was overridden with the username of
-    this credential due to 2).
-  </int>
-  <int value="1" label="Prefilled username not overridden">
-    1) the page has a username input element whose value was prefilled by the
-    website itself. 2) the prefilled value was NOT found in a list of known
-    placeholder values (e.g. &quot;username or email&quot;). 3) the user had a
-    credential stored and the field content was NOT overridden with the username
-    of this credential due to 2).
-  </int>
-</enum>
-
 <enum name="ProactivePasswordGenerationBottomSheetTransitionType">
   <int value="0" label="Silenced"/>
   <int value="1" label="Unsilenced"/>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index 40227f5..d8bea9b5 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -831,7 +831,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ApplySyncChanges.UpdateLoginSyncError"
-    enum="PasswordUpdateLoginSyncError" expires_after="2025-06-08">
+    enum="PasswordUpdateLoginSyncError" expires_after="2025-10-05">
   <owner>mamir@chromium.org</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -1381,7 +1381,7 @@
 </histogram>
 
 <histogram name="PasswordManager.CredentialsWithDuplicates3" units="units"
-    expires_after="2025-05-11">
+    expires_after="2025-11-15">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -1552,7 +1552,7 @@
 <histogram name="PasswordManager.FieldNameCollisionInVotes" enum="Boolean"
     expires_after="2025-08-10">
   <owner>kazinova@google.com</owner>
-  <owner>khamutov@google.com</owner>
+  <owner>vasilii@chromium.org</owner>
   <summary>
     Measures whether a password vote had a field name collision, i.e. multiple
     fields that should have an Autofill type uploaded have the same name.
@@ -1728,7 +1728,7 @@
 </histogram>
 
 <histogram name="PasswordManager.FormVisited.PerProfileType"
-    enum="BrowserProfileType" expires_after="2025-08-03">
+    enum="BrowserProfileType" expires_after="2025-10-05">
   <owner>rhalavati@chromium.org</owner>
   <owner>chrome-privacy-core@google.com</owner>
   <summary>
@@ -2389,7 +2389,7 @@
 </histogram>
 
 <histogram name="PasswordManager.ModelPredictions.Empty" enum="Boolean"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2414,9 +2414,9 @@
 <histogram
     name="PasswordManager.NewlySavedPasswordHasEmptyUsername.{PasswordType}"
     enum="Boolean" expires_after="2025-09-14">
-  <owner>khamutov@google.com</owner>
   <owner>kazinova@google.com</owner>
-  <owner>chrome-autofill-alerts@google.com</owner>
+  <owner>vasilii@chromium.org</owner>
+  <owner>chrome-password-manager-metrics-alerts@google.com</owner>
   <summary>
     Whether a newly saved password has an empty username. Recorded right before
     a new credential is commited to the store.
@@ -2436,7 +2436,7 @@
 </histogram>
 
 <histogram name="PasswordManager.OnEncryptorReceived.Success"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>vsemeniuk@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -2801,7 +2801,7 @@
 </histogram>
 
 <histogram name="PasswordManager.PasswordDropdownItemSelected"
-    enum="PasswordDropdownSelectedOption" expires_after="2025-08-03">
+    enum="PasswordDropdownSelectedOption" expires_after="2025-10-05">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -3681,21 +3681,6 @@
   </summary>
 </histogram>
 
-<histogram name="PasswordManager.PrefilledUsernameFillOutcome"
-    enum="PrefilledUsernameFillOutcome" expires_after="2025-05-11">
-  <owner>khamutov@google.com</owner>
-  <owner>kazinova@google.com</owner>
-  <summary>
-    Records successful fills of prefilled username values known as placeholders
-    and unsuccessful fills that were blocked because the prefilled value was not
-    identified as a placeholder. Recorded once per PasswordAutofillAgent
-    instance, when attempting to fill a password form that contains a username
-    value which was prepopulated by the website.
-
-    Warning: this histogram was expired from M86 to M115; data may be missing.
-  </summary>
-</histogram>
-
 <histogram
     name="PasswordManager.ProcessIncomingPasswordSharingInvitationResult"
     enum="PasswordManager.ProcessIncomingPasswordSharingInvitationResult"
@@ -3995,7 +3980,7 @@
 
 <histogram
     name="PasswordManager.SingleUsername.ForgotPasswordServerPredictionUsed"
-    enum="Boolean" expires_after="2025-05-11">
+    enum="Boolean" expires_after="2025-11-15">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -4026,7 +4011,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SingleUsername.VoteDataAvailability"
-    enum="SingleUsernameVoteDataAvailability" expires_after="2025-05-11">
+    enum="SingleUsernameVoteDataAvailability" expires_after="2025-11-15">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -4114,7 +4099,7 @@
 </histogram>
 
 <histogram name="PasswordManager.SuggestionPopupTriggerSource"
-    enum="AutofillSuggestionTriggerSource" expires_after="2025-08-03">
+    enum="AutofillSuggestionTriggerSource" expires_after="2025-10-05">
   <owner>kazinova@google.com</owner>
   <owner>vasilii@chromium.org</owner>
   <summary>
@@ -4230,7 +4215,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.DismissalReason"
-    enum="BottomSheet.StateChangeReason" expires_after="2025-08-03">
+    enum="BottomSheet.StateChangeReason" expires_after="2025-10-05">
   <owner>ioanap@chromium.org</owner>
   <owner>friedrichh@chromium.org</owner>
   <summary>
@@ -4240,7 +4225,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.Outcome"
-    enum="TouchToFill.Outcome" expires_after="2025-08-03">
+    enum="TouchToFill.Outcome" expires_after="2025-10-05">
   <owner>ioanap@chromium.org</owner>
   <owner>friedrichh@chromium.org</owner>
   <summary>
@@ -4280,7 +4265,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.SubmissionReadiness"
-    enum="TouchToFill.SubmissionReadiness" expires_after="2025-08-03">
+    enum="TouchToFill.SubmissionReadiness" expires_after="2025-10-05">
   <owner>ioanap@chromium.org</owner>
   <owner>friedrichh@chromium.org</owner>
   <summary>
@@ -4292,7 +4277,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.SuccessfulSubmissionWasObserved"
-    enum="Boolean" expires_after="2025-08-03">
+    enum="Boolean" expires_after="2025-10-05">
   <owner>ioanap@chromium.org</owner>
   <owner>friedrichh@chromium.org</owner>
   <summary>
@@ -4311,7 +4296,7 @@
 </histogram>
 
 <histogram name="PasswordManager.TouchToFill.TimeToSuccessfulLogin" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>ioanap@chromium.org</owner>
   <owner>friedrichh@chromium.org</owner>
   <summary>
@@ -4502,7 +4487,7 @@
 </histogram>
 
 <histogram name="PasswordManager.UpdateUIDismissalReason"
-    enum="PasswordManagerUIDismissalReason" expires_after="2025-08-03">
+    enum="PasswordManagerUIDismissalReason" expires_after="2025-10-05">
   <owner>vasilii@chromium.org</owner>
   <summary>Why was the update password UI (bubble or infobar) closed?</summary>
 </histogram>
diff --git a/tools/metrics/histograms/metadata/performance_controls/histograms.xml b/tools/metrics/histograms/metadata/performance_controls/histograms.xml
index 38c9e5b..9f1121e0 100644
--- a/tools/metrics/histograms/metadata/performance_controls/histograms.xml
+++ b/tools/metrics/histograms/metadata/performance_controls/histograms.xml
@@ -108,7 +108,7 @@
 
 <histogram
     name="PerformanceControls.Intervention.BackgroundTab.{ResourceType}.HealthStatusChange.{Time}"
-    enum="InterventionHealthChange" expires_after="2025-07-06">
+    enum="InterventionHealthChange" expires_after="2025-10-05">
   <owner>stluong@chromium.org</owner>
   <owner>estalin@chromium.org</owner>
   <owner>chrome-performance-ui-sea@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/performance_manager/enums.xml b/tools/metrics/histograms/metadata/performance_manager/enums.xml
index d60802a2..c21b6674 100644
--- a/tools/metrics/histograms/metadata/performance_manager/enums.xml
+++ b/tools/metrics/histograms/metadata/performance_manager/enums.xml
@@ -34,6 +34,15 @@
   <int value="4" label="Mixed"/>
 </enum>
 
+<enum name="InputScenarioUpdateReason">
+  <int value="0" label="Key Event"/>
+  <int value="1" label="Tap Event"/>
+  <int value="2" label="Scroll Start Event"/>
+  <int value="3" label="Scroll End Event"/>
+  <int value="4" label="Timeout"/>
+  <int value="5" label="Node Removed"/>
+</enum>
+
 <enum name="LocalSiteCharacteristicsDBInitStatus">
   <int value="0" label="Success"/>
   <int value="1" label="Corruption"/>
diff --git a/tools/metrics/histograms/metadata/performance_manager/histograms.xml b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
index 0f42044..9f4efdf3 100644
--- a/tools/metrics/histograms/metadata/performance_manager/histograms.xml
+++ b/tools/metrics/histograms/metadata/performance_manager/histograms.xml
@@ -210,6 +210,15 @@
   </summary>
 </histogram>
 
+<histogram name="PerformanceManager.InputScenarioChanged"
+    enum="InputScenarioUpdateReason" expires_after="2026-04-07">
+  <owner>kraskevich@google.com</owner>
+  <owner>chrome-catan@google.com</owner>
+  <summary>
+    Logged on every input scenario change in performance manager.
+  </summary>
+</histogram>
+
 <histogram name="PerformanceManager.LoadingNotQuiescentPageCount.{Visibility}"
     units="pages" expires_after="2025-06-22">
   <owner>joenotcharles@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml
index 9a3b3bc..c9b71c15 100644
--- a/tools/metrics/histograms/metadata/permissions/histograms.xml
+++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -906,7 +906,7 @@
 </histogram>
 
 <histogram name="Permissions.PageInfo.Changed.{PermissionType}.{ReloadInfoBar}"
-    enum="PermissionChangeAction" expires_after="2025-08-03">
+    enum="PermissionChangeAction" expires_after="2025-10-05">
   <owner>elklm@chromium.org</owner>
   <owner>src/components/permissions/PERMISSIONS_OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml
index a237d729..69c1fed 100644
--- a/tools/metrics/histograms/metadata/platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -131,7 +131,7 @@
 </histogram>
 
 <histogram name="Platform.Chaps.Session.{Operation}" enum="ChapsSessionStatus"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>chenyian@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
@@ -1770,7 +1770,7 @@
 </histogram>
 
 <histogram name="Platform.Missive.DataLossErrorReason"
-    enum="DataLossErrorReason" expires_after="2025-08-03">
+    enum="DataLossErrorReason" expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -1847,7 +1847,7 @@
 </histogram>
 
 <histogram name="Platform.Missive.StorageDegradationAmount" units="KiB"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>lbaraz@google.com</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -1879,7 +1879,7 @@
 </histogram>
 
 <histogram name="Platform.Missive.UnavailableErrorReason"
-    enum="UnavailableErrorReason" expires_after="2025-08-03">
+    enum="UnavailableErrorReason" expires_after="2025-10-05">
   <owner>lbaraz@chromium.org</owner>
   <owner>cros-reporting-team@google.com</owner>
   <summary>
@@ -1972,7 +1972,7 @@
 </histogram>
 
 <histogram name="Platform.MountEncrypted.EncryptionKeyStatus"
-    enum="MountEncryptedEncryptionKeyStatus" expires_after="2025-08-03">
+    enum="MountEncryptedEncryptionKeyStatus" expires_after="2025-10-05">
   <owner>apronin@chromium.org</owner>
   <owner>cros-hwsec+uma@google.com</owner>
   <summary>
@@ -1983,7 +1983,7 @@
 </histogram>
 
 <histogram name="Platform.MountEncrypted.SystemKeyStatus"
-    enum="MountEncryptedSystemKeyStatus" expires_after="2025-08-03">
+    enum="MountEncryptedSystemKeyStatus" expires_after="2025-10-05">
   <owner>apronin@chromium.org</owner>
   <owner>cros-hwsec+uma@google.com</owner>
   <summary>
@@ -2520,7 +2520,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.AuthErrorCode" enum="TPMResultCodeEnum"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>yich@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
@@ -2571,7 +2571,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.DictionaryAttackCounter" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>yich@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
@@ -2600,7 +2600,7 @@
 </histogram>
 
 <histogram name="Platform.TPM.ErrorCode" enum="TPMResultCodeEnum"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>yich@google.com</owner>
   <owner>cros-hwsec-userland-eng+uma@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml
index 557f55a..e330159 100644
--- a/tools/metrics/histograms/metadata/power/histograms.xml
+++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -845,7 +845,7 @@
 </histogram>
 
 <histogram name="Power.BatteryLife.{BatteryCapacityType}" units="minute"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>puthik@chromium.org</owner>
   <owner>chromeos-platform-power@google.com</owner>
   <summary>
@@ -1306,9 +1306,11 @@
 <!-- LINT.IfChange(InputScenarioSuffix) -->
 
   <token key="InputScenario">
-    <variant name="_NoInput" summary="the user is not typing"/>
+    <variant name="_NoInput" summary="the user is not providing input"/>
+    <variant name="_Scroll" summary="the user scrolled"/>
+    <variant name="_Tap" summary="the user tapped but not scrolled"/>
     <variant name="_Typing"
-        summary="the user was typing for some part of the 30s interval"/>
+        summary="The user typed be neither tapped nor scrolled"/>
     <variant name="_UnknownInputScenario"
         summary="input state could not be detected"/>
   </token>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml
index 088d385..80ba35a 100644
--- a/tools/metrics/histograms/metadata/printing/histograms.xml
+++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -94,7 +94,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.AddressResolutionResult" enum="BooleanSuccess"
-    expires_after="2025-06-30">
+    expires_after="2025-10-05">
   <owner>bmgordon@chromium.org</owner>
   <owner>cros-printing-dev@chromium.org</owner>
   <summary>
@@ -402,7 +402,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.TotalNetworkPrintersCount2" units="printers"
-    expires_after="2025-06-30">
+    expires_after="2025-10-05">
   <owner>bmgordon@chromium.org</owner>
   <owner>project-bolton@google.com</owner>
   <summary>
@@ -417,7 +417,7 @@
 </histogram>
 
 <histogram name="Printing.CUPS.TotalNetworkPrintersCount2.SettingsOpened"
-    units="printers" expires_after="2025-06-30">
+    units="printers" expires_after="2025-10-05">
   <owner>bmgordon@chromium.org</owner>
   <owner>project-bolton@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/privacy/histograms.xml b/tools/metrics/histograms/metadata/privacy/histograms.xml
index ba10426..d89bb21 100644
--- a/tools/metrics/histograms/metadata/privacy/histograms.xml
+++ b/tools/metrics/histograms/metadata/privacy/histograms.xml
@@ -474,7 +474,7 @@
 </histogram>
 
 <histogram name="Privacy.DIPS.DatabaseEntryCount" units="entries"
-    expires_after="2025-07-06">
+    expires_after="2025-10-05">
   <owner>wanderview@chromium.org</owner>
   <owner>src/content/browser/btm/OWNERS</owner>
   <summary>
@@ -1676,7 +1676,7 @@
 </histogram>
 
 <histogram name="PrivacySandbox.PrivacyPolicy.LoadingTime" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>chrstne@google.com</owner>
   <owner>koilos@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml
index 26c47d1..a6b039e8 100644
--- a/tools/metrics/histograms/metadata/profile/histograms.xml
+++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -314,7 +314,7 @@
 </histogram>
 
 <histogram name="Profile.Menu.ClickedActionableItem{ProfileType}"
-    enum="ProfileMenuActionableItem" expires_after="2025-08-03">
+    enum="ProfileMenuActionableItem" expires_after="2025-10-05">
   <owner>droger@chromium.org</owner>
   <owner>msarda@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -465,7 +465,7 @@
 </histogram>
 
 <histogram name="Profile.PercentageOfManagedProfiles" units="units"
-    expires_after="2025-07-13">
+    expires_after="2025-10-05">
   <owner>agawronska@chromium.org</owner>
   <owner>cros-families-eng@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/quota/histograms.xml b/tools/metrics/histograms/metadata/quota/histograms.xml
index ac1adfc..c5f4617 100644
--- a/tools/metrics/histograms/metadata/quota/histograms.xml
+++ b/tools/metrics/histograms/metadata/quota/histograms.xml
@@ -63,7 +63,7 @@
 </histogram>
 
 <histogram name="Quota.DatabaseMigration{VersionUpgrades}"
-    enum="BooleanSuccess" expires_after="2025-05-24">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/renderer4/histograms.xml b/tools/metrics/histograms/metadata/renderer4/histograms.xml
index 3d19544c..4e3a250 100644
--- a/tools/metrics/histograms/metadata/renderer4/histograms.xml
+++ b/tools/metrics/histograms/metadata/renderer4/histograms.xml
@@ -247,7 +247,7 @@
 </histogram>
 
 <histogram name="Renderer4.Renderer.RasterTaskTotalDuration{RasterTaskTypeGpu}"
-    units="microseconds" expires_after="2025-07-27">
+    units="microseconds" expires_after="2025-10-05">
   <owner>khushalsagar@chromium.org</owner>
   <owner>chrome-gpu-metric-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
index 74e972d..0f77c00 100644
--- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
+++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -386,7 +386,7 @@
 
 <histogram
     name="SafeBrowsing.BrowserThrottle.RequestDestination{RequestedSkippedOrChecked}"
-    enum="RequestDestination" expires_after="2025-07-06">
+    enum="RequestDestination" expires_after="2025-10-05">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -418,7 +418,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.BrowserThrottle.TotalDelay2{UserCategory}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -723,7 +723,7 @@
 
 <histogram
     name="SafeBrowsing.Daily.SecuritySensitiveCountLast28Days.{UserState}.AllEvents"
-    units="events" expires_after="2025-08-03">
+    units="events" expires_after="2025-10-05">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -2670,7 +2670,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.RT.IsLookupSuccessful{UserCategory}"
-    enum="BooleanSuccess" expires_after="2025-08-03">
+    enum="BooleanSuccess" expires_after="2025-10-05">
   <owner>xinghuilu@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -3349,7 +3349,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4GetHash.Network.Time" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>vakh@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
@@ -3766,7 +3766,7 @@
 </histogram>
 
 <histogram name="SafeBrowsing.V4StoreWriteError"
-    enum="V4HashPrefixMapWriteError" expires_after="2025-07-31">
+    enum="V4HashPrefixMapWriteError" expires_after="2025-10-05">
   <owner>drubery@chromium.org</owner>
   <owner>chrome-counter-abuse-alerts@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/scheduler/histograms.xml b/tools/metrics/histograms/metadata/scheduler/histograms.xml
index d904fae..ea73478e 100644
--- a/tools/metrics/histograms/metadata/scheduler/histograms.xml
+++ b/tools/metrics/histograms/metadata/scheduler/histograms.xml
@@ -34,7 +34,7 @@
 </variants>
 
 <histogram name="MessagePumpEpoll.WatchedFileDescriptors"
-    units="FileDescriptors" expires_after="2025-08-01">
+    units="FileDescriptors" expires_after="2025-10-05">
   <owner>mthiesse@chromium.org</owner>
   <owner>lizeb@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml
index 39f1a6b..abcf6591 100644
--- a/tools/metrics/histograms/metadata/security/histograms.xml
+++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -1071,7 +1071,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.ProxyCount" units="proxies"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
@@ -1144,7 +1144,7 @@
 </histogram>
 
 <histogram name="SiteIsolation.SavedWebTriggeredIsolatedOrigins.Size"
-    units="origins" expires_after="2025-08-03">
+    units="origins" expires_after="2025-10-05">
   <owner>alexmos@chromium.org</owner>
   <owner>creis@chromium.org</owner>
   <owner>lukasza@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
index 913365d..22c5929 100644
--- a/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
+++ b/tools/metrics/histograms/metadata/segmentation_platform/histograms.xml
@@ -201,7 +201,7 @@
 </histogram>
 
 <histogram name="SegmentationPlatform.Database.{DatabaseOperation}" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>haileywang@google.com</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
   <summary>
@@ -600,7 +600,7 @@
 
 <histogram
     name="SegmentationPlatform.ModelExecution.Result.{Index}.{SegmentationModel}"
-    units="score" expires_after="2025-08-03">
+    units="score" expires_after="2025-10-05">
   <owner>shaktisahu@chromium.org</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
   <summary>
@@ -648,7 +648,7 @@
 
 <histogram
     name="SegmentationPlatform.ModelExecution.Status.{SegmentationModel}"
-    enum="SegmentationPlatformModelExecutionStatus" expires_after="2025-08-03">
+    enum="SegmentationPlatformModelExecutionStatus" expires_after="2025-10-05">
   <owner>nyquist@chromium.org</owner>
   <owner>shaktisahu@chromium.org</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
@@ -740,7 +740,7 @@
 </histogram>
 
 <histogram name="SegmentationPlatform.SelectionFailedReason.{SegmentationKey}"
-    enum="SegmentationSelectionFailureReason" expires_after="2025-08-03">
+    enum="SegmentationSelectionFailureReason" expires_after="2025-10-05">
   <owner>ssid@chromium.org</owner>
   <owner>chrome-segmentation-platform@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml
index 4793eab..cd2c24050 100644
--- a/tools/metrics/histograms/metadata/service/histograms.xml
+++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -426,7 +426,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.Fallback.Time" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -439,7 +439,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.HasResponse.Time" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -451,7 +451,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.MainResource.Status"
-    enum="ServiceWorkerStatusCode" expires_after="2025-08-01">
+    enum="ServiceWorkerStatusCode" expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -475,7 +475,7 @@
 </histogram>
 
 <histogram name="ServiceWorker.FetchEvent.Subresource.Status"
-    enum="ServiceWorkerStatusCode" expires_after="2025-08-01">
+    enum="ServiceWorkerStatusCode" expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -781,7 +781,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FindRegistrationToCompleted{EmbeddedWorkerInitialStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -801,7 +801,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FindRegistrationToFallbackNetwork{EmbeddedWorkerInitialStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -821,7 +821,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.FindRegistrationToRequestStart{EmbeddedWorkerInitialStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -867,7 +867,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.InitialServiceWorkerStatus{NavigationType}{FrameTreeNodeType}{BrowserStartupCompleted}"
-    enum="InitialServiceWorkerStatus" expires_after="2025-08-01">
+    enum="InitialServiceWorkerStatus" expires_after="2025-10-05">
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
   <summary>
@@ -906,7 +906,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.ResponseReceivedToCompleted2{ServiceWorkerResponseSource}{EmbeddedWorkerInitialStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -1003,7 +1003,7 @@
 
 <histogram
     name="ServiceWorker.LoadTiming.MainFrame.MainResource.WorkerReadyToFetchHandlerStart{EmbeddedWorkerInitialStatus}"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2025-10-05">
   <owner>yyanagisawa@chromium.org</owner>
   <owner>chikamune@chromium.org</owner>
   <owner>chrome-worker@google.com</owner>
@@ -2047,7 +2047,7 @@
 
 <histogram
     name="ServiceWorkerCache.{ServiceWorkerCacheSchedulerOpClientType}.Scheduler.QueueDuration2.{ServiceWorkerSchedulerOp}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml
index 4d8119d1..e9f2cd4 100644
--- a/tools/metrics/histograms/metadata/settings/histograms.xml
+++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -120,7 +120,7 @@
 </histogram>
 
 <histogram name="Settings.AiPage.Compare.Interactions"
-    enum="SettingsAiPageCompareInteractions" expires_after="2025-08-03">
+    enum="SettingsAiPageCompareInteractions" expires_after="2025-10-05">
   <owner>zalmashni@google.com</owner>
   <owner>rainhard@chromium.org</owner>
   <owner>chrome-browser-privacy-team@google.com</owner>
@@ -140,7 +140,7 @@
 </histogram>
 
 <histogram name="Settings.AiPage.ElementVisibility.{FeatureName}"
-    enum="BooleanVisible" expires_after="2025-08-03">
+    enum="BooleanVisible" expires_after="2025-10-05">
   <owner>zalmashni@google.com</owner>
   <owner>rainhard@chromium.org</owner>
   <owner>chrome-browser-privacy-team@google.com</owner>
@@ -159,7 +159,7 @@
 </histogram>
 
 <histogram name="Settings.AiPage.HistorySearch.Interactions"
-    enum="SettingsAiPageHistorySearchInteractions" expires_after="2025-08-03">
+    enum="SettingsAiPageHistorySearchInteractions" expires_after="2025-10-05">
   <owner>zalmashni@google.com</owner>
   <owner>rainhard@chromium.org</owner>
   <owner>chrome-browser-privacy-team@google.com</owner>
@@ -170,7 +170,7 @@
 </histogram>
 
 <histogram name="Settings.AiPage.Interactions"
-    enum="SettingsAiPageInteractions" expires_after="2025-08-03">
+    enum="SettingsAiPageInteractions" expires_after="2025-10-05">
   <owner>zalmashni@google.com</owner>
   <owner>rainhard@chromium.org</owner>
   <owner>chrome-browser-privacy-team@google.com</owner>
@@ -288,7 +288,7 @@
 </histogram>
 
 <histogram name="Settings.FragmentAttached"
-    enum="AndroidSettingsFragmentHashes" expires_after="M140">
+    enum="AndroidSettingsFragmentHashes" expires_after="2025-10-05">
   <owner>dullweber@chromium.org</owner>
   <owner>chrome-browser-privacy@google.com</owner>
   <summary>
@@ -347,7 +347,7 @@
 </histogram>
 
 <histogram name="Settings.HoverCards.ImagePreview.Enabled"
-    enum="BooleanEnabled" expires_after="2025-06-22">
+    enum="BooleanEnabled" expires_after="2025-10-05">
   <owner>charlesmeng@chromium.org</owner>
   <owner>estalin@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml
index 1503afbb..6f15cf10 100644
--- a/tools/metrics/histograms/metadata/signin/histograms.xml
+++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -693,7 +693,7 @@
 </histogram>
 
 <histogram name="Signin.Bookmarks.{ConsentLevel}.{BookmarkGroup}{AccessPoint}"
-    units="count" expires_after="2025-08-03">
+    units="count" expires_after="2025-10-05">
   <owner>rsult@google.com</owner>
   <owner>droger@chromium.org</owner>
   <owner>chrome-signin-team@google.com</owner>
@@ -1430,7 +1430,7 @@
 </histogram>
 
 <histogram name="Signin.GetAccountsBackoffSuccess"
-    enum="BooleanGetAccountsSucceeded" expires_after="2025-08-03">
+    enum="BooleanGetAccountsSucceeded" expires_after="2025-10-05">
   <owner>samarchehade@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -2105,7 +2105,7 @@
 </histogram>
 
 <histogram name="Signin.NumberOfActiveAccounts.{TimeRange}" units="accounts"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>bsazonov@chromium.org</owner>
   <owner>droger@chromium.org</owner>
   <owner>treib@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml
index 53d9093..2dd87c7 100644
--- a/tools/metrics/histograms/metadata/startup/histograms.xml
+++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -1177,7 +1177,7 @@
 </histogram>
 
 <histogram name="Startup.Temperature" enum="StartupTemperature"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
 <!-- expires-after: Diagnosis metric for changes in StartupTemperature suffix.
      Shouldn't truly expire but kColdStartHardFaultCountThreshold should be
      surveyed yearly. -->
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index 71ef355..f8858d3 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -1328,7 +1328,7 @@
 </histogram>
 
 <histogram name="Storage.InterestGroup.PrevWinsNumEntries" units="entries"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>caraitto@chromium.org</owner>
   <owner>pauljensen@chromium.org</owner>
   <owner>privacy-sandbox-dev@chromium.org</owner>
@@ -1391,7 +1391,7 @@
 </histogram>
 
 <histogram name="Storage.SessionStorage.RendererAreaCacheHit"
-    enum="LocalStorageRendererAreaCacheHitEnum" expires_after="2025-08-05">
+    enum="LocalStorageRendererAreaCacheHitEnum" expires_after="2025-10-05">
   <owner>ayui@chromium.org</owner>
   <owner>chrome-owp-storage@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/subresource/histograms.xml b/tools/metrics/histograms/metadata/subresource/histograms.xml
index afffab7..da6a6a5 100644
--- a/tools/metrics/histograms/metadata/subresource/histograms.xml
+++ b/tools/metrics/histograms/metadata/subresource/histograms.xml
@@ -123,7 +123,7 @@
 </histogram>
 
 <histogram name="SubresourceFilter.IndexRuleset.Verify.Status"
-    enum="SubresourceFilterVerifyStatus" expires_after="2025-08-03">
+    enum="SubresourceFilterVerifyStatus" expires_after="2025-10-05">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
@@ -335,7 +335,7 @@
 </histogram>
 
 <histogram name="SubresourceFilter.SafeBrowsing.TotalCheckTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>alexmt@chromium.org</owner>
   <owner>chrome-ads-histograms@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml
index 5c412f0..f55bc62 100644
--- a/tools/metrics/histograms/metadata/sync/histograms.xml
+++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -202,7 +202,7 @@
 </histogram>
 
 <histogram name="Sync.BatchUpload.DataTypeAvailable" enum="SyncDataTypes"
-    expires_after="2025-08-24">
+    expires_after="2026-04-14">
   <owner>rsult@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -213,7 +213,7 @@
 </histogram>
 
 <histogram name="Sync.BatchUpload.DataTypeSelected" enum="SyncDataTypes"
-    expires_after="2025-04-14">
+    expires_after="2026-04-14">
   <owner>rsult@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -225,7 +225,7 @@
 </histogram>
 
 <histogram name="Sync.BatchUpload.DataTypeSelectedItemPercentage"
-    units="selection" expires_after="2025-04-14">
+    units="selection" expires_after="2026-04-14">
   <owner>rsult@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -237,7 +237,7 @@
 </histogram>
 
 <histogram name="Sync.BatchUpload.DialogCloseReason"
-    enum="BatchUploadDialogCloseReason" expires_after="2025-08-24">
+    enum="BatchUploadDialogCloseReason" expires_after="2026-04-14">
   <owner>rsult@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -247,7 +247,7 @@
 </histogram>
 
 <histogram name="Sync.BatchUpload.Opened" enum="BatchUploadEntryPoint"
-    expires_after="2025-08-24">
+    expires_after="2026-04-14">
   <owner>rsult@google.com</owner>
   <owner>chrome-signin-team@google.com</owner>
   <summary>
@@ -431,7 +431,7 @@
 </histogram>
 
 <histogram name="Sync.CommitResponse{SyncDataType}" enum="SyncerErrorValues"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>rushans@google.com</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -869,7 +869,7 @@
 </histogram>
 
 <histogram name="Sync.DataTypeRunFailures2" enum="SyncDataTypes"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -881,7 +881,7 @@
 </histogram>
 
 <histogram name="Sync.DataTypeStartFailures2" enum="SyncDataTypes"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>rushans@google.com</owner>
   <owner>mastiz@chromium.org</owner>
   <summary>
@@ -1245,7 +1245,7 @@
 </histogram>
 
 <histogram name="Sync.Local.Enabled2" enum="BooleanEnabled"
-    expires_after="2025-05-30">
+    expires_after="2025-10-05">
   <owner>igorruvinov@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -1254,7 +1254,7 @@
   </summary>
 </histogram>
 
-<histogram name="Sync.Local.FileSizeKB" units="KB" expires_after="2025-08-03">
+<histogram name="Sync.Local.FileSizeKB" units="KB" expires_after="2025-10-05">
   <owner>igorruvinov@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -1264,7 +1264,7 @@
 </histogram>
 
 <histogram name="Sync.Local.ReadPlatformFileError" enum="PlatformFileError"
-    expires_after="2025-05-30">
+    expires_after="2025-10-05">
   <owner>igorruvinov@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -1275,7 +1275,7 @@
 </histogram>
 
 <histogram name="Sync.Local.RoamingProfileUnavailable2" enum="BooleanError"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>igorruvinov@chromium.org</owner>
   <owner>pastarmovj@chromium.org</owner>
   <summary>
@@ -1351,7 +1351,7 @@
 </histogram>
 
 <histogram name="Sync.NudgedUpdateResult{SyncDataType}"
-    enum="NudgedUpdateResult" expires_after="2025-08-06">
+    enum="NudgedUpdateResult" expires_after="2025-10-05">
   <owner>rushans@google.com</owner>
   <owner>treib@chromium.org</owner>
   <summary>
@@ -1456,7 +1456,7 @@
 </histogram>
 
 <histogram name="Sync.PasswordsBatchUpload.Count" units="passwords"
-    expires_after="2025-08-06">
+    expires_after="2025-10-05">
   <owner>ankushkush@google.com</owner>
   <owner>src/components/sync/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml
index 243da83..4622455 100644
--- a/tools/metrics/histograms/metadata/tab/histograms.xml
+++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -1221,7 +1221,7 @@
 </histogram>
 
 <histogram name="TabGroups.Sync.RemoteActiveTabGroupCount.{NumberOfDays}Day"
-    units="groups" expires_after="2025-08-03">
+    units="groups" expires_after="2025-10-05">
   <owner>shaktisahu@chromium.org</owner>
   <owner>clank-tab-dev@google.com</owner>
   <summary>
@@ -1504,7 +1504,7 @@
 </histogram>
 
 <histogram name="TabGroups.Sync.TimeSinceLastUserInteractionWithGroup"
-    units="minutes" expires_after="2025-08-03">
+    units="minutes" expires_after="2025-10-05">
   <owner>shaktisahu@chromium.org</owner>
   <owner>clank-tab-dev@google.com</owner>
   <summary>
@@ -1704,7 +1704,7 @@
 </histogram>
 
 <histogram name="TabManager.Discarding.InactiveToReloadTime" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>chrisha@chromium.org</owner>
   <owner>catan-team@chromium.org</owner>
   <summary>
@@ -1807,7 +1807,7 @@
 </histogram>
 
 <histogram name="Tabs.ArchivedTabs.MaxLimitReachedAt" units="count"
-    expires_after="2025-07-06">
+    expires_after="2025-10-05">
   <owner>wylieb@google.com</owner>
   <owner>clank-tab-dev@google.com</owner>
   <summary>
@@ -2923,7 +2923,7 @@
 </histogram>
 
 <histogram name="Tabs.TabSearch.Mojo.TabUpdated" units="ms"
-    expires_after="2025-07-08">
+    expires_after="2025-10-05">
   <owner>kerenzhu@chromium.org</owner>
   <owner>romanarora@chromium.org</owner>
   <owner>yuhengh@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/trusted_vault/histograms.xml b/tools/metrics/histograms/metadata/trusted_vault/histograms.xml
index 4291025..0fc75e2 100644
--- a/tools/metrics/histograms/metadata/trusted_vault/histograms.xml
+++ b/tools/metrics/histograms/metadata/trusted_vault/histograms.xml
@@ -78,7 +78,7 @@
 <histogram
     name="TrustedVault.DownloadAuthenticationFactorsRegistrationState{SecurityDomainId}"
     enum="DownloadAuthenticationFactorsRegistrationStateResult"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>agl@google.com</owner>
   <owner>mmoskvitin@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml
index 62e0da5..4e1147d 100644
--- a/tools/metrics/histograms/metadata/v8/histograms.xml
+++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -1098,7 +1098,7 @@
 </histogram>
 
 <histogram name="V8.GC.Cycle{Priority}.MainThread.Full.Incremental.Mark"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>nikolaos@chromium.org</owner>
   <owner>v8-memory-sheriffs@google.com</owner>
   <summary>
@@ -2055,7 +2055,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeExecute" units="microseconds"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2067,7 +2067,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeFinalize" units="microseconds"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2079,7 +2079,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeForOnStackReplacementExecute"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2092,7 +2092,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeForOnStackReplacementFinalize"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2105,7 +2105,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeForOnStackReplacementPrepare"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2118,7 +2118,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizeForOnStackReplacementTotalTime"
-    units="microseconds" expires_after="2025-08-03">
+    units="microseconds" expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2143,7 +2143,7 @@
 </histogram>
 
 <histogram name="V8.TurboFanOptimizePrepare" units="microseconds"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>tebbi@chromium.org</owner>
   <owner>mslekova@chromium.org</owner>
   <summary>
@@ -2220,7 +2220,7 @@
   </summary>
 </histogram>
 
-<histogram name="V8.WasmCacheCount" units="count" expires_after="2025-08-03">
+<histogram name="V8.WasmCacheCount" units="count" expires_after="2025-10-05">
   <owner>ahaas@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
@@ -2278,7 +2278,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileHugeFunctionMilliSeconds" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>clemensb@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
@@ -2290,7 +2290,7 @@
 </histogram>
 
 <histogram name="V8.WasmCompileHugeFunctionPeakMemoryBytes" units="bytes"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>clemensb@chromium.org</owner>
   <owner>ecmziegler@chromium.org</owner>
   <owner>wasm-v8@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml
index 103441d..3ba28cf3 100644
--- a/tools/metrics/histograms/metadata/web_apk/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -93,7 +93,7 @@
 </histogram>
 
 <histogram name="WebApk.Install.InstallEvent" enum="WebApkInstallEvent"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>hartmanng@chromium.org</owner>
   <owner>src/chrome/android/webapk/OWNERS</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/web_audio/histograms.xml b/tools/metrics/histograms/metadata/web_audio/histograms.xml
index 41c89073..c94b7731 100644
--- a/tools/metrics/histograms/metadata/web_audio/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_audio/histograms.xml
@@ -107,7 +107,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioContext.HardwareSampleRate" units="Hz"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -132,7 +132,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioContext.latencyHintMilliSeconds" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -182,7 +182,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioContextOptions.sampleRate" units="Hz"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -206,7 +206,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioDestination.CallbackBufferSize" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -219,7 +219,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioDestination.HardwareBufferSize" units="units"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -230,7 +230,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioDestination.HardwareOutputLatency" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -242,7 +242,7 @@
 </histogram>
 
 <histogram name="WebAudio.AudioDestination.{ModeTag}.FIFODelay{LatencyTag}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -259,7 +259,7 @@
 
 <histogram
     name="WebAudio.AudioDestination.{ModeTag}.FIFOUnderrunCount{Duration}{LatencyTag}"
-    units="underruns" expires_after="2025-08-03">
+    units="underruns" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -279,7 +279,7 @@
 
 <histogram
     name="WebAudio.AudioDestination.{ModeTag}.RenderTimeRatio{LatencyTag}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -293,7 +293,7 @@
 
 <histogram
     name="WebAudio.AudioDestination.{ModeTag}.RequestRenderGapTimeRatio{LatencyTag}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -308,7 +308,7 @@
 
 <histogram
     name="WebAudio.AudioDestination.{ModeTag}.RequestRenderTimeRatio{LatencyTag}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -322,7 +322,7 @@
 
 <histogram
     name="WebAudio.AudioDestination.{ModeTag}.TotalPlayoutDelay{LatencyTag}"
-    units="ms" expires_after="2025-08-03">
+    units="ms" expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -456,7 +456,7 @@
 </histogram>
 
 <histogram name="WebAudio.PushPullFIFO.UnderflowGlitches" enum="Boolean"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
@@ -468,7 +468,7 @@
 </histogram>
 
 <histogram name="WebAudio.PushPullFIFO.UnderflowPercentage" units="%"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>mjwilson@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <owner>src/third_party/blink/renderer/modules/webaudio/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index fad7b83..2ea7b98 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -770,7 +770,7 @@
   </summary>
 </histogram>
 
-<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2025-08-03">
+<histogram name="WebRTC.BWE.InitialRtt" units="ms" expires_after="2025-10-05">
   <owner>holmer@chromium.org</owner>
   <summary>
     The round-trip time as measured 2 seconds into a WebRTC call.
@@ -778,7 +778,7 @@
 </histogram>
 
 <histogram name="WebRTC.BWE.InitialVsConvergedDiff" units="kbps"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>holmer@chromium.org</owner>
   <summary>
     The difference between the bandwidth estimate at 2 seconds and 20 seconds
@@ -902,7 +902,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.AudioBitrateReceivedInKbps" units="kbps"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average audio bitrate received during a call, counted from first packet
@@ -932,7 +932,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.LifetimeInSeconds" units="seconds"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>asapersson@chromium.org</owner>
   <summary>
     The lifetime of a call. Recorded when a Call instance is destroyed.
@@ -950,7 +950,7 @@
 </histogram>
 
 <histogram name="WebRTC.Call.RtcpBitrateReceivedInBps" units="bits/s"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>holmer@chromium.org</owner>
   <summary>
     Average RTCP bitrate received during a call, counted from first packet
@@ -1093,7 +1093,7 @@
 </histogram>
 
 <histogram name="WebRTC.DesktopCapture.RefreshRate.{CapturerType}" units="fps"
-    expires_after="2025-08-04">
+    expires_after="2025-10-05">
   <owner>henrika@chromium.org</owner>
   <owner>webrtc-dev@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index 85b0226..ae1fbabc 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -1227,7 +1227,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.InstallError"
-    enum="IsolatedWebAppInstallError" expires_after="2025-08-03">
+    enum="IsolatedWebAppInstallError" expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1239,7 +1239,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.InstallSuccess" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1318,7 +1318,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.OrphanedBundlesCleanupJobSuccess"
-    enum="BooleanValid" expires_after="2025-08-03">
+    enum="BooleanValid" expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1330,7 +1330,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.ReadResponseHeadError"
-    enum="IsolatedWebAppReadResponseHeadError" expires_after="2025-08-03">
+    enum="IsolatedWebAppReadResponseHeadError" expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1344,7 +1344,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.ReadResponseHeadSuccess" enum="BooleanSuccess"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1361,7 +1361,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.ResponseReaderCacheState"
-    enum="IsolatedWebAppResponseReaderCacheState" expires_after="2025-08-03">
+    enum="IsolatedWebAppResponseReaderCacheState" expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1379,7 +1379,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.SignatureVerificationDuration" units="ms"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1392,7 +1392,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.SignatureVerificationFileLength" units="MiB"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
@@ -1419,7 +1419,7 @@
 </histogram>
 
 <histogram name="WebApp.Isolated.SwbnFileUsabilitySuccess" enum="BooleanValid"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>giovax@chromium.org</owner>
   <owner>pwa-commercial@google.com</owner>
   <owner>src/chrome/browser/web_applications/isolated_web_apps/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml
index e4fa333..4ca855f 100644
--- a/tools/metrics/histograms/metadata/webauthn/histograms.xml
+++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -304,7 +304,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.EnclaveLoadDuration" units="ms"
-    expires_after="2025-07-31">
+    expires_after="2025-10-05">
   <owner>kenrb@chromium.org</owner>
   <owner>chrome-webauthn@google.com</owner>
   <summary>
diff --git a/tools/metrics/histograms/metadata/windows/histograms.xml b/tools/metrics/histograms/metadata/windows/histograms.xml
index 458ce4c65..840467a 100644
--- a/tools/metrics/histograms/metadata/windows/histograms.xml
+++ b/tools/metrics/histograms/metadata/windows/histograms.xml
@@ -351,7 +351,7 @@
 </histogram>
 
 <histogram name="Windows.Win11HardwareRequirements.{Type}Check"
-    enum="BooleanEnabled" expires_after="2025-08-03">
+    enum="BooleanEnabled" expires_after="2025-10-05">
   <owner>estalin@chromium.org</owner>
   <owner>davidbienvenu@chromium.org</owner>
   <summary>
@@ -368,7 +368,7 @@
 </histogram>
 
 <histogram name="Windows.Win11UpgradeEligible" enum="BooleanEnabled"
-    expires_after="2025-08-03">
+    expires_after="2025-10-05">
   <owner>estalin@chromium.org</owner>
   <owner>davidbienvenu@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml
index 3841f1241..26a2bb8d 100644
--- a/tools/metrics/ukm/ukm.xml
+++ b/tools/metrics/ukm/ukm.xml
@@ -18192,6 +18192,13 @@
     <summary>
       Records how the user interacted with a saving prompt.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Saving.Prompt.Shown" enum="Boolean">
     <summary>
@@ -18282,6 +18289,13 @@
     <summary>
       Records how the user interacted with an updating prompt.
     </summary>
+    <aggregation>
+      <history>
+        <statistics>
+          <enumeration/>
+        </statistics>
+      </history>
+    </aggregation>
   </metric>
   <metric name="Updating.Prompt.Shown" enum="Boolean">
     <summary>
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml
index 2696694..3aace8fe 100644
--- a/ui/android/java/res/values/color_palette.xml
+++ b/ui/android/java/res/values/color_palette.xml
@@ -25,6 +25,7 @@
     <color name="baseline_primary_40_alpha_65" tools:ignore="UnusedResources">#6A0B57D0</color>
     <color name="baseline_primary_30">#0842A0</color>
     <color name="baseline_primary_20">#062E6F</color>
+    <color name="baseline_primary_20_alpha_38">#61062E6F</color>
     <color name="baseline_primary_10">#041E49</color>
     <color name="baseline_neutral_100">@android:color/white</color>
     <color name="baseline_neutral_100_with_surface_tint_light_alpha_5" tools:ignore="UnusedResources">#F7F9FC</color>
diff --git a/v8 b/v8
index bd4ded6..35721b0 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit bd4ded6cee0c3cbd1106937be7a43116671692b2
+Subproject commit 35721b006fd74c1d7a316f9dff47376c0a4d0dab