diff --git a/DEPS b/DEPS
index 8e1321db..6f3b709 100644
--- a/DEPS
+++ b/DEPS
@@ -308,7 +308,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'src_internal_revision': '20987331c080610f354e4a0a7fbd4a5b71fd6624',
+  'src_internal_revision': '631be088f7fe566bcac84cc5b619c5784cdb6195',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
@@ -316,11 +316,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '80acc26727d5a34e77dabeebe7c9213ec1bd4768',
+  'v8_revision': 'e858bb3a89e0b1e8f5fd701c5687a60de6b4964f',
   # 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': 'c4fe7abe14469bafce44bc4e9502e84c458d4801',
+  'angle_revision': '1e01eea083a0e03e1a3b7581d2a600e608d46430',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -360,7 +360,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling freetype
   # and whatever else without interference from each other.
-  'freetype_revision': '32fc0af22206327ffd06e1d025f13b11fd8d1a46',
+  'freetype_revision': '85161d762262ce7a5bec3763e316d58f75c0b06e',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling HarfBuzz
   # and whatever else without interference from each other.
@@ -400,7 +400,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': '7d26bddc0d06cd6a294663fd23d0918e6ad33475',
+  'devtools_frontend_revision': '6c0aaacf6c509885ab267e5f7adb78252c2a386b',
   # 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.
@@ -424,7 +424,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': '518caee86914cb4346f7f82a90c3ab99b7f84532',
+  'dawn_revision': 'fa54d1eaf3f0184b44aa243972dbbc2aac6ee02d',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1115,10 +1115,10 @@
     'condition': 'non_git_source',
     'objects': [
       {
-        'object_name': 'meet-gpu-tests/836998641.tar.gz',
-        'sha256sum': '01c2bdc145047c00457e3c71088123f8342596f06f86f3971a061e5f92007db0',
-        'size_bytes': 279898707,
-        'generation': 1764232019101433,
+        'object_name': 'meet-gpu-tests/839157042.tar.gz',
+        'sha256sum': '468eecbe3b9416f7a4828ac83aedc9f78ebd9319462efc36794b6c5979742d0c',
+        'size_bytes': 279897361,
+        'generation': 1764672551757213,
       },
     ],
   },
@@ -1206,7 +1206,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': '2it76cjLdPaCbfU_n1nHToxGA9Yqb6oDjoMjvjkBkeUC',
+              'version': 'uOmVKMsuMkvBy455CW-KkxrbPo7dwq8s86TpizYCGkoC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1217,7 +1217,7 @@
       'packages': [
           {
               'package': 'chromium/android_webview/tools/orderfiles/arm',
-              'version': '_4uvw-BnNaJItX2a3LgLJqofccyB-mMNAYHSLC8MXL8C',
+              'version': '1TyiTMnBUhwQCorhkKFNw2SMw43NPEd1Q2IWoDRSsWwC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1613,7 +1613,7 @@
     'packages': [
       {
         'package': 'chromium/chrome/test/data/variations/cipd',
-        'version': 'Su70hwhseutRCC8sRZccSvzz097YZLRXoPGGsEao4iIC',
+        'version': 'fLSSpaTSKyEyNPEXwXYLs4z4igepXfD1r5oNqYScRNAC',
       },
     ],
     'dep_type': 'cipd',
@@ -1624,7 +1624,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '9c5c23a8cfe0538d87debe05f72e848c017b3121',
+    '2719afc3e384f88d83a0ce8b2cb29ab09214dbbc',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -2610,7 +2610,7 @@
     Var('pdfium_git') + '/pdfium.git' + '@' +  Var('pdfium_revision'),
 
   'src/third_party/perfetto':
-    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + 'f67fc0ed0a168a0d80b35d07215c8fed2735d7d3',
+    Var('chromium_git') + '/external/github.com/google/perfetto.git' + '@' + '26c98304146c6bcbda4f96066dfecdd28040777d',
 
   'src/base/tracing/test/data': {
     'bucket': 'perfetto',
@@ -2935,7 +2935,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@d96e0682f2c04a2e4b1d847c125d561a1a74e763',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@577557704db92682fbcb2d972d7bef783bf890f8',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@b5782e52ee2f7b3e40bb9c80d15b47016e008bc9',
   '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@b824a462d4256d720bebb40e78b9eb8f78bbb305',
@@ -2944,7 +2944,7 @@
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@e042a3a16bdf37e8c9d61b95b7a5933bccef0f45',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@48b5d246b2d0b1a41ee7ea1b69525ae7bb38a2ae',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@c010c19e796035e92fb3b0462cb887518a41a7c1',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@e1c92ec6cd2be77ef1fc2a0a0dabd432a1bccca7',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@b464a4655348cba4b168f7da993633d57d300692',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50',
@@ -2987,7 +2987,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'f680c1893f3b166b370439da52ae82d02f54969c',
+    Var('webrtc_git') + '/src.git' + '@' + 'b1e92cbead156841b29177be818b5aabbe194853',
 
   # 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.
@@ -3131,7 +3131,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'TFem2taXy7hamrLkbG6s4SuH0ACO61FStRL8l3Z58XMC',
+        'version': 'PBW18lzlKDBRJqM6ea0q51Y-XrtGLzPD7yoPvjUnu1kC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3175,7 +3175,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'cNbjxl70Rv2wHiWRPibMEUDnwJBlQRzkblv2jb-XURQC',
+        'version': 'hiHQeMjEMh2Zk8d9iKaKjexX7kQdkdEw5DhuXs6woygC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/WATCHLISTS b/WATCHLISTS
index 8f08bf6..d06edb68 100644
--- a/WATCHLISTS
+++ b/WATCHLISTS
@@ -1964,9 +1964,6 @@
       'filepath': 'chrome/browser/resources/print_preview/' \
                   '|chrome/browser/ui/webui/print_preview/'
     },
-    'privacy_budget': {
-      'filepath': 'privacy_budget',
-    },
     'privacy_guide_desktop': {
       'filepath': 'chrome/browser/resources/settings/privacy_page/privacy_guide/' \
                   '|chrome/test/data/webui/settings/privacy_guide*',
@@ -3258,7 +3255,6 @@
     'presentation': ['mfoltz+watch-media@chromium.org'],
     'preview_features': ['chrome-lite-pages+watch@google.com'],
     'print_preview': ['print-reviews+preview@chromium.org'],
-    'privacy_budget': ['antoniosartori+watch-privacy_budget@chromium.org'],
     'privacy_guide_desktop': ['rainhard+watch@chromium.org'],
     'private_aggregation': ['alexmt+watch@chromium.org'],
     'profile_keyed_service': ['rsult@google.com'],
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 849ac9ce..f2108bd36 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
@@ -4597,11 +4597,13 @@
     getter checked
     getter command
     getter commandForElement
+    getter defaultChecked
     getter disabled
     method constructor
     setter checked
     setter command
     setter commandForElement
+    setter defaultChecked
     setter disabled
 interface HTMLMenuListElement : HTMLElement
     attribute @@toStringTag
diff --git a/cc/debug/picture_debug_util.cc b/cc/debug/picture_debug_util.cc
index 17e053a..243e890e 100644
--- a/cc/debug/picture_debug_util.cc
+++ b/cc/debug/picture_debug_util.cc
@@ -21,12 +21,13 @@
 
 void PictureDebugUtil::SerializeAsBase64(const SkPicture* picture,
                                          std::string* output) {
-  SkSerialProcs procs{.fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
-    // Note: if the picture contains texture-backed (gpu) images, they will fail
-    // to be read-back and therefore fail to be encoded unless we can thread the
-    // correct GrDirectContext through to here.
-    return skia::EncodePngAsSkData(nullptr, img);
-  }};
+  SkSerialProcs procs{
+      .fImageProc = [](SkImage* img, void*) -> SkSerialReturnType {
+        // Note: if the picture contains texture-backed (gpu) images, they will
+        // fail to be read-back and therefore fail to be encoded unless we can
+        // thread the correct GrDirectContext through to here.
+        return skia::EncodePngAsSkData(nullptr, img);
+      }};
   sk_sp<SkData> data = picture->serialize(&procs);
   *output = base::Base64Encode(
       std::string_view(static_cast<const char*>(data->data()), data->size()));
diff --git a/cc/paint/paint_image_generator.h b/cc/paint/paint_image_generator.h
index e3d3ac5..0d2adc37 100644
--- a/cc/paint/paint_image_generator.h
+++ b/cc/paint/paint_image_generator.h
@@ -29,7 +29,7 @@
   PaintImageGenerator& operator=(const PaintImageGenerator&) = delete;
 
   // Returns a reference to the encoded content of this image.
-  virtual sk_sp<SkData> GetEncodedData() const = 0;
+  virtual sk_sp<const SkData> GetEncodedData() const = 0;
 
   // Decode into the given SkPixmap. This will modify the pixels pointed to by
   // `dst_pixmap`, but will not modify any of its properties (e.g, its
diff --git a/cc/paint/skia_paint_image_generator.cc b/cc/paint/skia_paint_image_generator.cc
index 3fc73d82..6c7eca5 100644
--- a/cc/paint/skia_paint_image_generator.cc
+++ b/cc/paint/skia_paint_image_generator.cc
@@ -21,7 +21,7 @@
 
 SkiaPaintImageGenerator::~SkiaPaintImageGenerator() = default;
 
-sk_sp<SkData> SkiaPaintImageGenerator::onRefEncodedData() {
+sk_sp<const SkData> SkiaPaintImageGenerator::onRefEncodedData() {
   return paint_image_generator_->GetEncodedData();
 }
 
diff --git a/cc/paint/skia_paint_image_generator.h b/cc/paint/skia_paint_image_generator.h
index 8918b26..df07a99 100644
--- a/cc/paint/skia_paint_image_generator.h
+++ b/cc/paint/skia_paint_image_generator.h
@@ -22,7 +22,7 @@
 
   SkiaPaintImageGenerator& operator=(const SkiaPaintImageGenerator&) = delete;
 
-  sk_sp<SkData> onRefEncodedData() override;
+  sk_sp<const SkData> onRefEncodedData() override;
   bool onGetPixels(const SkImageInfo&,
                    void* pixels,
                    size_t row_bytes,
diff --git a/cc/test/fake_paint_image_generator.cc b/cc/test/fake_paint_image_generator.cc
index 06e7080..32cdf53 100644
--- a/cc/test/fake_paint_image_generator.cc
+++ b/cc/test/fake_paint_image_generator.cc
@@ -41,7 +41,7 @@
 
 FakePaintImageGenerator::~FakePaintImageGenerator() = default;
 
-sk_sp<SkData> FakePaintImageGenerator::GetEncodedData() const {
+sk_sp<const SkData> FakePaintImageGenerator::GetEncodedData() const {
   return SkData::MakeEmpty();
 }
 
diff --git a/cc/test/fake_paint_image_generator.h b/cc/test/fake_paint_image_generator.h
index 6fc2e456..8c83249 100644
--- a/cc/test/fake_paint_image_generator.h
+++ b/cc/test/fake_paint_image_generator.h
@@ -34,7 +34,7 @@
   FakePaintImageGenerator& operator=(const FakePaintImageGenerator&) = delete;
 
   // PaintImageGenerator implementation.
-  sk_sp<SkData> GetEncodedData() const override;
+  sk_sp<const SkData> GetEncodedData() const override;
   bool GetPixels(SkPixmap pixmap,
                  size_t frame_index,
                  PaintImage::GeneratorClientId client_id,
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index a98156b..1840cb9 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -2400,7 +2400,6 @@
       "//chrome/browser/ui/android/webid/internal:javatests",
       "//chrome/browser/ui/plus_addresses/android:javatests",
       "//components/embedder_support/android:virtual_structure_javatests",
-      "//components/ip_protection/android/android_auth_client_lib/javatests:ip_protection_auth_javatests",
     ]
 
     if (is_desktop_android) {
@@ -2420,7 +2419,6 @@
     additional_apks = [
       "//chrome/android/webapk/shell_apk:javatests_webapk",
       "//chrome/test/android/chrome_public_test_support:chrome_public_test_support_apk",
-      "//components/ip_protection/android/android_auth_client_lib/testing/mock_service:ip_protection_auth_test_service_apk",
       "//components/media_router/test/android/media_router_test_support:media_router_test_support_apk",
     ]
 
@@ -3295,7 +3293,6 @@
       "//chrome/browser/supervised_user:test_support",
       "//components/crash/android:crash_android",
       "//components/external_intents/android:test_support",
-      "//components/ip_protection/android/android_auth_client_lib/cpp:ip_protection_auth_test_natives",
       "//components/minidump_uploader",
       "//components/paint_preview/player/android:test_support",
       "//components/sync",
diff --git a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
index b2c1641..256dc80 100644
--- a/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
+++ b/chrome/android/feed/core/java/src/org/chromium/chrome/browser/feed/FeedSurfaceCoordinator.java
@@ -566,7 +566,8 @@
                         }
                     };
 
-            mNtpCustomizationConfigManager.addListener(mHomepageStateListener, activity);
+            mNtpCustomizationConfigManager.addListener(
+                    mHomepageStateListener, activity, /* skipNotify= */ false);
         } else {
             setBackgroundColor(mDefaultBackgroundColor);
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index c703703f..29eeb93 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -308,6 +308,7 @@
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
 import org.chromium.chrome.browser.xr.scenecore.XrSceneCoreSessionInitializerImpl;
 import org.chromium.chrome.browser.xr.scenecore.XrSceneCoreSessionManagerImpl;
+import org.chromium.components.browser_ui.accessibility.AccessibilityFeatureMap;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
 import org.chromium.components.browser_ui.share.ShareParams;
 import org.chromium.components.browser_ui.util.BrowserControlsVisibilityDelegate;
@@ -3396,6 +3397,13 @@
     }
 
     @Override
+    public boolean shouldDisableVerticalScrollbar() {
+        // The vertical scrollbar causes buttons at the edge of the app menu to not receive any
+        // hover effects.
+        return AccessibilityFeatureMap.sAndroidZoomIndicator.isEnabled();
+    }
+
+    @Override
     public AppMenuPropertiesDelegate createAppMenuPropertiesDelegate() {
         return new TabbedAppMenuPropertiesDelegate(
                 this,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWindow.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWindow.java
index 055ecc0..8eddd6f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeWindow.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeWindow.java
@@ -119,7 +119,6 @@
 
     @Override
     public ModalDialogManager getModalDialogManager() {
-        // TODO(crbug.com/40160045): Move ModalDialogManager to UnownedUserData.
         return mModalDialogManagerSupplier.get();
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index 4d966156..4b3b238 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -2411,9 +2411,6 @@
 
             // On automotive, ignore density changes to prevent Chrome from exiting fullscreen.
             // See https://crbug.com/352816133.
-            // TODO(https://crbug.com/354039289): densityDpi is overridden on the Configuration so
-            // changes to densityDpi won't show up in the newConfig. Once Chrome migrates to adapt
-            // app, test this flow again.
             if (newConfig.densityDpi != mConfig.densityDpi) {
                 if (!DeviceInfo.isAutomotive()) {
                     doRecreateActivity();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
index d1c90696..ebb49f9 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/NewTabPage.java
@@ -859,7 +859,8 @@
                                 /* applyWhiteBackgroundOnSearchBox= */ false);
                     }
                 };
-        NtpCustomizationConfigManager.getInstance().addListener(mHomepageStateListener, mContext);
+        NtpCustomizationConfigManager.getInstance()
+                .addListener(mHomepageStateListener, mContext, /* skipNotify= */ false);
     }
 
     /** Initializes whether to use a light tint color on icons of toolbar and status bar. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
index 1d9cfe96..fdc425a2f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/share/LensUtils.java
@@ -14,7 +14,6 @@
 import org.chromium.components.externalauth.ExternalAuthUtils;
 
 /** This class provides utilities for intenting into Google Lens. */
-// TODO(crbug.com/40160855): Consolidate param-checks into a single function.
 @NullMarked
 public class LensUtils {
     private static final String LOG_UKM_PARAM_NAME = "logUkm";
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java
index 7124453..9efe8f0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninBridge.java
@@ -6,7 +6,7 @@
 
 import static org.chromium.build.NullUtil.assumeNonNull;
 
-import android.accounts.AccountManager;
+import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.content.Context;
 import android.content.Intent;
@@ -16,7 +16,6 @@
 import org.jni_zero.CalledByNative;
 import org.jni_zero.JniType;
 
-import org.chromium.base.Callback;
 import org.chromium.base.ThreadUtils;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
@@ -43,14 +42,10 @@
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
 import org.chromium.components.signin.GAIAServiceType;
-import org.chromium.components.signin.SigninFeatureMap;
-import org.chromium.components.signin.SigninFeatures;
 import org.chromium.components.signin.base.AccountInfo;
-import org.chromium.components.signin.browser.WebSigninTrackerResult;
 import org.chromium.components.signin.identitymanager.IdentityManager;
 import org.chromium.components.signin.metrics.AccountConsistencyPromoAction;
 import org.chromium.components.signin.metrics.SigninAccessPoint;
-import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
@@ -91,24 +86,19 @@
     /**
      * Starts a flow to add a Google account to the device.
      *
-     * @param tab The target tab for the continueUrl navigation.
+     * @param windowAndroid The window to use for the flow.
      * @param prefilledEmail The email address to prefill in the add account flow, or null if no
      *     email should be prefilled.
      * @param continueUrl The URL to navigate to after the account is added.
      */
+    // TODO(crbug.com/432009825): Remove when the redirection will be implemented.
+    @SuppressLint("UnusedVariable")
     @CalledByNative
     private static void startAddAccountFlow(
-            Tab tab,
+            WindowAndroid windowAndroid,
             @Nullable @JniType("std::string") String prefilledEmail,
             @JniType("GURL") GURL continueUrl) {
         ThreadUtils.assertOnUiThread();
-        WindowAndroid windowAndroid = tab.getWindowAndroid();
-        if (windowAndroid == null || !tab.isUserInteractable()) {
-            // The page is opened in the background, ignore the header. See
-            // https://crbug.com/1145031#c5 and https://crbug.com/323424409 for details.
-            return;
-        }
-        GURL initialTabURL = tab.getUrl();
         AccountManagerFacade accountManagerFacade = AccountManagerFacadeProvider.getInstance();
         accountManagerFacade.createAddAccountIntent(
                 prefilledEmail,
@@ -125,55 +115,13 @@
                     windowAndroid.showIntent(
                             intent,
                             (int resultCode, @Nullable Intent data) -> {
-                                @Nullable String addedAccountEmail =
-                                        data == null
-                                                ? prefilledEmail
-                                                : data.getStringExtra(
-                                                        AccountManager.KEY_ACCOUNT_NAME);
-                                if (SigninFeatureMap.isEnabled(
-                                                SigninFeatures.ENABLE_ADD_SESSION_REDIRECT)
-                                        && resultCode == Activity.RESULT_OK) {
-                                    waitForCookiesAndRedirect(
-                                            tab, addedAccountEmail, continueUrl, initialTabURL);
-                                }
+                                // TODO(crbug.com/432009825): Wait for the Cookies to be available,
+                                // and navigate to the continue URL.
                             },
                             null);
                 });
     }
 
-    /**
-     * Redirects to the continueUrl in the given tab if refresh tokens and cookies are minted for
-     * the account associated with the prefilledEmail.
-     */
-    private static void waitForCookiesAndRedirect(
-            Tab tab, @Nullable String prefilledEmail, GURL continueUrl, GURL initialTabURL) {
-        assert prefilledEmail != null;
-        new WebSigninBridge.Factory()
-                .createWithEmail(
-                        tab.getProfile(),
-                        prefilledEmail,
-                        createWebSigninBridgeCallback(tab, continueUrl, initialTabURL));
-    }
-
-    private static Callback<@WebSigninTrackerResult Integer> createWebSigninBridgeCallback(
-            Tab tab, GURL continueUrl, GURL initialTabURL) {
-        return (result) -> {
-            ThreadUtils.assertOnUiThread();
-            switch (result) {
-                case WebSigninTrackerResult.SUCCESS:
-                    if (!tab.isDestroyed() && tab.getUrl().equals(initialTabURL)) {
-                        tab.loadUrl(new LoadUrlParams(continueUrl));
-                    }
-                    break;
-                // TODO(crbug.com/456445865): Handle cases where WebSigninTracker returns an error.
-                case WebSigninTrackerResult.AUTH_ERROR:
-                    break;
-                case WebSigninTrackerResult.OTHER_ERROR:
-                    break;
-            }
-        };
-    }
-
     /** Opens account management screen. */
     @CalledByNative
     private static void openAccountManagementScreen(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java
index a1f838d..f078c24 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedTilesMediator.java
@@ -114,7 +114,8 @@
                         updateMvtVisibility();
                     }
                 };
-        NtpCustomizationConfigManager.getInstance().addListener(mMvtVisibilityListener, mContext);
+        NtpCustomizationConfigManager.getInstance()
+                .addListener(mMvtVisibilityListener, mContext, /* skipNotify= */ false);
     }
 
     /** Called to initialize this mediator when native is ready. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
index 4a80764d..7f9dbbae 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/system/StatusBarColorController.java
@@ -333,7 +333,8 @@
                         onBackgroundImageChangedImpl();
                     }
                 };
-        ntpCustomizationConfigManager.addListener(mHomepageStateListener, context);
+        ntpCustomizationConfigManager.addListener(
+                mHomepageStateListener, context, /* skipNotify= */ false);
     }
 
     /** Called when the background image of the NTP has changed. */
diff --git a/chrome/android/javatests/BUILD.gn b/chrome/android/javatests/BUILD.gn
index 9d24740d..7c3c1aa 100644
--- a/chrome/android/javatests/BUILD.gn
+++ b/chrome/android/javatests/BUILD.gn
@@ -1312,6 +1312,7 @@
     "src/org/chromium/chrome/browser/tab/TabContextMenuItemDelegateTest.java",
     "src/org/chromium/chrome/browser/tab/TabImplPWATest.java",
     "src/org/chromium/chrome/browser/tab/TabImplTest.java",
+    "src/org/chromium/chrome/browser/tab/TabMediaIndicatorTest.java",
     "src/org/chromium/chrome/browser/tab/TabStateTest.java",
     "src/org/chromium/chrome/browser/tab/TabUmaTest.java",
     "src/org/chromium/chrome/browser/tab/TabViewManagerTest.java",
@@ -1330,6 +1331,11 @@
     "src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImplTest.java",
   ]
 
+  data = [
+    "//chrome/test/data/media/tab_media_indicator.html",
+    "//chrome/test/data/media/bigbuck.webm",
+  ]
+
   deps = [ ":chrome_test_java_helper" ]
 }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/init/LaunchFailedActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/init/LaunchFailedActivityTest.java
index 3e707e08..9cf1265 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/init/LaunchFailedActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/init/LaunchFailedActivityTest.java
@@ -20,6 +20,7 @@
 import org.chromium.base.library_loader.ProcessInitException;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.DisableIf;
+import org.chromium.base.test.util.DisabledTest;
 import org.chromium.base.test.util.DoNotBatch;
 import org.chromium.chrome.browser.base.SplitCompatApplication;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
@@ -47,6 +48,7 @@
 
     @Test
     @SmallTest
+    @DisabledTest(message = "This test is flaky. See crbug.com/465393381.")
     public void testLaunchFailedWithoutCallbackRaisesProcessInitException() {
         LibraryLoader.getInstance().resetForTesting();
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabMediaIndicatorTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabMediaIndicatorTest.java
new file mode 100644
index 0000000..4458a8a
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/TabMediaIndicatorTest.java
@@ -0,0 +1,168 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.tab;
+
+import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE;
+
+import androidx.test.filters.SmallTest;
+
+import org.hamcrest.Matchers;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.util.Batch;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.Criteria;
+import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.Restriction;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.transit.ChromeTransitTestRules;
+import org.chromium.chrome.test.transit.FreshCtaTransitTestRule;
+import org.chromium.chrome.test.transit.page.WebPageStation;
+import org.chromium.chrome.test.util.browser.TabLoadObserver;
+import org.chromium.content_public.browser.test.util.DOMUtils;
+import org.chromium.media.MediaSwitches;
+
+import java.util.List;
+
+/** Tests for {@link Tab.MediaState}. */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({
+    ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE,
+    MediaSwitches.AUTOPLAY_NO_GESTURE_REQUIRED_POLICY,
+    "enable-features=EnableAudioMonitoringOnAndroid",
+})
+@Batch(Batch.PER_CLASS)
+@Restriction(RESTRICTION_TYPE_NON_LOW_END_DEVICE)
+public class TabMediaIndicatorTest {
+    @Rule
+    public FreshCtaTransitTestRule mActivityTestRule =
+            ChromeTransitTestRules.freshChromeTabbedActivityRule();
+
+    private static final String TEST_PATH = "/chrome/test/data/media/tab_media_indicator.html";
+    private static final String VIDEO_ID = "video";
+    private static final long RECENTLY_AUDIBLE_TIMEOUT = 3000;
+
+    public TabModel mTabModel;
+    public Tab mTab;
+
+    // TODO(crbug.com/454045510): Add tests for the other media states (recording, sharing).
+    @Before
+    public void setUp() throws Exception {
+        WebPageStation page = mActivityTestRule.startOnBlankPage();
+        mTabModel = mActivityTestRule.getActivity().getTabModelSelector().getModel(false);
+        mTab = page.getTab();
+
+        new TabLoadObserver(mTab).fullyLoadUrl(mActivityTestRule.getTestServer().getURL(TEST_PATH));
+        DOMUtils.waitForNonZeroNodeBounds(mTab.getWebContents(), VIDEO_ID);
+        Assert.assertEquals(Tab.MediaState.NONE, mTab.getMediaState());
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateAudible() throws Exception {
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateMuted() throws Exception {
+        setMuteState(true);
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.MUTED);
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateMutedThenUnmute() throws Exception {
+        setMuteState(true);
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.MUTED);
+        setMuteState(false);
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateAudibleThenMute() throws Exception {
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+        setMuteState(true);
+        waitForMediaState(Tab.MediaState.MUTED);
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateAudibleMuteWithPause() throws Exception {
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+
+        // Pause video.
+        DOMUtils.pauseMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPauseBeforeEnd(mTab.getWebContents(), VIDEO_ID);
+
+        // Wait for recently audible to update.
+        Thread.sleep(RECENTLY_AUDIBLE_TIMEOUT);
+        waitForMediaState(Tab.MediaState.NONE);
+
+        // Mute video.
+        setMuteState(true);
+        Assert.assertEquals(Tab.MediaState.NONE, mTab.getMediaState());
+
+        // Play the video again.
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.MUTED);
+    }
+
+    @Test
+    @SmallTest
+    public void testMediaStateWithVideoMutedAndUnmuted() throws Exception {
+        DOMUtils.playMedia(mTab.getWebContents(), VIDEO_ID);
+        DOMUtils.waitForMediaPlay(mTab.getWebContents(), VIDEO_ID);
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+
+        // Mute video element.
+        DOMUtils.clickNodeWithJavaScript(mTab.getWebContents(), "muteButton");
+
+        // Wait for recently audible to update.
+        Thread.sleep(RECENTLY_AUDIBLE_TIMEOUT);
+        Assert.assertFalse(DOMUtils.isMediaPaused(mTab.getWebContents(), VIDEO_ID));
+        waitForMediaState(Tab.MediaState.NONE);
+
+        // Unmute video element.
+        DOMUtils.clickNodeWithJavaScript(mTab.getWebContents(), "unmuteButton");
+        waitForMediaState(Tab.MediaState.AUDIBLE);
+    }
+
+    private void waitForMediaState(@Tab.MediaState int expectedState) {
+        CriteriaHelper.pollUiThread(
+                () -> {
+                    Criteria.checkThat(
+                            "Tab media state should be " + expectedState,
+                            mTab.getMediaState(),
+                            Matchers.is(expectedState));
+                });
+    }
+
+    private void setMuteState(boolean mute) {
+        ThreadUtils.runOnUiThreadBlocking(
+                () -> {
+                    mTabModel.setMuteSetting(List.of(mTab), mute);
+                });
+    }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java
index da1894c..9b8fcc6 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/suggestions/tile/MostVisitedMediatorUnitTest.java
@@ -147,7 +147,7 @@
     public void testOnMvtToggleChanged_MvtCustomizationEnabled() {
         createMediator();
         verify(mNtpCustomizationConfigManager)
-                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext));
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(false));
         NtpCustomizationConfigManager.HomepageStateListener listener =
                 mHomepageStateListenerCaptor.getValue();
 
@@ -184,7 +184,7 @@
     public void testOnMvtToggleChanged_MvtCustomizationDisabled() {
         createMediator();
         verify(mNtpCustomizationConfigManager)
-                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext));
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(false));
         NtpCustomizationConfigManager.HomepageStateListener listener =
                 mHomepageStateListenerCaptor.getValue();
 
@@ -519,7 +519,7 @@
     @Features.EnableFeatures(ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_FOR_MVT)
     public void testAddAndRemoveListener_FeatureEnabled() {
         createMediator();
-        verify(mNtpCustomizationConfigManager).addListener(any(), eq(mContext));
+        verify(mNtpCustomizationConfigManager).addListener(any(), eq(mContext), eq(false));
 
         mMediator.destroy();
         verify(mNtpCustomizationConfigManager).removeListener(any());
@@ -529,7 +529,7 @@
     @Features.DisableFeatures(ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_FOR_MVT)
     public void testAddAndRemoveListener_FeatureDisabled() {
         createMediator();
-        verify(mNtpCustomizationConfigManager, never()).addListener(any(), eq(mContext));
+        verify(mNtpCustomizationConfigManager, never()).addListener(any(), eq(mContext), eq(false));
 
         mMediator.destroy();
         verify(mNtpCustomizationConfigManager, never()).removeListener(any());
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 4f2d6e9..a70f62b 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -1946,7 +1946,6 @@
     "//chrome/browser/prefs:util_impl",
     "//chrome/browser/preloading:prefs",
     "//chrome/browser/preloading/search_preload",
-    "//chrome/browser/privacy_budget",
     "//chrome/browser/privacy_sandbox",
     "//chrome/browser/privacy_sandbox:headers",
     "//chrome/browser/profiles",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 3db506e..7233f8c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -6802,14 +6802,6 @@
     {"crostini-gpu-support", flag_descriptions::kCrostiniGpuSupportName,
      flag_descriptions::kCrostiniGpuSupportDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kCrostiniGpuSupport)},
-    {"file-transfer-enterprise-connector",
-     flag_descriptions::kFileTransferEnterpriseConnectorName,
-     flag_descriptions::kFileTransferEnterpriseConnectorDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(features::kFileTransferEnterpriseConnector)},
-    {"file-transfer-enterprise-connector-ui",
-     flag_descriptions::kFileTransferEnterpriseConnectorUIName,
-     flag_descriptions::kFileTransferEnterpriseConnectorUIDescription, kOsCrOS,
-     FEATURE_VALUE_TYPE(features::kFileTransferEnterpriseConnectorUI)},
     {"files-conflict-dialog", flag_descriptions::kFilesConflictDialogName,
      flag_descriptions::kFilesConflictDialogDescription, kOsCrOS,
      FEATURE_VALUE_TYPE(ash::features::kFilesConflictDialog)},
diff --git a/chrome/browser/android/media_state_observer.cc b/chrome/browser/android/media_state_observer.cc
index d490dc7c..b447daa 100644
--- a/chrome/browser/android/media_state_observer.cc
+++ b/chrome/browser/android/media_state_observer.cc
@@ -22,7 +22,6 @@
 };
 }  // namespace
 
-// TODO(crbug.com/454045510): Add tests.
 MediaStateObserver::MediaStateObserver(content::WebContents* web_contents)
     : content::WebContentsObserver(web_contents),
       content::WebContentsUserData<MediaStateObserver>(*web_contents),
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service.cc b/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
index bf7d2bb3..c5bbeb0 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service.cc
@@ -27,9 +27,6 @@
 
 }  // namespace
 
-const char kKioskPrimaryAppInSessionUpdateHistogram[] =
-    "Kiosk.ChromeApp.PrimaryAppInSessionUpdate";
-
 KioskAppUpdateService::KioskAppUpdateService(
     Profile* profile,
     system::AutomaticRebootManager* automatic_reboot_manager)
@@ -57,8 +54,6 @@
 }
 
 void KioskAppUpdateService::StartAppUpdateRestartTimer() {
-  base::UmaHistogramCounts100(kKioskPrimaryAppInSessionUpdateHistogram, 1);
-
   if (restart_timer_.IsRunning()) {
     return;
   }
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service.h b/chrome/browser/ash/app_mode/kiosk_app_update_service.h
index bca858c8..91aa7e9 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service.h
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service.h
@@ -29,8 +29,6 @@
 class AutomaticRebootManager;
 }
 
-extern const char kKioskPrimaryAppInSessionUpdateHistogram[];
-
 // This class enforces automatic restart on app and Chrome updates in app mode.
 class KioskAppUpdateService : public KeyedService,
                               public extensions::UpdateObserver,
diff --git a/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc b/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
index 20ab38c..d1444e33 100644
--- a/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
+++ b/chrome/browser/ash/app_mode/kiosk_app_update_service_browsertest.cc
@@ -184,10 +184,6 @@
   ExtensionTestMessageListener listener("app_update");
   FireAppUpdateAvailable();
   EXPECT_TRUE(listener.WaitUntilSatisfied());
-
-  histogram.ExpectUniqueSample(kKioskPrimaryAppInSessionUpdateHistogram,
-                               /*sample=*/1,
-                               /*expected_bucket_count=*/1);
 }
 
 // Verifies that the app is notified a reboot is required when an OS update is
diff --git a/chrome/browser/ash/app_mode/test/kiosk_iwa_allowlist_browsertest.cc b/chrome/browser/ash/app_mode/test/kiosk_iwa_allowlist_browsertest.cc
index 451fd48..c4fb9544 100644
--- a/chrome/browser/ash/app_mode/test/kiosk_iwa_allowlist_browsertest.cc
+++ b/chrome/browser/ash/app_mode/test/kiosk_iwa_allowlist_browsertest.cc
@@ -11,7 +11,6 @@
 #include "base/task/current_thread.h"
 #include "base/test/gmock_expected_support.h"
 #include "base/test/scoped_feature_list.h"
-#include "base/threading/thread_restrictions.h"
 #include "base/version.h"
 #include "chrome/browser/ash/app_mode/kiosk_app_launch_error.h"
 #include "chrome/browser/ash/app_mode/kiosk_controller.h"
@@ -89,10 +88,11 @@
 
   void SetIwaAllowlist(
       const std::vector<web_package::SignedWebBundleId>& managed_allowlist) {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    EXPECT_THAT(web_app::test::UpdateKeyDistributionInfoWithAllowlist(
-                    base::Version("1.0"), std::move(managed_allowlist)),
-                base::test::HasValue());
+    EXPECT_OK(
+        web_app::test::KeyDistributionComponentBuilder(base::Version("1.0"))
+            .WithManagedAllowlist(managed_allowlist)
+            .Build()
+            .UploadFromComponentFolder());
   }
 
  protected:
diff --git a/chrome/browser/default_browser/default_browser_manager.cc b/chrome/browser/default_browser/default_browser_manager.cc
index 6323126..4dc397d 100644
--- a/chrome/browser/default_browser/default_browser_manager.cc
+++ b/chrome/browser/default_browser/default_browser_manager.cc
@@ -40,7 +40,17 @@
   void StartCheckDefaultClientProgId(
       const std::string& scheme,
       base::OnceCallback<void(const std::u16string&)> callback) override {
-    // TODO(crbug.com/454597910): Implement this feature in shell_integration.
+    auto worker =
+        base::MakeRefCounted<shell_integration::DefaultSchemeClientWorker>(
+            scheme);
+    worker->StartCheckIsDefaultAndGetDefaultClientProgId(base::BindOnce(
+        [](base::OnceCallback<void(const std::u16string&)>
+               prog_id_handle_callback,
+           shell_integration::DefaultWebClientState,
+           const std::u16string& prog_id) {
+          std::move(prog_id_handle_callback).Run(prog_id);
+        },
+        std::move(callback)));
   }
 #endif
 };
diff --git a/chrome/browser/enterprise/idle/idle_service_interactive_uitest.cc b/chrome/browser/enterprise/idle/idle_service_interactive_uitest.cc
index 0ec19df..7e3b31d 100644
--- a/chrome/browser/enterprise/idle/idle_service_interactive_uitest.cc
+++ b/chrome/browser/enterprise/idle/idle_service_interactive_uitest.cc
@@ -5,6 +5,7 @@
 #include <array>
 #include <memory>
 
+#include "base/callback_list.h"
 #include "base/memory/raw_ptr.h"
 #include "base/scoped_observation.h"
 #include "base/task/single_thread_task_runner.h"
@@ -21,11 +22,7 @@
 #include "chrome/browser/enterprise/idle/idle_service.h"
 #include "chrome/browser/policy/profile_policy_connector_builder.h"
 #include "chrome/browser/profiles/profile_manager.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_list_observer.h"
-#include "chrome/browser/ui/browser_window.h"
+#include "chrome/browser/ui/browser_window/public/browser_window_interface.h"
 #include "chrome/browser/ui/browser_window/public/browser_window_interface_iterator.h"
 #include "chrome/browser/ui/idle_bubble.h"
 #include "chrome/browser/ui/profiles/profile_picker.h"
@@ -40,6 +37,7 @@
 #include "chrome/test/base/ui_test_utils.h"
 #include "components/enterprise/idle/idle_pref_names.h"
 #include "components/enterprise/idle/metrics.h"
+#include "components/keep_alive_registry/keep_alive_registry.h"
 #include "components/keep_alive_registry/keep_alive_types.h"
 #include "components/keep_alive_registry/scoped_keep_alive.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
@@ -51,6 +49,7 @@
 #include "content/public/test/test_utils.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/container/flat_hash_map.h"
 #include "ui/base/idle/idle_polling_service.h"
 #include "ui/base/idle/idle_time_provider.h"
 #include "ui/base/ozone_buildflags.h"
@@ -78,28 +77,36 @@
   MOCK_METHOD0(CheckIdleStateIsLocked, bool());
 };
 
-class BrowserCloseWaiter : public BrowserListObserver {
+class BrowserCloseWaiter {
  public:
   explicit BrowserCloseWaiter(
-      std::set<raw_ptr<Browser, SetExperimental>> browsers) {
-    BrowserList::AddObserver(this);
-    waiting_browsers_ = std::move(browsers);
-  }
-
-  // BrowserListObserver:
-  void OnBrowserRemoved(Browser* browser) override {
-    waiting_browsers_.erase(browser);
-    if (waiting_browsers_.size() == 0) {
-      BrowserList::RemoveObserver(this);
-      run_loop_.QuitWhenIdle();
+      std::set<raw_ptr<BrowserWindowInterface, SetExperimental>>
+          browser_window_interfaces) {
+    for (BrowserWindowInterface* browser_window_interface :
+         browser_window_interfaces) {
+      waiting_browsers_.insert(browser_window_interface);
+      browser_close_subscriptions_[browser_window_interface] =
+          browser_window_interface->RegisterBrowserDidClose(base::BindRepeating(
+              &BrowserCloseWaiter::OnBrowserDidClose, base::Unretained(this)));
     }
   }
 
   void Wait() { run_loop_.Run(); }
 
  private:
+  void OnBrowserDidClose(BrowserWindowInterface* browser_window_interface) {
+    waiting_browsers_.erase(browser_window_interface);
+    browser_close_subscriptions_.erase(browser_window_interface);
+    if (waiting_browsers_.empty()) {
+      run_loop_.QuitWhenIdle();
+    }
+  }
+
   base::RunLoop run_loop_;
-  std::set<raw_ptr<Browser, SetExperimental>> waiting_browsers_;
+  std::set<raw_ptr<BrowserWindowInterface, SetExperimental>> waiting_browsers_;
+  absl::flat_hash_map<raw_ptr<BrowserWindowInterface>,
+                      base::CallbackListSubscription>
+      browser_close_subscriptions_;
 };
 
 }  // namespace
@@ -158,7 +165,8 @@
 
     // If there are no active browsers, BrowserProcessImpl::Unpin() runs too
     // early and interrupts test teardown. `keep_alive_` solves this problem.
-    if (chrome::GetTotalBrowserCount() > 0) {
+    if (KeepAliveRegistry::GetInstance()->IsOriginRegistered(
+            KeepAliveOrigin::BROWSER)) {
       // It's safe to release this keepalive here, because browser windows are
       // already doing the same thing.
       keep_alive_.reset();
@@ -225,22 +233,22 @@
         ->IsDialogOpenForTesting();
   }
 
-  void ActivateBrowser(Browser* browser) {
+  void ActivateBrowser(BrowserWindowInterface* browser_window_interface) {
 #if BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE_WAYLAND)
     // TODO(nicolaso): BrowserActivationWaiter times out on Wayland. Figure out
     // why.
 #else
-    ActivateBrowserImpl(browser);
+    ActivateBrowserImpl(browser_window_interface);
 #endif  // BUILDFLAG(IS_LINUX) && BUILDFLAG(IS_OZONE_WAYLAND)
   }
 
-  void ActivateBrowserImpl(Browser* browser) {
-    if (GetIdleBubble(browser)) {
+  void ActivateBrowserImpl(BrowserWindowInterface* browser_window_interface) {
+    if (GetIdleBubble(browser_window_interface)) {
       return;
     }
-    CHECK(browser);
-    ui_test_utils::BrowserActivationWaiter waiter(browser);
-    browser->window()->Activate();
+    CHECK(browser_window_interface);
+    ui_test_utils::BrowserActivationWaiter waiter(browser_window_interface);
+    browser_window_interface->GetWindow()->Activate();
     waiter.WaitForActivation();
   }
 
@@ -261,7 +269,7 @@
       .WillOnce(Return(base::Seconds(58)));
   std::unique_ptr<base::HistogramTester> histogram_tester =
       std::make_unique<base::HistogramTester>();
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/0);
 
   EXPECT_EQ(1, GetBrowserCount(profile));
@@ -315,7 +323,7 @@
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, DidNotClose) {
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(59)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1);
 
   EXPECT_EQ(1, GetBrowserCount(profile));
@@ -347,7 +355,7 @@
   // Set the IdleTimeout policy to 10 minutes.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(599)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/10);
 
   EXPECT_EQ(1, GetBrowserCount(profile));
@@ -393,8 +401,8 @@
   // `profile` has the IdleTimeout policy set to 5 minutes.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(299)));
-  Profile* profile = browser()->profile();
-  Browser* browser2 = CreateBrowser(profile);
+  Profile* profile = GetProfile();
+  BrowserWindowInterface* browser2 = CreateBrowser(profile);
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/5);
 
   // `profile2` has the policy set to 5 minutes, so it will close at the same
@@ -407,7 +415,7 @@
             "Profile 2"));
     SetIdleTimeoutPolicies(policy_provider(1), /*idle_timeout=*/5);
   }
-  Browser* browser3 = CreateBrowser(profile2);
+  BrowserWindowInterface* browser3 = CreateBrowser(profile2);
 
   // `profile3` doesn't have the IdleTimeout policy set, so it will
   // never close.
@@ -471,8 +479,8 @@
   // `profile` has the IdleTimeout policy set to 5 minutes.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(299)));
-  Profile* profile = browser()->profile();
-  Browser* browser2 = CreateBrowser(profile);
+  Profile* profile = GetProfile();
+  BrowserWindowInterface* browser2 = CreateBrowser(profile);
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/5);
 
   // `profile2` has the policy set to 6 minutes, so it will close one minute
@@ -485,7 +493,7 @@
             "Profile 2"));
     SetIdleTimeoutPolicies(policy_provider(1), /*idle_timeout=*/6);
   }
-  Browser* browser3 = CreateBrowser(profile2);
+  BrowserWindowInterface* browser3 = CreateBrowser(profile2);
 
   EXPECT_EQ(2, GetBrowserCount(profile));
   EXPECT_EQ(1, GetBrowserCount(profile2));
@@ -542,7 +550,7 @@
       .WillOnce(Return(base::Seconds(58)));
   std::unique_ptr<base::HistogramTester> histogram_tester =
       std::make_unique<base::HistogramTester>();
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1);
 
   EXPECT_EQ(1, GetBrowserCount(profile));
@@ -589,7 +597,7 @@
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, NoActions) {
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{});
 
@@ -625,7 +633,7 @@
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, JustCloseBrowsers) {
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"close_browsers"});
 
@@ -662,7 +670,7 @@
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, JustShowProfilePicker) {
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"show_profile_picker"});
 
@@ -687,7 +695,7 @@
 }
 
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, ReloadPages) {
-  auto* web_contents = browser()->tab_strip_model()->GetWebContentsAt(0);
+  auto* web_contents = browser()->GetTabStripModel()->GetWebContentsAt(0);
 
   // TODO(crbug.com/430613676): Determine why about:blank refreshes are causing
   // timeouts with RenderDocument enabled and revert this test to being
@@ -699,7 +707,7 @@
 
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"reload_pages"});
 
@@ -735,15 +743,14 @@
 }
 
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, ShowBubbleImmediately) {
-  browser()->window()->Activate();
-  BrowserList::SetLastActive(browser());
+  browser()->GetWindow()->Activate();
 
   // Use "reload_pages" as our action, because:
   // - It runs synchronously (succeeds immediately).
   // - It doesn't close browsers.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"reload_pages"});
 
@@ -782,15 +789,14 @@
 #endif
 IN_PROC_BROWSER_TEST_F(IdleServiceTest,
                        MAYBE_CanFocusBubbleWithFocusDialogHotkey) {
-  browser()->window()->Activate();
-  BrowserList::SetLastActive(browser());
+  browser()->GetWindow()->Activate();
 
   // Use "reload_pages" as our action, because:
   // - It runs synchronously (succeeds immediately).
   // - It doesn't close browsers.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"reload_pages"});
 
@@ -836,15 +842,14 @@
 #endif
 IN_PROC_BROWSER_TEST_F(IdleServiceTest,
                        MAYBE_CanFocusBubbleWithRotatePaneFocusHotkey) {
-  browser()->window()->Activate();
-  BrowserList::SetLastActive(browser());
+  browser()->GetWindow()->Activate();
 
   // Use "reload_pages" as our action, because:
   // - It runs synchronously (succeeds immediately).
   // - It doesn't close browsers.
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1,
                          /*idle_timeout_actions=*/{"reload_pages"});
 
@@ -884,7 +889,7 @@
 IN_PROC_BROWSER_TEST_F(IdleServiceTest, PRE_ShowBubbleOnStartup) {
   EXPECT_CALL(idle_time_provider(), CalculateIdleTime())
       .WillOnce(Return(base::Seconds(58)));
-  Profile* profile = browser()->profile();
+  Profile* profile = GetProfile();
   SetIdleTimeoutPolicies(policy_provider(0), /*idle_timeout=*/1);
 
   EXPECT_EQ(1, GetBrowserCount(profile));
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index aec6f44e..e0178c232 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -5241,16 +5241,6 @@
     "expiry_milestone": 140
   },
   {
-    "name": "file-transfer-enterprise-connector",
-    "owners": [ "sseckler@google.com", "marcgrimme@chromium.org", "poromov@chromium.org" ],
-    "expiry_milestone": 130
-  },
-  {
-    "name": "file-transfer-enterprise-connector-ui",
-    "owners": [ "sseckler@google.com", "marcgrimme@chromium.org", "poromov@chromium.org" ],
-    "expiry_milestone": 130
-  },
-  {
     "name": "files-conflict-dialog",
     "owners": [ "simmonsjosh@google.com", "//ui/file_manager/OWNERS" ],
     "expiry_milestone": 135
@@ -9856,7 +9846,7 @@
   {
     "name": "tab-grid-new-transitions",
     "owners": [ "gambard@chromium.org", "bling-flags@google.com" ],
-    "expiry_milestone": 142
+    "expiry_milestone": 150
   },
   {
     "name": "tab-group-android-visual-data-cleanup",
@@ -10231,7 +10221,7 @@
       "vmiura@chromium.org",
       "chrome-gpu-team@google.com"
     ],
-    "expiry_milestone": 144
+    "expiry_milestone": 160
   },
   {
     "name": "trusted-web-activity-contacts-delegation",
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h
index 40ae5ee..3815e0bf 100644
--- a/chrome/browser/flag_descriptions.h
+++ b/chrome/browser/flag_descriptions.h
@@ -7400,16 +7400,6 @@
     "rather than disabling all the displays. Will not work on AMD devices as "
     "they are unable to accept commits without a primary plane.";
 
-inline constexpr char kFileTransferEnterpriseConnectorName[] =
-    "Enable Files Transfer Enterprise Connector.";
-inline constexpr char kFileTransferEnterpriseConnectorDescription[] =
-    "Enable the File Transfer Enterprise Connector.";
-
-inline constexpr char kFileTransferEnterpriseConnectorUIName[] =
-    "Enable UI for Files Transfer Enterprise Connector.";
-inline constexpr char kFileTransferEnterpriseConnectorUIDescription[] =
-    "Enable the UI for the File Transfer Enterprise Connector.";
-
 inline constexpr char kFilesConflictDialogName[] = "Files app conflict dialog";
 inline constexpr char kFilesConflictDialogDescription[] =
     "When enabled, the conflict dialog will be shown during file transfers "
diff --git a/chrome/browser/glic/host/glic_actor_general_interactive_uitest.cc b/chrome/browser/glic/host/glic_actor_general_interactive_uitest.cc
index db6c2659..7430533 100644
--- a/chrome/browser/glic/host/glic_actor_general_interactive_uitest.cc
+++ b/chrome/browser/glic/host/glic_actor_general_interactive_uitest.cc
@@ -873,44 +873,148 @@
   // clang-format on
 }
 
-// Test for the above behavior when the killswitch is turned off. i.e. that the
-// state change callback invokes before performActions resolves.
-class GlicActorCallbackOrderKillSwitchGeneralUiTest
-    : public GlicActorCallbackOrderGeneralUiTest {
- public:
-  GlicActorCallbackOrderKillSwitchGeneralUiTest() {
-    feature_list_.InitAndDisableFeature(
-        actor::kGlicPerformActionsReturnsBeforeStateChange);
-  }
-
-  ~GlicActorCallbackOrderKillSwitchGeneralUiTest() override = default;
-
- private:
-  base::test::ScopedFeatureList feature_list_;
-};
-
-IN_PROC_BROWSER_TEST_F(GlicActorCallbackOrderKillSwitchGeneralUiTest,
-                       StateChangeBeforePerformActionsResolves) {
+IN_PROC_BROWSER_TEST_F(GlicActorUiTest, ScreenshotInMinimizedWindow) {
+  EnableScreenshotsInContext();
   DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<bool>,
+                                      kIsMinimizedState);
 
+  const GURL task_url = embedded_test_server()->GetURL("/actor/blank.html");
   RunTestSequence(
       // clang-format off
-      InitializeWithOpenGlicWindow(),
-      StartActorTaskInNewTab(GURL(url::kAboutBlankURL), kNewActorTabId),
-      SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
-                              kActivateSurfaceIncompatibilityNotice),
+    InitializeWithOpenGlicWindow(),
+    StartActorTaskInNewTab(task_url, kNewActorTabId),
+    SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
+                            kActivateSurfaceIncompatibilityNotice),
+    // Wait for painting, so we can get the screenshot.
+    WaitForWebContentsPainted(kNewActorTabId),
+    // Take an action with the actor to make sure that actuation has started.
+    ClickAction({1,1}, ClickAction::LEFT, ClickAction::SINGLE),
+    // Verify we can get the screenshot.
+    GetPageContextForActorTab(),
+    Steps(Do(base::BindLambdaForTesting([this](){
+      EXPECT_TRUE(annotated_page_content_);
+      EXPECT_TRUE(viewport_screenshot_);
+      annotated_page_content_.reset();
+      viewport_screenshot_.reset();
+    }))),
 
-      RecordActorTaskStateChanges(),
-      InvokeToolThatNeverFinishes(kNewActorTabId),
-      StopActorTask(),
-      WaitForActorTaskState(mojom::ActorTaskState::kStopped),
+    // Minimize the window and wait until it is minimized.
+    Steps(Do([this](){
+      browser()->window()->Minimize();
+    })),
+    PollState(kIsMinimizedState, [this]() {
+      return browser()->window()->IsMinimized();
+    }),
+    WaitForState(kIsMinimizedState, true),
 
-      CheckResult([this]() { return GetEventLog(); },
-          "IDLE,"
-          "ACTING,"
-          "STOPPED,"
-          "PERFORM_ACTIONS_RETURNED")
-    );
+    // Try to get the screenshot when the window is minimized.
+    GetPageContextForActorTab(),
+    Steps(Do(base::BindLambdaForTesting([this](){
+      EXPECT_TRUE(annotated_page_content_);
+      EXPECT_TRUE(viewport_screenshot_);
+    }))));
+  // clang-format on
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorUiTest, ScreenshotInInitiallyMinimizedWindow) {
+  EnableScreenshotsInContext();
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<bool>,
+                                      kIsMinimizedState);
+
+  const GURL task_url = embedded_test_server()->GetURL("/actor/blank.html");
+  RunTestSequence(
+      // clang-format off
+    SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
+                            kActivateSurfaceIncompatibilityNotice),
+    InitializeWithOpenGlicWindow(),
+    AddInstrumentedTab(kNewActorTabId, task_url),
+    WithElement(kNewActorTabId, [this](ui::TrackedElement* el){
+      content::WebContents* tab_contents =
+          AsInstrumentedWebContents(el)->web_contents();
+      tabs::TabInterface* tab =
+          tabs::TabInterface::GetFromContents(tab_contents);
+      CHECK(tab);
+      tab_handle_ = tab->GetHandle();
+    }),
+
+    // Minimize the window and wait until it is minimized.
+    Steps(Do([this](){
+      browser()->window()->Minimize();
+    })),
+    PollState(kIsMinimizedState, [this]() {
+      return browser()->window()->IsMinimized();
+    }),
+    WaitForState(kIsMinimizedState, true),
+
+    CreateTask(task_id_, ""),
+    // Try to get the screenshot when the window is minimized.
+    GetPageContextForActorTab(),
+    Steps(Do(base::BindLambdaForTesting([this](){
+      EXPECT_TRUE(annotated_page_content_);
+      EXPECT_TRUE(viewport_screenshot_);
+    }))));
+  // clang-format on
+}
+
+IN_PROC_BROWSER_TEST_F(GlicActorUiTest, ScreenshotInMinimizedWindowWithFloaty) {
+  EnableScreenshotsInContext();
+  DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kNewActorTabId);
+  DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(ui::test::PollingStateObserver<bool>,
+                                      kIsMinimizedState);
+
+  const GURL task_url =
+      embedded_test_server()->GetURL("/actor/page_with_clickable_element.html");
+
+  // Ensure a new tab can be created without crashing when the most recently
+  // focused browser window is not a normal tabbed browser (e.g. a DevTools
+  // window).
+  TrackFloatingGlicInstance();
+  RunTestSequence(
+      // clang-format off
+    SetOnIncompatibleAction(OnIncompatibleAction::kSkipTest,
+                            kActivateSurfaceIncompatibilityNotice),
+    InstrumentTab(kNewActorTabId),
+    NavigateWebContents(kNewActorTabId, task_url),
+    OpenGlicFloatingWindow(),
+    WaitForWebContentsReady(kNewActorTabId),
+    WithElement(kNewActorTabId, [this](ui::TrackedElement* el){
+      content::WebContents* tab_contents =
+          AsInstrumentedWebContents(el)->web_contents();
+      tabs::TabInterface* tab =
+          tabs::TabInterface::GetFromContents(tab_contents);
+      CHECK(tab);
+      tab_handle_ = tab->GetHandle();
+    }),
+    CreateTask(task_id_, ""),
+
+    // Wait for painting, so we can get the screenshot.
+    WaitForWebContentsPainted(kNewActorTabId),
+    // Verify we can get the screenshot.
+    GetPageContextForActorTab(),
+    Steps(Do(base::BindLambdaForTesting([this](){
+      EXPECT_TRUE(annotated_page_content_);
+      EXPECT_TRUE(viewport_screenshot_);
+      annotated_page_content_.reset();
+      viewport_screenshot_.reset();
+    }))),
+
+    // // Minimize the window and wait until it is minimized.
+    Steps(Do([this](){
+      browser()->window()->Minimize();
+    })),
+    PollState(kIsMinimizedState, [this]() {
+      return browser()->window()->IsMinimized();
+    }),
+    WaitForState(kIsMinimizedState, true),
+
+    // Try to get the screenshot when the window is minimized.
+    GetPageContextForActorTab(),
+    Steps(Do(base::BindLambdaForTesting([this](){
+      EXPECT_TRUE(annotated_page_content_);
+      EXPECT_TRUE(viewport_screenshot_);
+    }))));
   // clang-format on
 }
 
diff --git a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc
index 5a19bd8..70208df 100644
--- a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc
+++ b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.cc
@@ -563,20 +563,17 @@
 
 MultiStep GlicActorUiTest::GetPageContextForActorTab() {
   return Steps(Do([&]() {
-    GlicKeyedService* glic_service =
-        GlicKeyedServiceFactory::GetGlicKeyedService(browser()->GetProfile());
-    ASSERT_TRUE(glic_service);
-
     base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed);
 
     auto options = mojom::GetTabContextOptions::New();
     options->include_annotated_page_content = true;
+    options->include_viewport_screenshot = include_screenshot_;
     // TODO (crbug.com/458415347): Look into replacing GetContextFromActorForTab
     // with an AKS::RequestTabObservation
     EXPECT_NE(tab_handle_, TabHandle::Null())
         << "GetPageContextForActorTab must be called after starting a task in "
            "a tab, e.g. using StartActorTaskInNewTab";
-    glic_service->sharing_manager().GetContextForActorFromTab(
+    GetGlicInstance()->host().sharing_manager().GetContextForActorFromTab(
         tab_handle_, *options.get(),
         base::BindLambdaForTesting([&](GlicGetContextResult result) {
           if (result.has_value()) {
@@ -584,6 +581,8 @@
                 *result.value()
                      ->get_tab_context()
                      ->annotated_page_data->annotated_page_content;
+            viewport_screenshot_ = std::move(
+                result.value()->get_tab_context()->viewport_screenshot);
             annotated_page_content_ = std::make_unique<AnnotatedPageContent>(
                 serialized_apc.As<AnnotatedPageContent>().value());
             actor::ActorTabData* tab_data =
diff --git a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.h b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.h
index bcd7ae3..3f91561 100644
--- a/chrome/browser/glic/host/glic_actor_interactive_uitest_common.h
+++ b/chrome/browser/glic/host/glic_actor_interactive_uitest_common.h
@@ -224,13 +224,17 @@
   tabs::TabHandle tab_handle_;
 
  protected:
+  void EnableScreenshotsInContext() { include_screenshot_ = true; }
+
   std::unique_ptr<optimization_guide::proto::AnnotatedPageContent>
       annotated_page_content_;
+  mojom::ScreenshotPtr viewport_screenshot_;
 
   // Label corresponds to the aria-label on the element in the page.
   int32_t SearchAnnotatedPageContent(std::string_view label);
 
  private:
+  bool include_screenshot_ = false;
   std::optional<optimization_guide::proto::ActionsResult>
       last_execution_result_;
   base::test::ScopedFeatureList scoped_feature_list_;
diff --git a/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc b/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
index 47521a1..b0c6a49 100644
--- a/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
+++ b/chrome/browser/media/webrtc/webrtc_mediadevices_interactive_uitest.cc
@@ -28,7 +28,6 @@
 #include "components/permissions/permission_request_manager.h"
 #include "components/permissions/test/permission_request_observer.h"
 #include "components/prefs/pref_service.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browsing_data_remover.h"
 #include "content/public/common/content_features.h"
diff --git a/chrome/browser/metrics/chrome_metrics_service_client.cc b/chrome/browser/metrics/chrome_metrics_service_client.cc
index 58a87b1a9..6b68d5e 100644
--- a/chrome/browser/metrics/chrome_metrics_service_client.cc
+++ b/chrome/browser/metrics/chrome_metrics_service_client.cc
@@ -54,7 +54,6 @@
 #include "chrome/browser/metrics/network_quality_estimator_provider_impl.h"
 #include "chrome/browser/metrics/usertype_by_devicetype_metrics_provider.h"
 #include "chrome/browser/performance_manager/metrics/metrics_provider_common.h"
-#include "chrome/browser/privacy_budget/privacy_budget_prefs.h"
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/profiles/profiles_state.h"
 #include "chrome/browser/regional_capabilities/regional_capabilities_metrics_provider.h"
@@ -540,7 +539,6 @@
   metrics::dwa::DwaService::RegisterPrefs(registry);
   metrics::private_metrics::PumaService::RegisterPrefs(registry);
   metrics::StabilityMetricsHelper::RegisterPrefs(registry);
-  prefs::RegisterPrivacyBudgetPrefs(registry);
 
   RegisterFileMetricsPreferences(registry);
 
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManager.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManager.java
index 7abac22..4907552 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManager.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManager.java
@@ -185,9 +185,14 @@
 
     /**
      * Adds a {@link HomepageStateListener} to receive updates when the home modules state changes.
+     *
+     * @param listener The listener instance to add.
+     * @param context The Application context.
+     * @param skipNotify Whether to skip being notified immediately.
      */
-    public void addListener(HomepageStateListener listener, Context context) {
+    public void addListener(HomepageStateListener listener, Context context, boolean skipNotify) {
         mHomepageStateListeners.addObserver(listener);
+        if (skipNotify) return;
 
         if (!mIsInitialized) {
             maybeInitializeColorTheme(context);
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtils.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtils.java
index c553d79..983e1f4 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtils.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtils.java
@@ -106,6 +106,14 @@
 
     // LINT.ThenChange(//tools/metrics/histograms/metadata/new_tab_page/enums.xml:NtpBackgroundImageType)
 
+    /** An interface to get the current NTP's theme color. */
+    interface PrimaryColorProvider {
+        // Returns the current primary theme color if exists.
+        @Nullable
+        @ColorInt
+        Integer getPrimaryColor();
+    }
+
     @VisibleForTesting static final String NTP_BACKGROUND_IMAGE_FILE = "ntp_background_image";
     private static final String TAG = "NtpCustomization";
     private static final String DELIMITER = "|";
@@ -716,30 +724,68 @@
      * Sets tint color for the default Google logo.
      *
      * @param context Used to look up current day/night mode status.
+     * @param defaultGoogleLogoDrawable The drawable instance for default Google Logo.
      */
     public static void setTintForDefaultGoogleLogo(
             Context context, Drawable defaultGoogleLogoDrawable) {
+        @NtpBackgroundImageType
+        int backgroundType = NtpCustomizationConfigManager.getInstance().getBackgroundImageType();
+        getTintedGoogleLogoDrawableImpl(
+                context,
+                defaultGoogleLogoDrawable,
+                backgroundType,
+                () -> NtpCustomizationUtils.getPrimaryColorFromCustomizedThemeColor(context));
+    }
+
+    /**
+     * Returns the default Google logo with tint.
+     *
+     * @param context Used to look up current day/night mode status.
+     * @param defaultGoogleLogoDrawable The drawable instance for default Google Logo.
+     * @param backgroundType backgroundType The NTP's background theme type.
+     * @param primaryColor The primary theme color.
+     */
+    public static Drawable getTintedGoogleLogoDrawableImpl(
+            Context context,
+            Drawable defaultGoogleLogoDrawable,
+            @NtpBackgroundImageType int backgroundType,
+            @Nullable @ColorInt Integer primaryColor) {
+        return getTintedGoogleLogoDrawableImpl(
+                context, defaultGoogleLogoDrawable, backgroundType, () -> primaryColor);
+    }
+
+    /**
+     * Returns the default Google logo with tint.
+     *
+     * @param context Used to look up current day/night mode status.
+     * @param defaultGoogleLogoDrawable The drawable instance for default Google Logo.
+     * @param backgroundType backgroundType The NTP's background theme type.
+     * @param primaryColorProvider The interface to get primary theme color.
+     */
+    private static Drawable getTintedGoogleLogoDrawableImpl(
+            Context context,
+            Drawable defaultGoogleLogoDrawable,
+            @NtpBackgroundImageType int backgroundType,
+            PrimaryColorProvider primaryColorProvider) {
         // Check the mode before applying a tinted color. A transparent tint in light mode will
         // cause the logo's color to disappear.
         boolean isNightMode = ColorUtils.inNightMode(context);
-        @NtpBackgroundImageType
-        int defaultBackgroundType =
-                NtpCustomizationConfigManager.getInstance().getBackgroundImageType();
-
         // The colorful Google logo is shown for default theme in light mode.
-        if (!isNightMode && defaultBackgroundType == NtpBackgroundImageType.DEFAULT) {
-            return;
+        if (!isNightMode && backgroundType == NtpBackgroundImageType.DEFAULT) {
+            return defaultGoogleLogoDrawable;
         }
 
         @ColorInt int tintColor;
-        if (defaultBackgroundType == NtpBackgroundImageType.CHROME_COLOR
-                || defaultBackgroundType == NtpBackgroundImageType.COLOR_FROM_HEX) {
-            @ColorInt Integer primaryColor = getPrimaryColorFromCustomizedThemeColor(context);
+        if (backgroundType == NtpBackgroundImageType.CHROME_COLOR
+                || backgroundType == NtpBackgroundImageType.COLOR_FROM_HEX) {
+            @Nullable
+            @ColorInt
+            Integer primaryColor = primaryColorProvider.getPrimaryColor();
             if (primaryColor != null) {
                 tintColor = primaryColor.intValue();
             } else if (!isNightMode) {
                 // When primary color is missing, falls back to colorful Google logo in light mode.
-                return;
+                return defaultGoogleLogoDrawable;
             } else {
                 // When primary color is missing, falls back to white Google logo in light mode.
                 tintColor = Color.WHITE;
@@ -751,7 +797,9 @@
             tintColor = Color.WHITE;
         }
 
-        defaultGoogleLogoDrawable.mutate().setTint(tintColor);
+        Drawable tintedDrawable = defaultGoogleLogoDrawable.mutate();
+        tintedDrawable.setTint(tintColor);
+        return tintedDrawable;
     }
 
     /**
diff --git a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/edge_to_edge/TopInsetCoordinator.java b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/edge_to_edge/TopInsetCoordinator.java
index 5af6b19..edefa953d 100644
--- a/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/edge_to_edge/TopInsetCoordinator.java
+++ b/chrome/browser/ntp_customization/java/src/org/chromium/chrome/browser/ntp_customization/edge_to_edge/TopInsetCoordinator.java
@@ -167,7 +167,8 @@
                         TopInsetCoordinator.this.refreshWindowInsets(consumeTopInset);
                     }
                 };
-        NtpCustomizationConfigManager.getInstance().addListener(mHomepageStateListener, context);
+        NtpCustomizationConfigManager.getInstance()
+                .addListener(mHomepageStateListener, context, /* skipNotify= */ false);
 
         mWindowInsetsConsumer = this::onApplyWindowInsets;
         mInsetObserver.addInsetsConsumer(
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManagerUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManagerUnitTest.java
index 219a1a2..2f90b16 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManagerUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationConfigManagerUnitTest.java
@@ -105,7 +105,7 @@
     @Test
     public void testOnUploadedImageSelected_persistsStateAndNotifiesListener() {
         int initialBackgroundImageType = mNtpCustomizationConfigManager.getBackgroundImageType();
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         BackgroundImageInfo backgroundImageInfo =
                 new BackgroundImageInfo(mPortraitMatrix, mLandscapeMatrix);
 
@@ -146,6 +146,32 @@
     }
 
     @Test
+    public void testAddListener_skipNotify() {
+        BackgroundImageInfo backgroundImageInfo =
+                new BackgroundImageInfo(mPortraitMatrix, mLandscapeMatrix);
+        mNtpCustomizationConfigManager.setBackgroundImageTypeForTesting(
+                NtpBackgroundImageType.IMAGE_FROM_DISK);
+        // Passes non-null matrices to mNtpCustomizationConfigManager.
+        mNtpCustomizationConfigManager.notifyBackgroundImageChanged(
+                mBitmap,
+                backgroundImageInfo,
+                /* fromInitialization= */ true,
+                /* oldType= */ NtpBackgroundImageType.DEFAULT);
+        mNtpCustomizationConfigManager.setIsInitializedForTesting(true);
+
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ true);
+
+        // Verifies that the listener isn't notified immediately with skipNotify being true.
+        verify(mListener, never())
+                .onBackgroundImageChanged(
+                        any(Bitmap.class),
+                        any(BackgroundImageInfo.class),
+                        anyBoolean(),
+                        anyInt(),
+                        anyInt());
+    }
+
+    @Test
     public void testAddListener_notifiesImmediatelyWithImage_forImageFromDisk() {
         BackgroundImageInfo backgroundImageInfo =
                 new BackgroundImageInfo(mPortraitMatrix, mLandscapeMatrix);
@@ -159,7 +185,7 @@
                 /* oldType= */ NtpBackgroundImageType.DEFAULT);
         mNtpCustomizationConfigManager.setIsInitializedForTesting(true);
 
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
 
         // Verifies that the listener should be called back immediately with
         // fromInitialization=true.
@@ -181,7 +207,7 @@
                 NtpBackgroundImageType.DEFAULT);
         mNtpCustomizationConfigManager.setIsInitializedForTesting(true);
 
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
 
         // Verifies that the listener should be called back immediately with
         // fromInitialization=true.
@@ -206,7 +232,7 @@
                 mContext, colorFromHexInfo, NtpBackgroundImageType.COLOR_FROM_HEX);
         mNtpCustomizationConfigManager.setIsInitializedForTesting(true);
 
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
 
         // Verifies that the listener should be called back immediately with
         // fromInitialization=true.
@@ -223,7 +249,7 @@
     public void testRemoveListener_stopsReceivingUpdates_onBackgroundChanged() {
         mNtpCustomizationConfigManager.setBackgroundImageTypeForTesting(
                 NtpBackgroundImageType.IMAGE_FROM_DISK);
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         mNtpCustomizationConfigManager.removeListener(mListener);
 
         // Triggers a change that would normally notify the listener.
@@ -242,7 +268,7 @@
     public void testRemoveListener_stopsReceivingUpdates_onBackgroundColorChanged() {
         mNtpCustomizationConfigManager.setBackgroundImageTypeForTesting(
                 NtpBackgroundImageType.DEFAULT);
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         mNtpCustomizationConfigManager.removeListener(mListener);
 
         // Triggers a change that would normally notify the listener.
@@ -260,7 +286,7 @@
     @Test
     public void testAddAndRemoveMvtVisibilityListener() {
         // Verifies the listener added is notified when the visibility if changed.
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         mNtpCustomizationConfigManager.setPrefIsMvtToggleOn(/* isMvtToggleOn= */ true);
         verify(mListener).onMvtToggleChanged();
 
@@ -276,7 +302,7 @@
     public void testSetAndGetPrefMvtVisibility() {
         // Verifies setPrefIsMvtVisible() sets the ChromeSharedPreferences properly and
         // getPrefIsMvtVisible() gets the right value.
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         mNtpCustomizationConfigManager.setPrefIsMvtToggleOn(/* isMvtToggleOn= */ false);
         assertFalse(
                 ChromeSharedPreferences.getInstance()
@@ -303,7 +329,7 @@
 
     @Test
     public void testOnBackgroundColorChanged() {
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         clearInvocations(mListener);
 
         int colorInfoId = NtpThemeColorInfo.NtpThemeColorId.NTP_COLORS_BLUE;
@@ -353,7 +379,7 @@
 
     @Test
     public void testOnBackgroundColorChanged_colorFromHexString() {
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         clearInvocations(mListener);
 
         @ColorInt int backgroundColor = Color.RED;
@@ -398,7 +424,7 @@
     @Test
     public void testOnThemeCollectionImageSelected() {
         int initialBackgroundImageType = mNtpCustomizationConfigManager.getBackgroundImageType();
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
         BackgroundImageInfo backgroundImageInfo =
                 new BackgroundImageInfo(mPortraitMatrix, mLandscapeMatrix);
         CustomBackgroundInfo customBackgroundInfo =
@@ -444,7 +470,7 @@
                 /* oldType= */ NtpBackgroundImageType.DEFAULT);
         mNtpCustomizationConfigManager.setIsInitializedForTesting(true);
 
-        mNtpCustomizationConfigManager.addListener(mListener, mContext);
+        mNtpCustomizationConfigManager.addListener(mListener, mContext, /* skipNotify= */ false);
 
         // Verifies that the listener should be called back immediately with
         // fromInitialization=true.
diff --git a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtilsUnitTest.java b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtilsUnitTest.java
index e49a230..6bf7b20 100644
--- a/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtilsUnitTest.java
+++ b/chrome/browser/ntp_customization/junit/src/org/chromium/chrome/browser/ntp_customization/NtpCustomizationUtilsUnitTest.java
@@ -466,25 +466,21 @@
     }
 
     @Test
-    public void testSetTintForDefaultGoogleLogo() {
+    public void testGetTintedGoogleLogoDrawable_nonChromeColor() {
         ColorUtils.setInNightModeForTesting(false);
-        NtpCustomizationConfigManager customizationConfigManager =
-                new NtpCustomizationConfigManager();
-        NtpCustomizationConfigManager.setInstanceForTesting(customizationConfigManager);
-
         Drawable mutateDrawable = mock(Drawable.class);
         when(mDrawable.mutate()).thenReturn(mutateDrawable);
+        @ColorInt int primaryColor = Color.RED;
 
         // Test cases in light mode:
-
         // Verifies that no tint color is set for the default theme in light mode.
-        customizationConfigManager.setBackgroundImageTypeForTesting(NtpBackgroundImageType.DEFAULT);
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.DEFAULT, primaryColor);
         verify(mutateDrawable, never()).setTint(anyInt());
 
         // Verifies that color white is set for customized background images.
-        customizationConfigManager.setBackgroundImageTypeForTesting(IMAGE_FROM_DISK);
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.IMAGE_FROM_DISK, primaryColor);
         verify(mutateDrawable).setTint(eq(Color.WHITE));
 
         // Test cases in dark mode:
@@ -492,69 +488,64 @@
         clearInvocations(mutateDrawable);
 
         // Verifies that color white is set for customized background images.
-        customizationConfigManager.setBackgroundImageTypeForTesting(IMAGE_FROM_DISK);
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.IMAGE_FROM_DISK, primaryColor);
         verify(mutateDrawable).setTint(eq(Color.WHITE));
 
         // Verifies that color white is set for the default theme.
-        customizationConfigManager.setBackgroundImageTypeForTesting(NtpBackgroundImageType.DEFAULT);
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.DEFAULT, primaryColor);
         verify(mutateDrawable, times(2)).setTint(eq(Color.WHITE));
-
-        // Cleans up.
-        customizationConfigManager.resetForTesting();
     }
 
     @Test
     @Features.EnableFeatures(ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2)
-    public void testSetTintForDefaultGoogleLogo_chromeColor() {
+    public void testGetTintedGoogleLogoDrawable_chromeColor_lightMode() {
+        // Test cases in light mode.
         ColorUtils.setInNightModeForTesting(false);
-        NtpCustomizationConfigManager customizationConfigManager =
-                new NtpCustomizationConfigManager();
-        NtpCustomizationConfigManager.setInstanceForTesting(customizationConfigManager);
+        @ColorInt int primaryColor = mContext.getColor(R.color.ntp_color_blue_primary);
+        Drawable mutateDrawable = mock(Drawable.class);
+        when(mDrawable.mutate()).thenReturn(mutateDrawable);
+
+        // Verifies that the saved primary color is set for customized color themes if exists.
+        assertEquals(
+                mutateDrawable,
+                NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                        mContext, mDrawable, NtpBackgroundImageType.CHROME_COLOR, primaryColor));
+        verify(mutateDrawable).setTint(eq(primaryColor));
+
+        clearInvocations(mutateDrawable);
+        // Verifies that if primary color is missing, no tint color is set in light mode.
+        assertEquals(
+                mDrawable,
+                NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                        mContext,
+                        mDrawable,
+                        NtpBackgroundImageType.CHROME_COLOR,
+                        /* primaryColor= */ null));
+        verify(mutateDrawable, never()).setTint(eq(primaryColor));
+    }
+
+    @Test
+    @Features.EnableFeatures(ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2)
+    public void testGetTintedGoogleLogoDrawable_chromeColor_darkMode() {
+        // Test cases in dark mode.
+        ColorUtils.setInNightModeForTesting(true);
+        @ColorInt int primaryColor = mContext.getColor(R.color.ntp_color_blue_primary);
 
         Drawable mutateDrawable = mock(Drawable.class);
         when(mDrawable.mutate()).thenReturn(mutateDrawable);
 
-        // Test cases in light mode:
-
-        // Verifies that when the primary color is missing, no tint color is set in light mode.
-        @NtpThemeColorId int colorId = NtpThemeColorId.NTP_COLORS_AQUA;
-        NtpThemeColorInfo ntpThemeColorInfo =
-                NtpThemeColorUtils.createNtpThemeColorInfo(mContext, colorId);
-        @ColorInt int primaryColor = mContext.getColor(ntpThemeColorInfo.primaryColorResId);
-        NtpCustomizationUtils.setNtpBackgroundImageTypeToSharedPreference(
-                NtpBackgroundImageType.CHROME_COLOR);
-        customizationConfigManager.setBackgroundImageTypeForTesting(
-                NtpBackgroundImageType.CHROME_COLOR);
-        assertEquals(
-                NtpThemeColorId.DEFAULT,
-                NtpCustomizationUtils.getNtpThemeColorIdFromSharedPreference());
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
-        verify(mutateDrawable, never()).setTint(anyInt());
-
-        // Verifies that the saved primary color is set for customized color themes if exists.
-        NtpCustomizationUtils.setNtpThemeColorIdToSharedPreference(colorId);
-        assertEquals(colorId, NtpCustomizationUtils.getNtpThemeColorIdFromSharedPreference());
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
-        verify(mutateDrawable).setTint(eq(primaryColor));
-
-        // Test cases in dark mode:
-        ColorUtils.setInNightModeForTesting(true);
-        clearInvocations(mutateDrawable);
-
         // Verifies that the saved primary color is set for customized color themes.
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.CHROME_COLOR, primaryColor);
         verify(mutateDrawable).setTint(eq(primaryColor));
 
+        clearInvocations(mutateDrawable);
         // Verifies when the primary color is missing, color white is set in dark mode.
-        NtpCustomizationUtils.resetSharedPreferenceForTesting();
-        assertNull(NtpCustomizationUtils.getPrimaryColorFromCustomizedThemeColor(mContext));
-        NtpCustomizationUtils.setTintForDefaultGoogleLogo(mContext, mDrawable);
+        NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                mContext, mDrawable, NtpBackgroundImageType.CHROME_COLOR, /* primaryColor= */ null);
         verify(mutateDrawable).setTint(eq(Color.WHITE));
-
-        // Cleans up.
-        customizationConfigManager.resetForTesting();
     }
 
     @Test
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 2c7878ae..d93e860 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -929,6 +929,14 @@
 const char kFpfRulesetChecksum[] =
     "fingerprinting_protection_filter.ruleset_version.checksum";
 
+// Deprecated 12/2025.
+const char kPrivacyBudgetGeneration[] = "privacy_budget.generation";
+const char kPrivacyBudgetSeenSurfaces[] = "privacy_budget.seen";
+const char kPrivacyBudgetSelectedOffsets[] = "privacy_budget.selected";
+const char kPrivacyBudgetSelectedBlock[] = "privacy_budget.block_offset";
+const char kPrivacyBudgetMetaExperimentActivationSalt[] =
+    "privacy_budget.meta_experiment_activation_salt";
+
 // Register local state used only for migration (clearing or moving to a new
 // key).
 void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -1017,6 +1025,13 @@
   registry->RegisterStringPref(kFpfRulesetContent, std::string());
   registry->RegisterIntegerPref(kFpfRulesetFormat, 0);
   registry->RegisterUint64Pref(kFpfRulesetChecksum, 0);
+
+  // Deprecated 12/2025.
+  registry->RegisterIntegerPref(kPrivacyBudgetGeneration, 0);
+  registry->RegisterStringPref(kPrivacyBudgetSeenSurfaces, std::string());
+  registry->RegisterStringPref(kPrivacyBudgetSelectedOffsets, std::string());
+  registry->RegisterIntegerPref(kPrivacyBudgetSelectedBlock, -1);
+  registry->RegisterDoublePref(kPrivacyBudgetMetaExperimentActivationSalt, 0);
 }
 
 // Register prefs used only for migration (clearing or moving to a new key).
@@ -2208,6 +2223,13 @@
   local_state->ClearPref(kFpfRulesetFormat);
   local_state->ClearPref(kFpfRulesetChecksum);
 
+  // Added 12/2025
+  local_state->ClearPref(kPrivacyBudgetGeneration);
+  local_state->ClearPref(kPrivacyBudgetSeenSurfaces);
+  local_state->ClearPref(kPrivacyBudgetSelectedOffsets);
+  local_state->ClearPref(kPrivacyBudgetSelectedBlock);
+  local_state->ClearPref(kPrivacyBudgetMetaExperimentActivationSalt);
+
   // Please don't delete the following line. It is used by PRESUBMIT.py.
   // END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS
 
diff --git a/chrome/browser/privacy_budget/BUILD.gn b/chrome/browser/privacy_budget/BUILD.gn
deleted file mode 100644
index cf83ff0..0000000
--- a/chrome/browser/privacy_budget/BUILD.gn
+++ /dev/null
@@ -1,19 +0,0 @@
-# Copyright 2020 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("headers") {
-  sources = [ "privacy_budget_prefs.h" ]
-
-  deps = [ "//components/prefs" ]
-}
-
-source_set("privacy_budget") {
-  sources = [ "privacy_budget_prefs.cc" ]
-
-  configs += [ "//build/config/compiler:wexit_time_destructors" ]
-
-  public_deps = [ ":headers" ]
-
-  deps = [ "//components/prefs" ]
-}
diff --git a/chrome/browser/privacy_budget/DIR_METADATA b/chrome/browser/privacy_budget/DIR_METADATA
deleted file mode 100644
index 6d362b2..0000000
--- a/chrome/browser/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
diff --git a/chrome/browser/privacy_budget/OWNERS b/chrome/browser/privacy_budget/OWNERS
deleted file mode 100644
index dc54869..0000000
--- a/chrome/browser/privacy_budget/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/blink/public/common/privacy_budget/OWNERS
diff --git a/chrome/browser/privacy_budget/privacy_budget_prefs.cc b/chrome/browser/privacy_budget/privacy_budget_prefs.cc
deleted file mode 100644
index abd33b7..0000000
--- a/chrome/browser/privacy_budget/privacy_budget_prefs.cc
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/browser/privacy_budget/privacy_budget_prefs.h"
-
-#include "components/prefs/pref_registry_simple.h"
-
-namespace prefs {
-
-const char kPrivacyBudgetGeneration[] = "privacy_budget.generation";
-const char kPrivacyBudgetSeenSurfaces[] = "privacy_budget.seen";
-const char kPrivacyBudgetSelectedOffsets[] = "privacy_budget.selected";
-const char kPrivacyBudgetSelectedBlock[] = "privacy_budget.block_offset";
-const char kPrivacyBudgetMetaExperimentActivationSalt[] =
-    "privacy_budget.meta_experiment_activation_salt";
-
-void RegisterPrivacyBudgetPrefs(PrefRegistrySimple* registry) {
-  registry->RegisterIntegerPref(kPrivacyBudgetGeneration, 0);
-  registry->RegisterStringPref(kPrivacyBudgetSeenSurfaces, std::string());
-  registry->RegisterStringPref(kPrivacyBudgetSelectedOffsets, std::string());
-  registry->RegisterIntegerPref(kPrivacyBudgetSelectedBlock, -1);
-  registry->RegisterDoublePref(kPrivacyBudgetMetaExperimentActivationSalt, 0);
-}
-
-}  // namespace prefs
diff --git a/chrome/browser/privacy_budget/privacy_budget_prefs.h b/chrome/browser/privacy_budget/privacy_budget_prefs.h
deleted file mode 100644
index 1e93dbc..0000000
--- a/chrome/browser/privacy_budget/privacy_budget_prefs.h
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_BROWSER_PRIVACY_BUDGET_PRIVACY_BUDGET_PREFS_H_
-#define CHROME_BROWSER_PRIVACY_BUDGET_PRIVACY_BUDGET_PREFS_H_
-
-#include "components/prefs/pref_registry_simple.h"
-
-namespace prefs {
-
-// See documentation for IdentifiabilityStudyState for details on how these
-// values are used.
-
-// Pref used for persisting |IdentifiabilityStudyState::generation_|.
-//
-// Value is an int stored as IntegerPref.
-extern const char kPrivacyBudgetGeneration[];
-
-// Pref used for persisting |IdentifiabilityStudyState::seen_surface_sequence_|.
-//
-// Value is a list of IdentifiableSurface encoded via
-// EncodeIdentifiabilityFieldTrialParam<> into a StringPref. Use
-// DecodeIdentifiabilityFieldTrialParam<> to read.
-//
-// The ordering is a significant and represents the order in which the surfaces
-// were encountered with the exception of blocked surfaces.
-extern const char kPrivacyBudgetSeenSurfaces[];
-
-// Pref used for persisting |IdentifiabilityStudyState::selected_offsets_|.
-//
-// Value is a list of offsets (>= 0) encoded into a ListPref where each element
-// in the list is an integer value.
-extern const char kPrivacyBudgetSelectedOffsets[];
-
-// Pref used for persisting the selected block during assigned block sampling.
-//
-// Value is an integer >= 0.
-extern const char kPrivacyBudgetSelectedBlock[];
-
-// Pref used for persisting the random salt which is used to decide whether the
-// meta experiment should be active. The meta experiment is active if the salt
-// is smaller than the meta experiment selection probability.
-//
-// Value is a double in the interval [0,1)
-extern const char kPrivacyBudgetMetaExperimentActivationSalt[];
-
-void RegisterPrivacyBudgetPrefs(PrefRegistrySimple* registry);
-
-}  // namespace prefs
-
-#endif  // CHROME_BROWSER_PRIVACY_BUDGET_PRIVACY_BUDGET_PREFS_H_
diff --git a/chrome/browser/shell_integration.cc b/chrome/browser/shell_integration.cc
index 5cfe6ce..523a9a0 100644
--- a/chrome/browser/shell_integration.cc
+++ b/chrome/browser/shell_integration.cc
@@ -348,19 +348,31 @@
           this, std::move(callback)));
 }
 
+#if BUILDFLAG(IS_WIN)
+void DefaultSchemeClientWorker::StartCheckIsDefaultAndGetDefaultClientProgId(
+    DefaultSchemeHandlerWorkerCallback callback) {
+  g_sequenced_task_runner.Get()->PostTask(
+      FROM_HERE,
+      base::BindOnce(
+          &DefaultSchemeClientWorker::CheckIsDefaultAndGetDefaultClientProgId,
+          this, std::move(callback)));
+}
+#endif
+
 ///////////////////////////////////////////////////////////////////////////////
 // DefaultSchemeClientWorker, protected:
 
 DefaultSchemeClientWorker::~DefaultSchemeClientWorker() = default;
 
-void DefaultSchemeClientWorker::OnCheckIsDefaultAndGetDefaultClientNameComplete(
-    DefaultWebClientState state,
-    std::u16string program_name,
-    DefaultSchemeHandlerWorkerCallback callback) {
+void DefaultSchemeClientWorker::
+    OnCheckIsDefaultAndGetDefaultClientValueComplete(
+        DefaultWebClientState state,
+        std::u16string client_value,
+        DefaultSchemeHandlerWorkerCallback callback) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
 
   if (!callback.is_null() && IsValidDefaultWebClientState(state)) {
-    std::move(callback).Run(state, program_name);
+    std::move(callback).Run(state, client_value);
   }
 }
 
@@ -378,10 +390,27 @@
   content::GetUIThreadTaskRunner({})->PostTask(
       FROM_HERE,
       base::BindOnce(&DefaultSchemeClientWorker::
-                         OnCheckIsDefaultAndGetDefaultClientNameComplete,
+                         OnCheckIsDefaultAndGetDefaultClientValueComplete,
                      this, state, program_name, std::move(callback)));
 }
 
+#if BUILDFLAG(IS_WIN)
+void DefaultSchemeClientWorker::CheckIsDefaultAndGetDefaultClientProgId(
+    DefaultSchemeHandlerWorkerCallback callback) {
+  DCHECK(!url_.is_empty());
+  base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+                                                base::BlockingType::MAY_BLOCK);
+
+  DefaultWebClientState state = CheckIsDefaultImpl();
+  std::u16string program_id = GetDefaultClientProgIdImpl();
+  content::GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&DefaultSchemeClientWorker::
+                         OnCheckIsDefaultAndGetDefaultClientValueComplete,
+                     this, state, program_id, std::move(callback)));
+}
+#endif
+
 DefaultWebClientState DefaultSchemeClientWorker::CheckIsDefaultImpl() {
   return IsDefaultClientForScheme(scheme_);
 }
@@ -390,6 +419,12 @@
   return GetApplicationNameForScheme(url_);
 }
 
+#if BUILDFLAG(IS_WIN)
+std::u16string DefaultSchemeClientWorker::GetDefaultClientProgIdImpl() {
+  return GetProgIdForScheme(url_);
+}
+#endif
+
 void DefaultSchemeClientWorker::SetAsDefaultImpl(
     base::OnceClosure on_finished_callback) {
   switch (GetDefaultSchemeClientSetPermission()) {
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index 93a9a2e..0690cf22 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -74,6 +74,13 @@
 // Returns an empty string on failure.
 std::u16string GetApplicationNameForScheme(const GURL& url);
 
+#if BUILDFLAG(IS_WIN)
+// Returns a string representing the ProgID of the default handler for the
+// scheme of the requested url.
+// Returns an empty string on failure.
+std::u16string GetProgIdForScheme(const GURL& url);
+#endif
+
 #if BUILDFLAG(IS_MAC)
 // Returns a vector which containing all the application paths that can be used
 // to launch the requested URL.
@@ -325,6 +332,14 @@
   void StartCheckIsDefaultAndGetDefaultClientName(
       DefaultSchemeHandlerWorkerCallback callback);
 
+#if BUILDFLAG(IS_WIN)
+  // Checks to see if Chrome is the default application for the |url_|.
+  // The provided callback will be run to communicate the default state to the
+  // caller, and also return the program ID of the default client if available.
+  void StartCheckIsDefaultAndGetDefaultClientProgId(
+      DefaultSchemeHandlerWorkerCallback callback);
+#endif
+
   const std::string& scheme() const { return scheme_; }
   const GURL& url() const { return url_; }
 
@@ -332,9 +347,9 @@
   ~DefaultSchemeClientWorker() override;
 
   // Communicates the result via |callback|.
-  void OnCheckIsDefaultAndGetDefaultClientNameComplete(
+  void OnCheckIsDefaultAndGetDefaultClientValueComplete(
       DefaultWebClientState state,
-      std::u16string program_name,
+      std::u16string client_value,
       DefaultSchemeHandlerWorkerCallback callback);
 
  private:
@@ -343,6 +358,13 @@
   void CheckIsDefaultAndGetDefaultClientName(
       DefaultSchemeHandlerWorkerCallback callback);
 
+#if BUILDFLAG(IS_WIN)
+  // Checks whether Chrome is the default client for |url_|. This also returns
+  // the default client's program ID if available.
+  void CheckIsDefaultAndGetDefaultClientProgId(
+      DefaultSchemeHandlerWorkerCallback callback);
+#endif
+
   // Check if Chrome is the default handler for this scheme.
   DefaultWebClientState CheckIsDefaultImpl() override;
 
@@ -350,6 +372,12 @@
   // sequence.
   virtual std::u16string GetDefaultClientNameImpl();
 
+#if BUILDFLAG(IS_WIN)
+  // Gets the default client program ID for |scheme_|. Always called on a
+  // blocking sequence.
+  std::u16string GetDefaultClientProgIdImpl();
+#endif
+
   // Set Chrome as the default handler for this scheme.
   void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override;
 
diff --git a/chrome/browser/shell_integration_win.cc b/chrome/browser/shell_integration_win.cc
index f01c8ccc..50dfa6d 100644
--- a/chrome/browser/shell_integration_win.cc
+++ b/chrome/browser/shell_integration_win.cc
@@ -164,23 +164,19 @@
 // Windows 8 introduced a new scheme->executable binding system which cannot
 // be retrieved in the HKCR registry subkey method implemented below. We call
 // AssocQueryString with the new Win8-only flag ASSOCF_IS_PROTOCOL instead.
-std::u16string GetAppForSchemeUsingAssocQuery(const GURL& url) {
+std::u16string GetForSchemeUsingAssocQuery(const GURL& url,
+                                           ASSOCSTR assoc_str) {
   const std::wstring url_scheme = base::ASCIIToWide(url.GetScheme());
   if (!IsValidCustomScheme(url_scheme)) {
     return std::u16string();
   }
 
-  // Query AssocQueryString for a human-readable description of the program
-  // that will be invoked given the provided URL spec. This is used only to
-  // populate the external scheme dialog box the user sees when invoking
-  // an unknown external scheme.
   wchar_t out_buffer[1024];
   DWORD buffer_size = std::size(out_buffer);
   HRESULT hr =
-      AssocQueryString(ASSOCF_IS_PROTOCOL, ASSOCSTR_FRIENDLYAPPNAME,
-                       url_scheme.c_str(), NULL, out_buffer, &buffer_size);
+      AssocQueryString(ASSOCF_IS_PROTOCOL, assoc_str, url_scheme.c_str(), NULL,
+                       out_buffer, &buffer_size);
   if (FAILED(hr)) {
-    DLOG(WARNING) << "AssocQueryString failed!";
     return std::u16string();
   }
   return base::AsString16(std::wstring(out_buffer));
@@ -663,7 +659,12 @@
 }
 
 std::u16string GetApplicationNameForScheme(const GURL& url) {
-  std::u16string application_name = GetAppForSchemeUsingAssocQuery(url);
+  // Query AssocQueryString for a human-readable description of the program
+  // that will be invoked given the provided URL spec. This is used only to
+  // populate the external scheme dialog box the user sees when invoking
+  // an unknown external scheme.
+  std::u16string application_name =
+      GetForSchemeUsingAssocQuery(url, ASSOCSTR_FRIENDLYAPPNAME);
   if (!application_name.empty()) {
     return application_name;
   }
@@ -671,6 +672,10 @@
   return GetAppForSchemeUsingRegistry(url);
 }
 
+std::u16string GetProgIdForScheme(const GURL& url) {
+  return GetForSchemeUsingAssocQuery(url, ASSOCSTR_PROGID);
+}
+
 DefaultWebClientState GetDefaultBrowser() {
   return GetDefaultWebClientStateFromShellUtilDefaultState(
       ShellUtil::GetChromeDefaultState());
diff --git a/chrome/browser/signin/android/signin_bridge.cc b/chrome/browser/signin/android/signin_bridge.cc
index 594d9a8..ae78d55b 100644
--- a/chrome/browser/signin/android/signin_bridge.cc
+++ b/chrome/browser/signin/android/signin_bridge.cc
@@ -17,14 +17,12 @@
 
 using base::android::JavaParamRef;
 
-void SigninBridge::StartAddAccountFlow(TabAndroid* tab,
+void SigninBridge::StartAddAccountFlow(ui::WindowAndroid* window,
                                        const std::string& prefilled_email,
                                        const GURL& continue_url) {
-  if (!tab) {
-    return;
-  }
+  DCHECK(window);
   JNIEnv* env = base::android::AttachCurrentThread();
-  Java_SigninBridge_startAddAccountFlow(env, tab->GetJavaObject(),
+  Java_SigninBridge_startAddAccountFlow(env, window->GetJavaObject(),
                                         prefilled_email, continue_url);
 }
 
diff --git a/chrome/browser/signin/android/signin_bridge.h b/chrome/browser/signin/android/signin_bridge.h
index f6acad9..4b1acb31 100644
--- a/chrome/browser/signin/android/signin_bridge.h
+++ b/chrome/browser/signin/android/signin_bridge.h
@@ -7,7 +7,6 @@
 
 #include <string>
 
-#include "chrome/browser/android/tab_android.h"
 #include "components/keyed_service/core/keyed_service.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/public/base/signin_metrics.h"
@@ -28,7 +27,7 @@
 
   // Opens a add account flow pre-filled with |prefilled_email| that opens
   // the specified |continue_url| upon completion.
-  virtual void StartAddAccountFlow(TabAndroid* tab,
+  virtual void StartAddAccountFlow(ui::WindowAndroid* window,
                                    const std::string& prefilled_email,
                                    const GURL& continue_url);
 
diff --git a/chrome/browser/signin/android/web_signin_bridge.cc b/chrome/browser/signin/android/web_signin_bridge.cc
index 27a8d02..74a33197 100644
--- a/chrome/browser/signin/android/web_signin_bridge.cc
+++ b/chrome/browser/signin/android/web_signin_bridge.cc
@@ -5,14 +5,12 @@
 #include "chrome/browser/signin/android//web_signin_bridge.h"
 
 #include "base/android/jni_android.h"
-#include "base/android/jni_string.h"
 #include "base/android/scoped_java_ref.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
-#include "google_apis/gaia/core_account_id.h"
 
 // Must come after all headers that specialize FromJniType() / ToJniType().
 #include "chrome/browser/signin/services/android/jni_headers/WebSigninBridge_jni.h"
@@ -31,7 +29,7 @@
 WebSigninBridge::WebSigninBridge(
     signin::IdentityManager* identity_manager,
     AccountReconcilor* account_reconcilor,
-    std::variant<CoreAccountId, std::string> signin_account,
+    CoreAccountId signin_account,
     base::OnceCallback<void(signin::WebSigninTracker::Result)> callback)
     : tracker_(identity_manager,
                account_reconcilor,
@@ -40,12 +38,12 @@
 
 WebSigninBridge::~WebSigninBridge() = default;
 
-static jlong JNI_WebSigninBridge_CreateWithCoreAccountId(
+static jlong JNI_WebSigninBridge_Create(
     JNIEnv* env,
     Profile* profile,
-    CoreAccountId& account_id,
+    CoreAccountInfo& account,
     const JavaParamRef<jobject>& j_listener) {
-  CHECK(j_listener) << "Listener should be non-null";
+  DCHECK(j_listener) << "Listener should be non-null";
 
   signin::IdentityManager* identity_manager =
       IdentityManagerFactory::GetForProfile(profile);
@@ -56,28 +54,8 @@
           &ForwardOnSigninCompletedToJava,
           base::android::ScopedJavaGlobalRef<jobject>(j_listener));
   return reinterpret_cast<intptr_t>(
-      new WebSigninBridge(identity_manager, account_reconcilor, account_id,
-                          std::move(on_signin_completed)));
-}
-
-static jlong JNI_WebSigninBridge_CreateWithEmail(
-    JNIEnv* env,
-    Profile* profile,
-    std::string& account_email,
-    const JavaParamRef<jobject>& j_listener) {
-  CHECK(j_listener) << "Listener should be non-null";
-
-  signin::IdentityManager* identity_manager =
-      IdentityManagerFactory::GetForProfile(profile);
-  AccountReconcilor* account_reconcilor =
-      AccountReconcilorFactory::GetForProfile(profile);
-  base::OnceCallback<void(signin::WebSigninTracker::Result)>
-      on_signin_completed = base::BindOnce(
-          &ForwardOnSigninCompletedToJava,
-          base::android::ScopedJavaGlobalRef<jobject>(j_listener));
-  return reinterpret_cast<intptr_t>(
-      new WebSigninBridge(identity_manager, account_reconcilor, account_email,
-                          std::move(on_signin_completed)));
+      new WebSigninBridge(identity_manager, account_reconcilor,
+                          account.account_id, std::move(on_signin_completed)));
 }
 
 static void JNI_WebSigninBridge_Destroy(JNIEnv* env, jlong web_signin_bridge) {
diff --git a/chrome/browser/signin/android/web_signin_bridge.h b/chrome/browser/signin/android/web_signin_bridge.h
index 1785a1f..9e57e2ba 100644
--- a/chrome/browser/signin/android/web_signin_bridge.h
+++ b/chrome/browser/signin/android/web_signin_bridge.h
@@ -15,7 +15,7 @@
   explicit WebSigninBridge(
       signin::IdentityManager* identity_manager,
       AccountReconcilor* account_reconcilor,
-      std::variant<CoreAccountId, std::string> signin_account,
+      CoreAccountId signin_account,
       base::OnceCallback<void(signin::WebSigninTracker::Result)>
           on_signin_completed);
 
diff --git a/chrome/browser/signin/chrome_signin_client.cc b/chrome/browser/signin/chrome_signin_client.cc
index 0d221dad..9fdb57e3 100644
--- a/chrome/browser/signin/chrome_signin_client.cc
+++ b/chrome/browser/signin/chrome_signin_client.cc
@@ -41,6 +41,7 @@
 #include "chrome/common/pref_names.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/metrics/metrics_service.h"
+#include "components/plus_addresses/core/common/features.h"
 #include "components/policy/core/browser/browser_policy_connector.h"
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/cookie_settings_util.h"
@@ -188,11 +189,13 @@
 
 class ChromeOAuthConsumerRegistry : public signin::OAuthConsumerRegistry {
  protected:
-  signin::OAuthConsumer GetOAuthConsumerFromIdInternal(
-      signin::OAuthConsumerId oauth_consumer_id) const override {
-    // TODO(crbug.com/425896213): Temporarily notreached until consumers are
-    // added.
-    NOTREACHED();
+  signin::OAuthConsumer GetOAuthConsumerForEnterprisePlusAddress()
+      const override {
+    CHECK(base::FeatureList::IsEnabled(
+        plus_addresses::features::kPlusAddressesEnabled));
+    return signin::OAuthConsumer(
+        signin::oauth_consumer_name::kEnterprisePlusAddressName,
+        {plus_addresses::features::kEnterprisePlusAddressOAuthScope.Get()});
   }
 };
 
diff --git a/chrome/browser/signin/chrome_signin_helper.cc b/chrome/browser/signin/chrome_signin_helper.cc
index 6eb55ae..16396a7 100644
--- a/chrome/browser/signin/chrome_signin_helper.cc
+++ b/chrome/browser/signin/chrome_signin_helper.cc
@@ -30,7 +30,6 @@
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/base/signin_buildflags.h"
 #include "components/signin/public/base/signin_switches.h"
-#include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_cookie_mutator.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "content/public/browser/browser_thread.h"
@@ -360,20 +359,8 @@
 
   if (service_type == signin::GAIA_SERVICE_TYPE_ADDSESSION &&
       base::FeatureList::IsEnabled(switches::kSupportWebSigninAddSession)) {
-    signin::IdentityManager* const identity_manager =
-        IdentityManagerFactory::GetForProfile(profile);
-    for (CoreAccountInfo account :
-         identity_manager->GetAccountsWithRefreshTokens()) {
-      if (gaia::AreEmailsSame(account.email, manage_accounts_params.email)) {
-        // If account is already on device don't start the add account flow.
-        // TODO(crbug.com/456445865): Consider adding a reauth flow or a wait
-        // for cookies in this scenario.
-        return;
-      }
-    }
     SigninBridgeFactory::GetForProfile(profile)->StartAddAccountFlow(
-        TabAndroid::FromWebContents(web_contents), manage_accounts_params.email,
-        continue_url);
+        window, manage_accounts_params.email, continue_url);
     return;
   }
 
diff --git a/chrome/browser/signin/chrome_signin_helper_unittest.cc b/chrome/browser/signin/chrome_signin_helper_unittest.cc
index 58dad5a..c47ce32 100644
--- a/chrome/browser/signin/chrome_signin_helper_unittest.cc
+++ b/chrome/browser/signin/chrome_signin_helper_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/test/bind.h"
 #include "build/buildflag.h"
 #include "chrome/browser/content_settings/cookie_settings_factory.h"
+#include "chrome/browser/signin/android/signin_bridge.h"
 #include "chrome/browser/signin/android/signin_bridge_factory.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/content_settings/core/browser/cookie_settings.h"
@@ -46,8 +47,6 @@
 #include "url/gurl.h"
 
 #if BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/android/tab_android.h"
-#include "chrome/browser/signin/android/signin_bridge.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_test_helper.h"
 #include "ui/android/window_android.h"
@@ -201,7 +200,7 @@
 
   MOCK_METHOD(void,
               StartAddAccountFlow,
-              (TabAndroid * window,
+              (ui::WindowAndroid * window,
                const std::string& prefilled_email,
                const GURL& continue_url),
               (override));
diff --git a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/WebSigninBridge.java b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/WebSigninBridge.java
index 59636f2bd..9e128eb 100644
--- a/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/WebSigninBridge.java
+++ b/chrome/browser/signin/services/android/java/src/org/chromium/chrome/browser/signin/services/WebSigninBridge.java
@@ -14,8 +14,8 @@
 import org.chromium.base.Callback;
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.components.signin.base.CoreAccountInfo;
 import org.chromium.components.signin.browser.WebSigninTrackerResult;
-import org.chromium.google_apis.gaia.CoreAccountId;
 
 import java.util.Objects;
 
@@ -36,23 +36,11 @@
          * @param account The primary account account used for the sign-in process.
          * @param callback The callback to be notified about sign-in result.
          */
-        public WebSigninBridge createWithCoreAccountId(
+        public WebSigninBridge create(
                 Profile profile,
-                CoreAccountId accountId,
+                CoreAccountInfo account,
                 Callback<@WebSigninTrackerResult Integer> callback) {
-            return new WebSigninBridge(profile, accountId, callback);
-        }
-
-        /**
-         * Creates a WebSigninBridge object.
-         *
-         * @param profile The profile to use for the sign-in.
-         * @param email The primary account account email used for the sign-in process.
-         * @param callback The callback to be notified about sign-in result.
-         */
-        public WebSigninBridge createWithEmail(
-                Profile profile, String email, Callback<@WebSigninTrackerResult Integer> callback) {
-            return new WebSigninBridge(profile, email, callback);
+            return new WebSigninBridge(profile, account, callback);
         }
     }
 
@@ -68,30 +56,11 @@
      */
     private WebSigninBridge(
             Profile profile,
-            CoreAccountId accountId,
+            CoreAccountInfo account,
             Callback<@WebSigninTrackerResult Integer> callback) {
-        Objects.requireNonNull(accountId);
+        Objects.requireNonNull(account);
         Objects.requireNonNull(callback);
-        mNativeWebSigninBridge =
-                WebSigninBridgeJni.get().createWithCoreAccountId(profile, accountId, callback);
-        assert mNativeWebSigninBridge != 0 : "Couldn't create native WebSigninBridge object!";
-    }
-
-    /**
-     * Notifies the passed {@link Listener} when the sign-in process completes either successfully
-     * or with an error. Successful completion means that the primary account is available in
-     * cookies. Should be explicitly destroyed using {@link #destroy()} to release native resources.
-     *
-     * @param account The primary account account used for the sign-in process.
-     * @param callback The callback to be notified about sign-in result.
-     */
-    private WebSigninBridge(
-            Profile profile, String email, Callback<@WebSigninTrackerResult Integer> callback) {
-        Objects.requireNonNull(email);
-        Objects.requireNonNull(callback);
-        mNativeWebSigninBridge =
-                org.chromium.chrome.browser.signin.services.WebSigninBridgeJni.get()
-                        .createWithEmail(profile, email, callback);
+        mNativeWebSigninBridge = WebSigninBridgeJni.get().create(profile, account, callback);
         assert mNativeWebSigninBridge != 0 : "Couldn't create native WebSigninBridge object!";
     }
 
@@ -111,14 +80,9 @@
 
     @NativeMethods
     interface Natives {
-        long createWithCoreAccountId(
+        long create(
                 @JniType("Profile*") Profile profile,
-                @JniType("CoreAccountId") CoreAccountId account,
-                Callback<@WebSigninTrackerResult Integer> callback);
-
-        long createWithEmail(
-                @JniType("Profile*") Profile profile,
-                @JniType("std::string") String email,
+                @JniType("CoreAccountInfo") CoreAccountInfo account,
                 Callback<@WebSigninTrackerResult Integer> callback);
 
         void destroy(long webSigninBridgePtr);
diff --git a/chrome/browser/signin/services/android/junit/src/org/chromium/chrome/browser/signin/services/WebSigninBridgeTest.java b/chrome/browser/signin/services/android/junit/src/org/chromium/chrome/browser/signin/services/WebSigninBridgeTest.java
index 7eb6688..5e9cf50 100644
--- a/chrome/browser/signin/services/android/junit/src/org/chromium/chrome/browser/signin/services/WebSigninBridgeTest.java
+++ b/chrome/browser/signin/services/android/junit/src/org/chromium/chrome/browser/signin/services/WebSigninBridgeTest.java
@@ -43,25 +43,21 @@
     @Before
     public void setUp() {
         WebSigninBridgeJni.setInstanceForTesting(mNativeMock);
-        when(mNativeMock.createWithCoreAccountId(
-                        mProfileMock, CORE_ACCOUNT_INFO.getId(), mCallbackMock))
+        when(mNativeMock.create(mProfileMock, CORE_ACCOUNT_INFO, mCallbackMock))
                 .thenReturn(NATIVE_WEB_SIGNIN_BRIDGE);
     }
 
     @Test
     public void testFactoryCreate() {
         WebSigninBridge webSigninBridge =
-                mFactory.createWithCoreAccountId(
-                        mProfileMock, CORE_ACCOUNT_INFO.getId(), mCallbackMock);
+                mFactory.create(mProfileMock, CORE_ACCOUNT_INFO, mCallbackMock);
         Assert.assertNotNull("Factory#create should not return null!", webSigninBridge);
-        verify(mNativeMock)
-                .createWithCoreAccountId(mProfileMock, CORE_ACCOUNT_INFO.getId(), mCallbackMock);
+        verify(mNativeMock).create(mProfileMock, CORE_ACCOUNT_INFO, mCallbackMock);
     }
 
     @Test
     public void testDestroy() {
-        mFactory.createWithCoreAccountId(mProfileMock, CORE_ACCOUNT_INFO.getId(), mCallbackMock)
-                .destroy();
+        mFactory.create(mProfileMock, CORE_ACCOUNT_INFO, mCallbackMock).destroy();
         verify(mNativeMock).destroy(NATIVE_WEB_SIGNIN_BRIDGE);
     }
 
diff --git a/chrome/browser/subresource_filter/ad_heuristic_tpcd_browsertest.cc b/chrome/browser/subresource_filter/ad_heuristic_tpcd_browsertest.cc
index 4b9d150..f676fcb 100644
--- a/chrome/browser/subresource_filter/ad_heuristic_tpcd_browsertest.cc
+++ b/chrome/browser/subresource_filter/ad_heuristic_tpcd_browsertest.cc
@@ -33,7 +33,6 @@
 #include "components/prefs/pref_service.h"
 #include "components/privacy_sandbox/tpcd_pref_names.h"
 #include "components/privacy_sandbox/tpcd_utils.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "components/subresource_filter/core/common/test_ruleset_utils.h"
 #include "components/tpcd/metadata/browser/parser.h"
 #include "components/user_prefs/user_prefs.h"
diff --git a/chrome/browser/tpcd/experiment/eligibility_service_unittest.cc b/chrome/browser/tpcd/experiment/eligibility_service_unittest.cc
index 2d3692e..48398f5 100644
--- a/chrome/browser/tpcd/experiment/eligibility_service_unittest.cc
+++ b/chrome/browser/tpcd/experiment/eligibility_service_unittest.cc
@@ -30,7 +30,6 @@
 #include "components/privacy_sandbox/privacy_sandbox_test_util.h"
 #include "components/privacy_sandbox/tpcd_experiment_eligibility.h"
 #include "components/privacy_sandbox/tracking_protection_onboarding.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "components/version_info/channel.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_task_environment.h"
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
index 66c5983..8bc4b96 100644
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenu.java
@@ -253,6 +253,7 @@
     private final int mChipHighlightExtension;
     private final int[] mTempLocation;
     private final AppMenuVisibilityDelegate mVisibilityDelegate;
+    private final boolean mDisableVerticalScrollbar;
 
     private @Nullable Context mContext;
     private @Nullable ListView mListView;
@@ -276,8 +277,10 @@
     AppMenu(
             AppMenuVisibilityDelegate visibilityDelegate,
             Resources res,
-            HierarchicalMenuController hierarchicalMenuController) {
+            HierarchicalMenuController hierarchicalMenuController,
+            boolean disableVerticalScrollbar) {
         mVisibilityDelegate = visibilityDelegate;
+        mDisableVerticalScrollbar = disableVerticalScrollbar;
 
         mNegativeSoftwareVerticalOffset =
                 res.getDimensionPixelSize(R.dimen.menu_negative_software_vertical_offset);
@@ -416,6 +419,11 @@
         }
 
         mListView = contentView.findViewById(R.id.app_menu_list);
+        if (mDisableVerticalScrollbar) {
+            // TODO(crbug.com/465107697) Move code to xml file once the feature is launched.
+            // Cleanup AppMenuDelegate too.
+            mListView.setVerticalScrollBarEnabled(false);
+        }
 
         int footerHeight = attachFooter(footer, (ViewGroup) contentView, menuWidth);
         int headerHeight = attachHeader(header, menuWidth);
diff --git a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
index 4cbaa8b3..778a18c 100644
--- a/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
+++ b/chrome/browser/ui/android/appmenu/internal/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuHandlerImpl.java
@@ -305,7 +305,12 @@
                 /* headerModelList= */ null, mModelList, () -> {});
 
         if (mAppMenu == null) {
-            mAppMenu = new AppMenu(this, mContext.getResources(), mHierarchicalMenuController);
+            mAppMenu =
+                    new AppMenu(
+                            this,
+                            mContext.getResources(),
+                            mHierarchicalMenuController,
+                            mAppMenuDelegate.shouldDisableVerticalScrollbar());
             mAppMenuDragHelper = new AppMenuDragHelper(mContext, mAppMenu, itemRowHeight);
         }
 
diff --git a/chrome/browser/ui/android/appmenu/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuDelegate.java b/chrome/browser/ui/android/appmenu/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuDelegate.java
index 1e70d2a..cb284f2 100644
--- a/chrome/browser/ui/android/appmenu/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuDelegate.java
+++ b/chrome/browser/ui/android/appmenu/java/src/org/chromium/chrome/browser/ui/appmenu/AppMenuDelegate.java
@@ -42,6 +42,13 @@
             int itemId, @Nullable Bundle menuItemData, @Nullable MotionEventInfo triggeringMotion);
 
     /**
+     * @return Whether the vertical scroll should be disabled in the app menu.
+     */
+    default boolean shouldDisableVerticalScrollbar() {
+        return false;
+    };
+
+    /**
      * @return {@link AppMenuPropertiesDelegate} instance that the {@link AppMenuHandlerImpl} should
      *     be using.
      */
diff --git a/chrome/browser/ui/android/autofill/save_update_address_profile_flow_manager.h b/chrome/browser/ui/android/autofill/save_update_address_profile_flow_manager.h
index 3f22096..9fb20d1f 100644
--- a/chrome/browser/ui/android/autofill/save_update_address_profile_flow_manager.h
+++ b/chrome/browser/ui/android/autofill/save_update_address_profile_flow_manager.h
@@ -63,6 +63,7 @@
 
   void OnPromptWithDetailsDismissed();
 
+  // TODO: crbug.com/460410690 - Use `AutofillMessageController` instead.
   SaveUpdateAddressProfileMessageController
       save_update_address_profile_message_controller_;
   std::unique_ptr<SaveUpdateAddressProfilePromptController>
diff --git a/chrome/browser/ui/android/logo/BUILD.gn b/chrome/browser/ui/android/logo/BUILD.gn
index cfe48f5d..d15da4d 100644
--- a/chrome/browser/ui/android/logo/BUILD.gn
+++ b/chrome/browser/ui/android/logo/BUILD.gn
@@ -73,6 +73,7 @@
   resources_package = "org.chromium.chrome.browser.logo"
   sources = [
     "java/src/org/chromium/chrome/browser/logo/CachedTintedBitmapUnitTest.java",
+    "java/src/org/chromium/chrome/browser/logo/LogoCoordinatorUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoUtilsUnitTest.java",
     "java/src/org/chromium/chrome/browser/logo/LogoViewBinderUnitTest.java",
@@ -87,9 +88,11 @@
     "//base:base_junit_test_support",
     "//chrome/android:chrome_java",
     "//chrome/browser/flags:java",
+    "//chrome/browser/ntp_customization:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/search_engines/android:java",
+    "//components/browser_ui/theme/android:java_resources",
     "//components/image_fetcher:java",
     "//components/search_engines/android:java",
     "//content/public/android:content_full_java",
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinator.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinator.java
index ffe044d2..2218f29 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinator.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinator.java
@@ -5,9 +5,11 @@
 package org.chromium.chrome.browser.logo;
 
 import android.content.Context;
+import android.graphics.Bitmap;
 import android.graphics.drawable.Drawable;
 import android.view.View.MeasureSpec;
 
+import androidx.annotation.ColorInt;
 import androidx.core.content.ContextCompat;
 
 import org.chromium.base.Callback;
@@ -15,7 +17,12 @@
 import org.chromium.build.annotations.Nullable;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.logo.LogoBridge.Logo;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationConfigManager;
 import org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils.NtpBackgroundImageType;
+import org.chromium.chrome.browser.ntp_customization.theme.chrome_colors.NtpThemeColorInfo;
+import org.chromium.chrome.browser.ntp_customization.theme.chrome_colors.NtpThemeColorUtils;
+import org.chromium.chrome.browser.ntp_customization.theme.upload_image.BackgroundImageInfo;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.ui.modelutil.PropertyModel;
@@ -24,9 +31,10 @@
 /** Coordinator used to fetch and load logo image for Start surface and NTP. */
 @NullMarked
 public class LogoCoordinator {
-    private final LogoMediator mMediator;
     private final PropertyModel mLogoModel;
+    private LogoMediator mMediator;
     private LogoView mLogoView;
+    private NtpCustomizationConfigManager.@Nullable HomepageStateListener mHomepageStateListener;
 
     // The default google logo that is shared across all NTPs.
     static final CachedTintedBitmap sDefaultGoogleLogo =
@@ -62,7 +70,10 @@
         if (ChromeFeatureList.sAndroidLogoViewRefactor.isEnabled()) {
             defaultGoogleLogoDrawable =
                     ContextCompat.getDrawable(context, R.drawable.ic_google_logo);
-            NtpCustomizationUtils.setTintForDefaultGoogleLogo(context, defaultGoogleLogoDrawable);
+            if (ChromeFeatureList.sNewTabPageCustomizationV2.isEnabled()) {
+                NtpCustomizationUtils.setTintForDefaultGoogleLogo(
+                        context, defaultGoogleLogoDrawable);
+            }
         }
 
         mMediator =
@@ -74,6 +85,50 @@
                         visibilityObserver,
                         sDefaultGoogleLogo,
                         defaultGoogleLogoDrawable);
+
+        // Should be called after mMediator is created.
+        maybeInitHomepageStateListener(context);
+    }
+
+    private void maybeInitHomepageStateListener(Context context) {
+        if (!ChromeFeatureList.sAndroidLogoViewRefactor.isEnabled()
+                || !ChromeFeatureList.sNewTabPageCustomizationV2.isEnabled()) {
+            return;
+        }
+
+        mHomepageStateListener =
+                new NtpCustomizationConfigManager.HomepageStateListener() {
+                    @Override
+                    public void onBackgroundImageChanged(
+                            Bitmap originalBitmap,
+                            @Nullable BackgroundImageInfo backgroundImageInfo,
+                            boolean fromInitialization,
+                            int oldType,
+                            int newType) {
+                        maybeUpdateTintForDefaultGoogleLogo(
+                                context, newType, /* primaryColor= */ null);
+                    }
+
+                    @Override
+                    public void onBackgroundColorChanged(
+                            @Nullable NtpThemeColorInfo ntpThemeColorInfo,
+                            int backgroundColor,
+                            boolean fromInitialization,
+                            int oldType,
+                            int newType) {
+                        @ColorInt
+                        Integer primaryColor =
+                                ntpThemeColorInfo == null
+                                        ? null
+                                        : NtpThemeColorUtils.getPrimaryColorFromColorInfo(
+                                                context, ntpThemeColorInfo);
+                        maybeUpdateTintForDefaultGoogleLogo(context, newType, primaryColor);
+                    }
+                };
+        // Skips being notified from NtpCustomizationConfigManager since the drawable has been
+        // tinted if necessary when the initial logo view is shown.
+        NtpCustomizationConfigManager.getInstance()
+                .addListener(mHomepageStateListener, context, /* skipNotify= */ true);
     }
 
     /**
@@ -108,6 +163,10 @@
         mMediator.destroy();
         mLogoView.destroy();
         mLogoView = null;
+        if (mHomepageStateListener != null) {
+            NtpCustomizationConfigManager.getInstance().removeListener(mHomepageStateListener);
+            mHomepageStateListener = null;
+        }
     }
 
     /**
@@ -162,10 +221,25 @@
     }
 
     /**
-     * @see LogoMediator#isLogoVisible
+     * Updates the default Google logo with a tint color if it is shown.
+     *
+     * @param context The context to get themed color.
+     * @param backgroundType The NTP's background theme type.
+     * @param primaryColor The primary color is selected.
      */
-    public boolean isLogoVisible() {
-        return mMediator.isLogoVisible();
+    private void maybeUpdateTintForDefaultGoogleLogo(
+            Context context,
+            @NtpBackgroundImageType int backgroundType,
+            @Nullable @ColorInt Integer primaryColor) {
+        // If the default Google logo isn't shown, returns here.
+        if (!mMediator.isDefaultGoogleLogoShown()) return;
+
+        Drawable defaultGoogleLogoDrawable =
+                ContextCompat.getDrawable(context, R.drawable.ic_google_logo);
+        Drawable tintedDrawable =
+                NtpCustomizationUtils.getTintedGoogleLogoDrawableImpl(
+                        context, defaultGoogleLogoDrawable, backgroundType, primaryColor);
+        mMediator.updateDefaultGoogleLogo(tintedDrawable);
     }
 
     /**
@@ -188,4 +262,8 @@
     public void setOnLogoClickUrlForTesting(String onLogoClickUrl) {
         mMediator.setOnLogoClickUrlForTesting(onLogoClickUrl);
     }
+
+    void setMediatorForTesting(LogoMediator mediator) {
+        mMediator = mediator;
+    }
 }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinatorUnitTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinatorUnitTest.java
new file mode 100644
index 0000000..bbd027a
--- /dev/null
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoCoordinatorUnitTest.java
@@ -0,0 +1,202 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.logo;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Color;
+import android.graphics.drawable.Drawable;
+import android.view.ContextThemeWrapper;
+
+import androidx.annotation.ColorInt;
+import androidx.test.core.app.ApplicationProvider;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.Callback;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.Features.DisableFeatures;
+import org.chromium.base.test.util.Features.EnableFeatures;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
+import org.chromium.chrome.browser.logo.LogoBridge.Logo;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationConfigManager;
+import org.chromium.chrome.browser.ntp_customization.NtpCustomizationUtils.NtpBackgroundImageType;
+import org.chromium.chrome.browser.ntp_customization.theme.chrome_colors.NtpThemeColorFromHexInfo;
+import org.chromium.chrome.browser.ntp_customization.theme.upload_image.BackgroundImageInfo;
+import org.chromium.content_public.browser.LoadUrlParams;
+
+/** Unit tests for the {@link LogoCoordinator}. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class LogoCoordinatorUnitTest {
+    @Rule public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+    @Mock private LogoView mLogoView;
+    @Mock private Callback<LoadUrlParams> mLogoClickedCallback;
+    @Mock private Callback<Logo> mOnLogoAvailableCallback;
+    @Mock private LogoCoordinator.VisibilityObserver mVisibilityObserver;
+    @Mock private LogoMediator mLogoMediator;
+    @Mock private NtpCustomizationConfigManager mNtpCustomizationConfigManager;
+
+    @Captor
+    private ArgumentCaptor<NtpCustomizationConfigManager.HomepageStateListener>
+            mHomepageStateListenerCaptor;
+
+    private Context mContext;
+    private LogoCoordinator mLogoCoordinator;
+
+    @Before
+    public void setUp() {
+        mContext =
+                new ContextThemeWrapper(
+                        ApplicationProvider.getApplicationContext(),
+                        R.style.Theme_BrowserUI_DayNight);
+        NtpCustomizationConfigManager.setInstanceForTesting(mNtpCustomizationConfigManager);
+    }
+
+    @Test
+    @DisableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testMaybeInitHomepageStateListener_featuresDisabled() {
+        createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager, never()).addListener(any(), any(), anyBoolean());
+    }
+
+    @Test
+    @EnableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testMaybeInitHomepageStateListener_featuresEnabled() {
+        createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager)
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(true));
+    }
+
+    @Test
+    @EnableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testHomepageStateListener_logoNotShown() {
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        BackgroundImageInfo backgroundImageInfo = mock(BackgroundImageInfo.class);
+
+        when(mLogoMediator.isDefaultGoogleLogoShown()).thenReturn(false);
+        createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager)
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(true));
+
+        mHomepageStateListenerCaptor
+                .getValue()
+                .onBackgroundImageChanged(
+                        bitmap,
+                        backgroundImageInfo,
+                        false,
+                        NtpBackgroundImageType.DEFAULT,
+                        NtpBackgroundImageType.IMAGE_FROM_DISK);
+
+        verify(mLogoMediator, never()).updateDefaultGoogleLogo(any());
+    }
+
+    @Test
+    @EnableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testHomepageStateListener_onBackgroundImageChanged() {
+        Bitmap bitmap = Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888);
+        BackgroundImageInfo backgroundImageInfo = mock(BackgroundImageInfo.class);
+
+        when(mLogoMediator.isDefaultGoogleLogoShown()).thenReturn(true);
+        createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager)
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(true));
+
+        mHomepageStateListenerCaptor
+                .getValue()
+                .onBackgroundImageChanged(
+                        bitmap,
+                        backgroundImageInfo,
+                        false,
+                        NtpBackgroundImageType.DEFAULT,
+                        NtpBackgroundImageType.IMAGE_FROM_DISK);
+
+        verify(mLogoMediator).updateDefaultGoogleLogo(any(Drawable.class));
+    }
+
+    @Test
+    @EnableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testHomepageStateListener_onBackgroundColorChanged() {
+        @ColorInt int backgroundColor = Color.RED;
+        @ColorInt int primaryColor = Color.BLUE;
+        NtpThemeColorFromHexInfo colorFromHexInfo =
+                new NtpThemeColorFromHexInfo(mContext, backgroundColor, primaryColor);
+        when(mLogoMediator.isDefaultGoogleLogoShown()).thenReturn(true);
+
+        createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager)
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(true));
+
+        mHomepageStateListenerCaptor
+                .getValue()
+                .onBackgroundColorChanged(
+                        colorFromHexInfo,
+                        backgroundColor,
+                        false,
+                        NtpBackgroundImageType.DEFAULT,
+                        NtpBackgroundImageType.COLOR_FROM_HEX);
+
+        verify(mLogoMediator).updateDefaultGoogleLogo(any(Drawable.class));
+    }
+
+    @Test
+    @EnableFeatures({
+        ChromeFeatureList.ANDROID_LOGO_VIEW_REFACTOR,
+        ChromeFeatureList.NEW_TAB_PAGE_CUSTOMIZATION_V2
+    })
+    public void testDestroyRemovesListener() {
+        mLogoCoordinator = createLogoCoordinator();
+        verify(mNtpCustomizationConfigManager)
+                .addListener(mHomepageStateListenerCaptor.capture(), eq(mContext), eq(true));
+        mLogoCoordinator.destroy();
+        verify(mNtpCustomizationConfigManager)
+                .removeListener(mHomepageStateListenerCaptor.getValue());
+    }
+
+    private LogoCoordinator createLogoCoordinator() {
+        LogoCoordinator coordinator =
+                new LogoCoordinator(
+                        mContext,
+                        mLogoClickedCallback,
+                        mLogoView,
+                        mOnLogoAvailableCallback,
+                        mVisibilityObserver);
+        coordinator.setMediatorForTesting(mLogoMediator);
+        return coordinator;
+    }
+}
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
index 509ad6f..f8b5f973 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediator.java
@@ -94,7 +94,7 @@
     private boolean mHasLogoLoadedForCurrentSearchEngine;
     private final LogoCoordinator.@Nullable VisibilityObserver mVisibilityObserver;
     private final CachedTintedBitmap mDefaultGoogleLogo;
-    private final @Nullable Drawable mDefaultGoogleLogoDrawable;
+    private @Nullable Drawable mDefaultGoogleLogoDrawable;
     private final boolean mIsRefactorEnabled;
     private boolean mShouldShowLogo;
     private boolean mIsLoadPending;
@@ -235,6 +235,13 @@
         return mShouldShowLogo && mLogoModel.get(LogoProperties.VISIBILITY);
     }
 
+    /** Returns whether the default Google Logo is shown. */
+    boolean isDefaultGoogleLogoShown() {
+        return mShouldShowLogo
+                && mLogoModel.get(LogoProperties.VISIBILITY)
+                && mLogoModel.get(LogoProperties.LOGO) == null;
+    }
+
     /**
      * Load the search provider logo on Start surface.
      *
@@ -338,6 +345,18 @@
         return mDefaultGoogleLogoDrawable;
     }
 
+    /**
+     * Updates the drawable of the LogoView and show it.
+     *
+     * @param drawable The updated drawable for default Google logo.
+     */
+    void updateDefaultGoogleLogo(Drawable drawable) {
+        mDefaultGoogleLogoDrawable = drawable;
+
+        mLogoModel.set(LogoProperties.DEFAULT_GOOGLE_LOGO_DRAWABLE, mDefaultGoogleLogoDrawable);
+        mLogoModel.set(LogoProperties.SHOW_DEFAULT_GOOGLE_LOGO, true);
+    }
+
     public void onLogoClicked(boolean isAnimatedLogoShowing) {
         if (mLogoBridge == null) return;
 
@@ -483,15 +502,11 @@
         mSearchEngineKeyword = null;
     }
 
-    @Nullable ImageFetcher getImageFetcherForTesting() {
-        return mImageFetcher;
-    }
-
-    @Nullable LogoBridge getLogoBridgeForTesting() {
-        return mLogoBridge;
-    }
-
     boolean getIsLoadPendingForTesting() {
         return mIsLoadPending;
     }
+
+    public void setShouldShowLogoForTesting(boolean shouldShowLogo) {
+        mShouldShowLogo = shouldShowLogo;
+    }
 }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
index ed7887d8..bb08ad7 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoMediatorUnitTest.java
@@ -4,7 +4,10 @@
 
 package org.chromium.chrome.browser.logo;
 
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
@@ -40,7 +43,6 @@
 import org.chromium.chrome.browser.preferences.ChromeSharedPreferences;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.search_engines.TemplateUrlServiceFactory;
-import org.chromium.components.image_fetcher.ImageFetcher;
 import org.chromium.components.search_engines.TemplateUrl;
 import org.chromium.components.search_engines.TemplateUrlService;
 import org.chromium.content_public.browser.LoadUrlParams;
@@ -58,8 +60,6 @@
 
     @Mock LogoBridge mLogoBridge;
 
-    @Mock ImageFetcher mImageFetcher;
-
     @Mock TemplateUrlService mTemplateUrlService;
 
     @Mock TemplateUrl mTemplateUrl;
@@ -184,13 +184,13 @@
         LogoMediator logoMediator = createMediatorWithoutNative();
         logoMediator.updateVisibility(/* animationEnabled= */ false);
 
-        Assert.assertTrue(logoMediator.isLogoVisible());
+        assertTrue(logoMediator.isLogoVisible());
         // When parent surface is shown while native library isn't loaded, calling
         // updateVisibilityAndMaybeCleanUp() will add a pending load task.
-        Assert.assertTrue(logoMediator.getIsLoadPendingForTesting());
+        assertTrue(logoMediator.getIsLoadPendingForTesting());
         logoMediator.initWithNative(mProfile);
 
-        Assert.assertTrue(logoMediator.isLogoVisible());
+        assertTrue(logoMediator.isLogoVisible());
         verify(mLogoBridge, times(1)).getCurrentLogo(any());
         verify(mTemplateUrlService).addObserver(logoMediator);
     }
@@ -222,7 +222,7 @@
         // destroyed.
         logoMediator.setLogoBridgeForTesting(mLogoBridge);
         logoMediator.updateVisibility(/* animationEnabled= */ false);
-        Assert.assertTrue(logoMediator.isLogoVisible());
+        assertTrue(logoMediator.isLogoVisible());
         verify(mLogoBridge).getCurrentLogo(any());
         verify(mLogoBridge, never()).destroy();
         Assert.assertFalse(mLogoModel.get(LogoProperties.ANIMATION_ENABLED));
@@ -230,7 +230,7 @@
         // Attached the test for animationEnabled.
         logoMediator.setHasLogoLoadedForCurrentSearchEngineForTesting(false);
         logoMediator.updateVisibility(/* animationEnabled= */ true);
-        Assert.assertTrue(mLogoModel.get(LogoProperties.ANIMATION_ENABLED));
+        assertTrue(mLogoModel.get(LogoProperties.ANIMATION_ENABLED));
     }
 
     @Test
@@ -241,6 +241,39 @@
         verify(mTemplateUrlService).removeObserver(logoMediator);
     }
 
+    @Test
+    public void testIsDefaultGoogleLogoShown() {
+        LogoMediator logoMediator = createMediator();
+        Logo logo = mock(Logo.class);
+
+        logoMediator.setShouldShowLogoForTesting(true);
+        mLogoModel.set(LogoProperties.VISIBILITY, true);
+        mLogoModel.set(LogoProperties.LOGO, null);
+        assertTrue(logoMediator.isDefaultGoogleLogoShown());
+
+        logoMediator.setShouldShowLogoForTesting(false);
+        Assert.assertFalse(logoMediator.isDefaultGoogleLogoShown());
+
+        logoMediator.setShouldShowLogoForTesting(true);
+        mLogoModel.set(LogoProperties.VISIBILITY, false);
+        Assert.assertFalse(logoMediator.isDefaultGoogleLogoShown());
+
+        logoMediator.setShouldShowLogoForTesting(true);
+        mLogoModel.set(LogoProperties.VISIBILITY, true);
+        mLogoModel.set(LogoProperties.LOGO, logo);
+        Assert.assertFalse(logoMediator.isDefaultGoogleLogoShown());
+    }
+
+    @Test
+    public void testUpdateDefaultGoogleLogo() {
+        LogoMediator logoMediator = createMediator();
+        Drawable drawable = mock(Drawable.class);
+        logoMediator.updateDefaultGoogleLogo(drawable);
+
+        assertEquals(drawable, logoMediator.getDefaultGoogleLogoDrawable());
+        assertTrue(mLogoModel.get(LogoProperties.SHOW_DEFAULT_GOOGLE_LOGO));
+    }
+
     private LogoMediator createMediator() {
         return createMediator(null);
     }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoProperties.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoProperties.java
index 5fa44a9a0..9475d22b 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoProperties.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoProperties.java
@@ -50,6 +50,8 @@
     WritableObjectPropertyKey<Callback<Logo>> LOGO_AVAILABLE_CALLBACK =
             new WritableObjectPropertyKey<>();
     WritableIntPropertyKey DOODLE_SIZE = new WritableIntPropertyKey();
+    WritableObjectPropertyKey<Boolean> SHOW_DEFAULT_GOOGLE_LOGO =
+            new WritableObjectPropertyKey<>(/* skipEquality= */ true);
 
     PropertyKey[] ALL_KEYS =
             new PropertyKey[] {
@@ -67,6 +69,7 @@
                 SHOW_LOADING_VIEW,
                 ANIMATED_LOGO,
                 LOGO_AVAILABLE_CALLBACK,
-                DOODLE_SIZE
+                DOODLE_SIZE,
+                SHOW_DEFAULT_GOOGLE_LOGO
             };
 }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoView.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoView.java
index 8af19862..cd8a15f 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoView.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoView.java
@@ -522,7 +522,7 @@
      *
      * @return Whether the default search engine logo drawable is available.
      */
-    private boolean maybeShowDefaultLogoDrawable() {
+    boolean maybeShowDefaultLogoDrawable() {
         if (mDefaultGoogleLogoDrawable != null) {
             updateLogoDrawableImpl(
                     mDefaultGoogleLogoDrawable,
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinder.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinder.java
index e3c2367..0badf76 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinder.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinder.java
@@ -55,6 +55,8 @@
             logoView.setLogoAvailableCallback(model.get(LogoProperties.LOGO_AVAILABLE_CALLBACK));
         } else if (LogoProperties.DOODLE_SIZE == propertyKey) {
             logoView.setDoodleSize(model.get(LogoProperties.DOODLE_SIZE));
+        } else if (LogoProperties.SHOW_DEFAULT_GOOGLE_LOGO == propertyKey) {
+            logoView.maybeShowDefaultLogoDrawable();
         } else {
             assert false : "Unhandled property detected in LogoViewBinder!";
         }
diff --git a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinderUnitTest.java b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinderUnitTest.java
index d1cdc3b..77b1656 100644
--- a/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinderUnitTest.java
+++ b/chrome/browser/ui/android/logo/java/src/org/chromium/chrome/browser/logo/LogoViewBinderUnitTest.java
@@ -93,7 +93,6 @@
 
     @Before
     public void setUp() {
-        LogoBridgeJni.setInstanceForTesting(mLogoBridgeJniMock);
         mActivity = Robolectric.buildActivity(Activity.class).setup().get();
         mLogoView = new LogoView(mActivity, null);
         LayoutParams params =
@@ -260,11 +259,11 @@
     @Test
     @SmallTest
     public void testShowSearchProviderInitialView() {
-        PropertyModel LogoModel = new PropertyModel(LogoProperties.ALL_KEYS);
-        PropertyModelChangeProcessor.create(LogoModel, mMockLogoView, new LogoViewBinder());
-        LogoModel.set(LogoProperties.SHOW_SEARCH_PROVIDER_INITIAL_VIEW, true);
+        PropertyModel logoModel = new PropertyModel(LogoProperties.ALL_KEYS);
+        PropertyModelChangeProcessor.create(logoModel, mMockLogoView, new LogoViewBinder());
+        logoModel.set(LogoProperties.SHOW_SEARCH_PROVIDER_INITIAL_VIEW, true);
         verify(mMockLogoView).showSearchProviderInitialView();
-        LogoModel.set(LogoProperties.SHOW_SEARCH_PROVIDER_INITIAL_VIEW, true);
+        logoModel.set(LogoProperties.SHOW_SEARCH_PROVIDER_INITIAL_VIEW, true);
         verify(mMockLogoView, times(2)).showSearchProviderInitialView();
     }
 
@@ -293,4 +292,14 @@
         mLogoModel.set(LogoProperties.DOODLE_SIZE, DoodleSize.TABLET_SPLIT_SCREEN);
         assertEquals(DoodleSize.TABLET_SPLIT_SCREEN, mLogoView.getDoodleSizeForTesting());
     }
+
+    @Test
+    @SmallTest
+    public void testShowDefaultGoogleLogo() {
+        PropertyModel logoModel = new PropertyModel(LogoProperties.ALL_KEYS);
+        PropertyModelChangeProcessor.create(logoModel, mMockLogoView, new LogoViewBinder());
+
+        logoModel.set(LogoProperties.SHOW_DEFAULT_GOOGLE_LOGO, true);
+        verify(mMockLogoView).maybeShowDefaultLogoDrawable();
+    }
 }
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
index 973d601..5e0759c 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediator.java
@@ -320,16 +320,23 @@
         mModel.set(FuseboxProperties.ATTACHMENTS_VISIBLE, !mModelList.isEmpty());
         mModel.set(
                 FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED,
-                !attachmentsContainType(FuseboxAttachmentType.ATTACHMENT_TAB));
+                areAttachmentsCompatibleWithCreateImage());
     }
 
-    private boolean attachmentsContainType(@FuseboxAttachmentType int target) {
+    private boolean areAttachmentsCompatibleWithCreateImage() {
+        int imageCount = 0;
         for (MVCListAdapter.ListItem listItem : mModelList) {
-            if (listItem.type == target) {
-                return true;
+            if (listItem.type == FuseboxAttachmentType.ATTACHMENT_FILE) {
+                return false;
+            }
+            if (listItem.type == FuseboxAttachmentType.ATTACHMENT_TAB) {
+                return false;
+            }
+            if (listItem.type == FuseboxAttachmentType.ATTACHMENT_IMAGE) {
+                imageCount++;
             }
         }
-        return false;
+        return imageCount <= 1;
     }
 
     @VisibleForTesting
diff --git a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
index 0314f50..6b68c42 100644
--- a/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
+++ b/chrome/browser/ui/android/omnibox/java/src/org/chromium/chrome/browser/omnibox/fusebox/FuseboxMediatorUnitTest.java
@@ -199,10 +199,16 @@
             when(mComposeBoxQueryControllerBridge.addTabContext(mockTab)).thenReturn(token);
             when(mComposeBoxQueryControllerBridge.addTabContextFromCache(0)).thenReturn(token);
             mAttachments.add(FuseboxAttachment.forTab(mockTab, mResources));
-        } else if (attachmentType == FuseboxAttachmentType.ATTACHMENT_FILE
-                || attachmentType == FuseboxAttachmentType.ATTACHMENT_IMAGE) {
+        } else if (attachmentType == FuseboxAttachmentType.ATTACHMENT_FILE) {
             doReturn(token).when(mComposeBoxQueryControllerBridge).addFile(eq(title), any(), any());
             mAttachments.add(FuseboxAttachment.forFile(null, title, "image/", new byte[0]));
+        } else if (attachmentType == FuseboxAttachmentType.ATTACHMENT_IMAGE) {
+            doReturn(token).when(mComposeBoxQueryControllerBridge).addFile(eq(title), any(), any());
+            mAttachments.add(
+                    FuseboxAttachment.forCameraImage(
+                            /* thumbnail= */ null, title, "image/", new byte[0]));
+        } else {
+            throw new UnsupportedOperationException();
         }
     }
 
@@ -675,6 +681,26 @@
         assertEquals(0, mAttachments.size());
         mModel.get(FuseboxProperties.BUTTON_ADD_CLICKED).run();
         assertTrue(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
+
+        addAttachment("title", "token1", FuseboxAttachmentType.ATTACHMENT_FILE);
+        assertEquals(1, mAttachments.size());
+        assertFalse(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
+
+        mAttachments.get(0).model.get(FuseboxAttachmentProperties.ON_REMOVE).run();
+        assertEquals(0, mAttachments.size());
+        assertTrue(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
+
+        addAttachment("title", "token2", FuseboxAttachmentType.ATTACHMENT_IMAGE);
+        assertEquals(1, mAttachments.size());
+        assertTrue(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
+
+        addAttachment("title", "token3", FuseboxAttachmentType.ATTACHMENT_IMAGE);
+        assertEquals(2, mAttachments.size());
+        assertFalse(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
+
+        mAttachments.get(0).model.get(FuseboxAttachmentProperties.ON_REMOVE).run();
+        assertEquals(1, mAttachments.size());
+        assertTrue(mModel.get(FuseboxProperties.POPUP_CREATE_IMAGE_BUTTON_ENABLED));
     }
 
     @Test
diff --git a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegate.java b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegate.java
index dc48db4..cbb308b 100644
--- a/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegate.java
+++ b/chrome/browser/ui/android/signin/java/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegate.java
@@ -78,9 +78,9 @@
             CoreAccountInfo accountInfo, AccountPickerDelegate.SigninStateController controller) {
         // Create WebSigninBridge and wait for redirect to the continue url.
         mWebSigninBridge =
-                mWebSigninBridgeFactory.createWithCoreAccountId(
+                mWebSigninBridgeFactory.create(
                         mProfile,
-                        accountInfo.getId(),
+                        accountInfo,
                         createWebSigninBridgeCallback(mCurrentTab, mContinueUrl, controller));
     }
 
diff --git a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegateTest.java b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegateTest.java
index 3238082..12c6201 100644
--- a/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegateTest.java
+++ b/chrome/browser/ui/android/signin/junit/src/org/chromium/chrome/browser/ui/signin/account_picker/WebSigninAccountPickerDelegateTest.java
@@ -83,7 +83,7 @@
         mDelegate =
                 new WebSigninAccountPickerDelegate(
                         mTabMock, mWebSigninBridgeFactoryMock, CONTINUE_URL);
-        when(mWebSigninBridgeFactoryMock.createWithCoreAccountId(eq(mProfileMock), any(), any()))
+        when(mWebSigninBridgeFactoryMock.create(eq(mProfileMock), any(), any()))
                 .thenReturn(mWebSigninBridgeMock);
     }
 
@@ -98,9 +98,9 @@
         mDelegate.onSignInComplete(TestAccounts.ACCOUNT1, mSigninStateControllerMock);
 
         verify(mWebSigninBridgeFactoryMock)
-                .createWithCoreAccountId(
+                .create(
                         eq(mProfileMock),
-                        eq(TestAccounts.ACCOUNT1.getId()),
+                        eq(TestAccounts.ACCOUNT1),
                         mWebSigninCallbackCaptor.capture());
 
         mWebSigninCallbackCaptor.getValue().onResult(WebSigninTrackerResult.SUCCESS);
@@ -117,9 +117,9 @@
         mDelegate.onSignInComplete(TestAccounts.ACCOUNT1, mSigninStateControllerMock);
 
         verify(mWebSigninBridgeFactoryMock)
-                .createWithCoreAccountId(
+                .create(
                         eq(mProfileMock),
-                        eq(TestAccounts.ACCOUNT1.getId()),
+                        eq(TestAccounts.ACCOUNT1),
                         mWebSigninCallbackCaptor.capture());
 
         mWebSigninCallbackCaptor.getValue().onResult(WebSigninTrackerResult.OTHER_ERROR);
@@ -139,9 +139,9 @@
         mDelegate.onSignInComplete(TestAccounts.ACCOUNT1, mSigninStateControllerMock);
 
         verify(mWebSigninBridgeFactoryMock)
-                .createWithCoreAccountId(
+                .create(
                         eq(mProfileMock),
-                        eq(TestAccounts.ACCOUNT1.getId()),
+                        eq(TestAccounts.ACCOUNT1),
                         mWebSigninCallbackCaptor.capture());
 
         mWebSigninCallbackCaptor.getValue().onResult(WebSigninTrackerResult.AUTH_ERROR);
diff --git a/chrome/browser/ui/autofill/BUILD.gn b/chrome/browser/ui/autofill/BUILD.gn
index e987641..abee0df 100644
--- a/chrome/browser/ui/autofill/BUILD.gn
+++ b/chrome/browser/ui/autofill/BUILD.gn
@@ -59,6 +59,8 @@
       "autofill_keyboard_accessory_controller.h",
       "autofill_keyboard_accessory_controller_impl.h",
       "autofill_keyboard_accessory_view.h",
+      "autofill_message_controller.h",
+      "autofill_message_model.h",
       "autofill_snackbar_controller.h",
       "autofill_snackbar_controller_impl.h",
       "autofill_snackbar_type.h",
@@ -182,6 +184,8 @@
     sources += [
       "autofill_keyboard_accessory_controller.cc",
       "autofill_keyboard_accessory_controller_impl.cc",
+      "autofill_message_controller.cc",
+      "autofill_message_model.cc",
       "autofill_snackbar_controller_impl.cc",
     ]
     deps += [
@@ -312,12 +316,15 @@
   if (is_android) {
     sources += [
       "autofill_keyboard_accessory_controller_impl_unittest.cc",
+      "autofill_message_controller_unittest.cc",
+      "autofill_message_model_unittest.cc",
       "autofill_snackbar_controller_impl_unittest.cc",
     ]
     deps += [
       "//chrome/browser/autofill/android:jni_test_headers",
       "//chrome/browser/fast_checkout",
       "//chrome/browser/preferences:android",
+      "//components/messages/android:test_support",
     ]
   } else {
     sources += [
@@ -351,7 +358,10 @@
   public_deps = [ ":autofill" ]
 
   if (is_android) {
-    sources += [ "autofill_keyboard_accessory_controller_impl_test_api.h" ]
+    sources += [
+      "autofill_keyboard_accessory_controller_impl_test_api.h",
+      "autofill_message_controller_test_api.h",
+    ]
   } else {
     sources += [
       "autofill_ai/mock_autofill_ai_import_data_controller.cc",
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_controller.cc b/chrome/browser/ui/autofill/autofill_message_controller.cc
similarity index 94%
rename from chrome/browser/ui/autofill/payments/autofill_message_controller.cc
rename to chrome/browser/ui/autofill/autofill_message_controller.cc
index 5718df0..a8bd196 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_controller.cc
+++ b/chrome/browser/ui/autofill/autofill_message_controller.cc
@@ -2,14 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller.h"
 
 #include <memory>
 
 #include "base/check_op.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/strings/strcat.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 #include "components/messages/android/message_dispatcher_bridge.h"
 
 namespace autofill {
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_controller.h b/chrome/browser/ui/autofill/autofill_message_controller.h
similarity index 84%
rename from chrome/browser/ui/autofill/payments/autofill_message_controller.h
rename to chrome/browser/ui/autofill/autofill_message_controller.h
index e135cf7..8ede062 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_controller.h
+++ b/chrome/browser/ui/autofill/autofill_message_controller.h
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_H_
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_H_
 
 #include <memory>
 
 #include "base/containers/unique_ptr_adapters.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 #include "content/public/browser/web_contents.h"
 
 namespace autofill {
@@ -46,4 +46,4 @@
 
 }  // namespace autofill
 
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_H_
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_H_
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_controller_test_api.h b/chrome/browser/ui/autofill/autofill_message_controller_test_api.h
similarity index 75%
rename from chrome/browser/ui/autofill/payments/autofill_message_controller_test_api.h
rename to chrome/browser/ui/autofill/autofill_message_controller_test_api.h
index cf0f6a6..9a60c27a 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_controller_test_api.h
+++ b/chrome/browser/ui/autofill/autofill_message_controller_test_api.h
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
 
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller.h"
 
 namespace autofill {
 
@@ -41,4 +41,4 @@
 
 }  // namespace autofill
 
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_CONTROLLER_TEST_API_H_
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_controller_unittest.cc b/chrome/browser/ui/autofill/autofill_message_controller_unittest.cc
similarity index 95%
rename from chrome/browser/ui/autofill/payments/autofill_message_controller_unittest.cc
rename to chrome/browser/ui/autofill/autofill_message_controller_unittest.cc
index f5506a3..a8d4ddb5 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_controller_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_message_controller_unittest.cc
@@ -2,13 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller.h"
 
 #include <memory>
 
 #include "base/test/metrics/histogram_tester.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller_test_api.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller_test_api.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
 #include "components/messages/android/mock_message_dispatcher_bridge.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_model.cc b/chrome/browser/ui/autofill/autofill_message_model.cc
similarity index 97%
rename from chrome/browser/ui/autofill/payments/autofill_message_model.cc
rename to chrome/browser/ui/autofill/autofill_message_model.cc
index 049edfe..6db43de 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_model.cc
+++ b/chrome/browser/ui/autofill/autofill_message_model.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 
 #include "base/memory/ptr_util.h"
 #include "chrome/browser/android/resource_mapper.h"
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_model.h b/chrome/browser/ui/autofill/autofill_message_model.h
similarity index 90%
rename from chrome/browser/ui/autofill/payments/autofill_message_model.h
rename to chrome/browser/ui/autofill/autofill_message_model.h
index db86e953..f3650ab 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_model.h
+++ b/chrome/browser/ui/autofill/autofill_message_model.h
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#ifndef CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_MODEL_H_
-#define CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_MODEL_H_
+#ifndef CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_MODEL_H_
+#define CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_MODEL_H_
 
 #include <memory>
 #include <string>
@@ -66,4 +66,4 @@
 
 }  // namespace autofill
 
-#endif  // CHROME_BROWSER_UI_AUTOFILL_PAYMENTS_AUTOFILL_MESSAGE_MODEL_H_
+#endif  // CHROME_BROWSER_UI_AUTOFILL_AUTOFILL_MESSAGE_MODEL_H_
diff --git a/chrome/browser/ui/autofill/payments/autofill_message_model_unittest.cc b/chrome/browser/ui/autofill/autofill_message_model_unittest.cc
similarity index 97%
rename from chrome/browser/ui/autofill/payments/autofill_message_model_unittest.cc
rename to chrome/browser/ui/autofill/autofill_message_model_unittest.cc
index 8dca3d6..7a7e864 100644
--- a/chrome/browser/ui/autofill/payments/autofill_message_model_unittest.cc
+++ b/chrome/browser/ui/autofill/autofill_message_model_unittest.cc
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 
 #include <string>
 
diff --git a/chrome/browser/ui/autofill/payments/BUILD.gn b/chrome/browser/ui/autofill/payments/BUILD.gn
index fd1a526..0ab4a304 100644
--- a/chrome/browser/ui/autofill/payments/BUILD.gn
+++ b/chrome/browser/ui/autofill/payments/BUILD.gn
@@ -35,8 +35,6 @@
     sources += [
       "android_bnpl_ui_delegate.h",
       "android_payments_window_manager.h",
-      "autofill_message_controller.h",
-      "autofill_message_model.h",
       "offer_notification_controller_android.h",
     ]
     public_deps += [
@@ -119,8 +117,6 @@
     sources += [
       "android_bnpl_ui_delegate.cc",
       "android_payments_window_manager.cc",
-      "autofill_message_controller.cc",
-      "autofill_message_model.cc",
       "offer_notification_controller_android.cc",
     ]
     public_deps += [ "//chrome/browser/touch_to_fill/autofill/android:public" ]
@@ -271,9 +267,6 @@
     sources += [
       "android_bnpl_ui_delegate_unittest.cc",
       "android_payments_window_manager_unittest.cc",
-      "autofill_message_controller_test_api.h",
-      "autofill_message_controller_unittest.cc",
-      "autofill_message_model_unittest.cc",
     ]
     public_deps += [ ":payments" ]
 
@@ -284,7 +277,6 @@
       "//chrome/browser/ui/android/tab_model:test_support",
       "//components/autofill/android:autofill_core_browser_java_enums",
       "//components/autofill/content/browser:test_support",
-      "//components/messages/android:test_support",
       "//components/resources:components_scaled_resources",
       "//components/resources:components_scaled_resources_grit",
       "//ui/android",
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
index 6181ff5..d2b3c3bf 100644
--- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
+++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client.cc
@@ -91,11 +91,11 @@
 #include "chrome/browser/ui/android/autofill/card_expiration_date_fix_flow_view_android.h"
 #include "chrome/browser/ui/android/autofill/card_name_fix_flow_view_android.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller.h"
+#include "chrome/browser/ui/autofill/autofill_message_model.h"
 #include "chrome/browser/ui/autofill/autofill_snackbar_controller_impl.h"
 #include "chrome/browser/ui/autofill/payments/android_bnpl_ui_delegate.h"
 #include "chrome/browser/ui/autofill/payments/android_payments_window_manager.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_model.h"
 #include "chrome/browser/ui/autofill/payments/offer_notification_controller_android.h"
 #include "components/autofill/core/browser/payments/android_bnpl_strategy.h"
 #include "components/autofill/core/browser/payments/autofill_save_iban_ui_info.h"
diff --git a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client_unittest.cc b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client_unittest.cc
index 6a9edeb..db2ed00 100644
--- a/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client_unittest.cc
+++ b/chrome/browser/ui/autofill/payments/chrome_payments_autofill_client_unittest.cc
@@ -35,8 +35,8 @@
 #include "chrome/browser/ui/android/autofill/autofill_save_iban_bottom_sheet_bridge.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_test_helper.h"
+#include "chrome/browser/ui/autofill/autofill_message_controller.h"
 #include "chrome/browser/ui/autofill/autofill_snackbar_controller_impl.h"
-#include "chrome/browser/ui/autofill/payments/autofill_message_controller.h"
 #include "components/autofill/core/browser/data_model/payments/bnpl_issuer.h"
 #include "components/autofill/core/browser/payments/android_bnpl_strategy.h"
 #include "components/autofill/core/browser/payments/autofill_save_card_ui_info.h"
diff --git a/chrome/browser/ui/hats/BUILD.gn b/chrome/browser/ui/hats/BUILD.gn
index f9dd3db0..af8c173 100644
--- a/chrome/browser/ui/hats/BUILD.gn
+++ b/chrome/browser/ui/hats/BUILD.gn
@@ -89,7 +89,6 @@
     "//components/prefs",
     "//components/privacy_sandbox:features",
     "//components/privacy_sandbox:privacy_sandbox_prefs",
-    "//components/privacy_sandbox:tracking_protection_prefs",
     "//components/safe_browsing/core/common:features",
     "//components/safe_browsing/core/common:safe_browsing_prefs",
     "//components/signin/public/base",
@@ -142,7 +141,6 @@
       "//chrome/common:chrome_features",
       "//chrome/test:test_support",
       "//components/content_settings/core/test:test_support",
-      "//components/privacy_sandbox:tracking_protection_prefs",
       "//components/signin/public/base",
       "//components/unified_consent",
       "//content/test:test_support",
diff --git a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
index 881e0f0..eb4e51f0 100644
--- a/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
+++ b/chrome/browser/ui/views/user_education/help_bubble_factory_webui_interactive_uitest.cc
@@ -211,13 +211,10 @@
 };
 
 // TODO(https://crbug.com/463379523): This test is flaky on CI on Mac.
-#if BUILDFLAG(IS_MAC)
-#define MAYBE_ShowFloatingHelpBubble DISABLED_ShowFloatingHelpBubble
-#else
-#define MAYBE_ShowFloatingHelpBubble ShowFloatingHelpBubble
-#endif
+// TODO(https://crbug.com/463867599): This test is flaky/failing on CI on
+// Windows, Linux, and ChromeOS.
 IN_PROC_BROWSER_TEST_F(HelpBubbleFactoryWebUIInteractiveUiTest,
-                       MAYBE_ShowFloatingHelpBubble) {
+                       DISABLED_ShowFloatingHelpBubble) {
   const DeepQuery kPathToAddCurrentTabElement{"reading-list-app",
                                               "#currentPageActionButton"};
   gfx::Rect bubble_rect;
diff --git a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
index 4474a37..548ad637 100644
--- a/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
+++ b/chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.cc
@@ -9,6 +9,7 @@
 #include <string_view>
 
 #include "base/files/file_path.h"
+#include "base/test/gmock_expected_support.h"
 #include "base/test/test_future.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
@@ -266,10 +267,10 @@
 void IsolatedWebAppBrowserTestHarness::SetIwaManagedAllowlist(
     const std::vector<web_package::SignedWebBundleId>& managed_allowlist,
     const base::Version& component_version) {
-  base::ScopedAllowBlockingForTesting allow_blocking;
-  ASSERT_TRUE(test::UpdateKeyDistributionInfoWithAllowlist(
-                  component_version, std::move(managed_allowlist))
-                  .has_value());
+  ASSERT_OK(test::KeyDistributionComponentBuilder(component_version)
+                .WithManagedAllowlist(managed_allowlist)
+                .Build()
+                .UploadFromComponentFolder());
 }
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.cc b/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.cc
index 08ab4b5a..d8206c80 100644
--- a/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.cc
@@ -30,6 +30,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/install/isolated_web_app_install_source.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_integrity_block_data.h"
 #include "chrome/browser/web_applications/isolated_web_apps/jobs/prepare_install_info_job.h"
+#include "chrome/browser/web_applications/isolated_web_apps/remove_isolated_web_app_data.h"
 #include "chrome/browser/web_applications/locks/app_lock.h"
 #include "chrome/browser/web_applications/web_app.h"
 #include "chrome/browser/web_applications/web_app_helpers.h"
@@ -161,6 +162,7 @@
       &InstallIsolatedWebAppCommand::CheckTrustAndSignatures,
       &InstallIsolatedWebAppCommand::CreateStoragePartition,
       &InstallIsolatedWebAppCommand::PrepareInstallInfo,
+      &InstallIsolatedWebAppCommand::ProcessInstallInfoResultAndProceed,
       &InstallIsolatedWebAppCommand::FinalizeInstall);
 }
 
@@ -256,7 +258,8 @@
       std::move(next_step_callback));
 }
 
-void InstallIsolatedWebAppCommand::FinalizeInstall(
+void InstallIsolatedWebAppCommand::ProcessInstallInfoResultAndProceed(
+    base::OnceCallback<void(WebAppInstallInfo)> next_step_callback,
     PrepareInstallInfoJob::InstallInfoOrFailure result) {
   prepare_install_info_job_.reset();
 
@@ -287,9 +290,34 @@
         ReportFailure(iwa_error, web_app_error, failure.message);
       });
 
-  GetMutableDebugValue().Set(
-      "actual_version", install_info.isolated_web_app_version().GetString());
-  GetMutableDebugValue().Set("app_title", install_info.title.AsDebugValue());
+  // As IWAs can have more than one install source at a time, the app might
+  // already be installed.
+  auto iwa_result =
+      GetIsolatedWebAppById(lock_->registrar(), url_info_.app_id());
+
+  // Policy source always takes precedence over the user installed
+  // version, even if it is lower. Such scenario requires user data clearance
+  // before downgrading.
+  if (iwa_result.has_value() &&
+      install_info.isolated_web_app_version() <
+          iwa_result.value().get().isolation_data()->version()) {
+    web_app::RemoveIsolatedWebAppBrowsingData(
+        &profile(), url_info_.origin(),
+        base::BindOnce(std::move(next_step_callback), std::move(install_info)));
+    return;
+  }
+
+  std::move(next_step_callback).Run(std::move(install_info));
+}
+
+void InstallIsolatedWebAppCommand::FinalizeInstall(
+    WebAppInstallInfo install_info) {
+  const IwaVersion to_be_installed_version =
+      install_info.isolated_web_app_version();
+
+  GetMutableDebugValue().Set("actual_version",
+                             to_be_installed_version.GetString());
+  GetMutableDebugValue().Set("app_title", install_info.title.value());
 
   WebAppInstallFinalizer::FinalizeOptions options(install_surface_);
 
@@ -297,10 +325,9 @@
       *destination_storage_location_, std::move(integrity_block_data_));
 
   lock_->install_finalizer().FinalizeInstall(
-      install_info, options,
+      std::move(install_info), options,
       base::BindOnce(&InstallIsolatedWebAppCommand::OnFinalizeInstall,
-                     weak_factory_.GetWeakPtr(),
-                     install_info.isolated_web_app_version()));
+                     weak_factory_.GetWeakPtr(), to_be_installed_version));
 }
 
 void InstallIsolatedWebAppCommand::OnFinalizeInstall(
diff --git a/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h b/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h
index 0190f55..b731dab3 100644
--- a/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h
+++ b/chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h
@@ -171,8 +171,11 @@
       base::OnceCallback<void(PrepareInstallInfoJob::InstallInfoOrFailure)>
           next_step_callback);
 
-  void FinalizeInstall(PrepareInstallInfoJob::InstallInfoOrFailure result);
+  void ProcessInstallInfoResultAndProceed(
+      base::OnceCallback<void(WebAppInstallInfo)> next_step_callback,
+      PrepareInstallInfoJob::InstallInfoOrFailure result);
 
+  void FinalizeInstall(WebAppInstallInfo install_info);
   void OnFinalizeInstall(const IwaVersion& attempted_version,
                          const webapps::AppId& unused_app_id,
                          webapps::InstallResultCode install_result_code);
diff --git a/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc
index 9b4e10b..a3b8039 100644
--- a/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/key_distribution/iwa_key_distribution_info_provider_unittest.cc
@@ -4,6 +4,7 @@
 
 #include "components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h"
 
+#include <optional>
 #include <variant>
 
 #include "base/base64.h"
@@ -27,6 +28,7 @@
 #include "chrome/test/base/testing_browser_process.h"
 #include "components/component_updater/component_updater_paths.h"
 #include "components/component_updater/mock_component_updater_service.h"
+#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_signature_verifier.h"
 #include "components/web_package/test_support/signed_web_bundles/signature_verifier_test_utils.h"
 #include "components/web_package/test_support/signed_web_bundles/web_bundle_signer.h"
@@ -217,14 +219,19 @@
       ht.GetAllSamples(kIwaKeyRotationInfoSource),
       base::BucketsAre(base::Bucket(KeyDistributionComponentSource::kNone, 1)));
 
+  ASSERT_OK_AND_ASSIGN(auto kSignedWebBundleId,
+                       web_package::SignedWebBundleId::Create(kWebBundleId));
+
   auto expected_key = std::visit(
       [](const auto& key_pair) -> base::span<const uint8_t> {
         return key_pair.public_key.bytes();
       },
       key_pairs[0]);
-  EXPECT_THAT(test::UpdateKeyDistributionInfo(base::Version("1.0.0"),
-                                              kWebBundleId, expected_key),
-              HasValue());
+
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.0"))
+                .AddToKeyRotations(kSignedWebBundleId, expected_key)
+                .Build()
+                .UploadFromComponentFolder());
 
   EXPECT_THAT(web_package::test::VerifySignatures(signature_verifier, file,
                                                   parsed_integrity_block),
@@ -237,10 +244,11 @@
           base::Bucket(KeyDistributionComponentSource::kDownloaded, 1)));
 
   auto random_key = web_package::test::Ed25519KeyPair::CreateRandom();
-  EXPECT_THAT(
-      test::UpdateKeyDistributionInfo(base::Version("1.0.1"), kWebBundleId,
-                                      random_key.public_key.bytes()),
-      HasValue());
+  EXPECT_OK(
+      test::KeyDistributionComponentBuilder(base::Version("1.0.1"))
+          .AddToKeyRotations(kSignedWebBundleId, random_key.public_key.bytes())
+          .Build()
+          .UploadFromComponentFolder());
 
   EXPECT_THAT(
       web_package::test::VerifySignatures(signature_verifier, file,
@@ -256,10 +264,10 @@
           base::Bucket(KeyDistributionComponentSource::kNone, 1),
           base::Bucket(KeyDistributionComponentSource::kDownloaded, 2)));
 
-  EXPECT_THAT(
-      test::UpdateKeyDistributionInfo(base::Version("1.0.2"), kWebBundleId,
-                                      /*expected_key=*/std::nullopt),
-      HasValue());
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.2"))
+                .AddToKeyRotations(kSignedWebBundleId, std::nullopt)
+                .Build()
+                .UploadFromComponentFolder());
 
   EXPECT_THAT(
       web_package::test::VerifySignatures(signature_verifier, file,
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc
index 61163a8..c65c036e 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_cache_browsertest.cc
@@ -507,12 +507,10 @@
   void SetIwasAllowlist(
       const std::vector<SignedWebBundleId>& bundle_ids,
       base::Version key_distribution_version = base::Version("1.0.1")) {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-
-    EXPECT_THAT(test::UpdateKeyDistributionInfoWithAllowlist(
-                    key_distribution_version,
-                    /*managed_allowlist=*/bundle_ids),
-                base::test::HasValue());
+    EXPECT_OK(test::KeyDistributionComponentBuilder(key_distribution_version)
+                  .WithManagedAllowlist(bundle_ids)
+                  .Build()
+                  .UploadFromComponentFolder());
   }
 
   void CheckCacheManagerDebugOperationResult(const std::string& operation_name,
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc
index a2f57f9a..23da2eb6 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.cc
@@ -37,6 +37,7 @@
 #include "chrome/browser/web_applications/isolated_web_apps/commands/install_isolated_web_app_command.h"
 #include "chrome/browser/web_applications/isolated_web_apps/install/isolated_web_app_install_source.h"
 #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
+#include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_external_install_options.h"
 #include "chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_installer.h"
 #include "chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.h"
 #include "chrome/browser/web_applications/web_app_command_scheduler.h"
@@ -150,6 +151,11 @@
   return *kCallback;
 }
 
+base::RepeatingClosure& GetPolicyFullyProcessedEventForTesting() {
+  static base::NoDestructor<base::RepeatingClosure> kCallback;
+  return *kCallback;
+}
+
 bool IsOnDemandComponentUpdateFeatureEnabled() {
   return base::FeatureList::IsEnabled(kIwaPolicyManagerOnDemandComponentUpdate);
 }
@@ -187,7 +193,14 @@
     base::RepeatingCallback<void(web_package::SignedWebBundleId,
                                  IwaInstaller::Result)> callback) {
   CHECK_IS_TEST();
-  GetOnInstallTaskCompletedCallbackForTesting() = callback;
+  GetOnInstallTaskCompletedCallbackForTesting() = std::move(callback);
+}
+
+// static
+void IsolatedWebAppPolicyManager::SetOnPolicyFullyProcessedCallbackForTesting(
+    base::RepeatingClosure callback) {
+  CHECK_IS_TEST();
+  GetPolicyFullyProcessedEventForTesting() = std::move(callback);
 }
 
 // static
@@ -339,9 +352,30 @@
 
   std::vector<IsolatedWebAppExternalInstallOptions> apps_in_policy =
       GetIwaInstallForceList(*profile_);
+  debug_info.Set("apps_in_policy",
+                 base::ToValueList(apps_in_policy, [](const auto& options) {
+                   return base::ToString(options.web_bundle_id());
+                 }));
+
+  // Apps in blocklist behave like they are just not in the policy.
+  //  1. Installation is not requested.
+  //  2. The policy install source is removed if previously was there.
+  std::erase_if(
+      apps_in_policy,
+      [](const IsolatedWebAppExternalInstallOptions& install_options) {
+        return IwaKeyDistributionInfoProvider::GetInstance()
+            .IsBundleBlocklisted(install_options.web_bundle_id().id());
+      });
+
   base::flat_map<web_package::SignedWebBundleId,
                  std::reference_wrapper<const WebApp>>
       installed_iwas = GetInstalledIwas(lock.registrar());
+  debug_info.Set(
+      "installed_iwas",
+      base::ToValueList(installed_iwas, [](const auto& installed_iwa) {
+        const auto& [web_bundle_id, _] = installed_iwa;
+        return base::ToString(web_bundle_id);
+      }));
 
   AppActions app_actions;
   size_t number_of_install_tasks = 0;
@@ -424,16 +458,6 @@
     }
   }
 
-  debug_info.Set("apps_in_policy",
-                 base::ToValueList(apps_in_policy, [](const auto& options) {
-                   return base::ToString(options.web_bundle_id());
-                 }));
-  debug_info.Set(
-      "installed_iwas",
-      base::ToValueList(installed_iwas, [](const auto& installed_iwa) {
-        const auto& [web_bundle_id, _] = installed_iwa;
-        return base::ToString(web_bundle_id);
-      }));
   debug_info.Set(
       "app_actions", base::ToValueList(app_actions, [](const auto& entry) {
         const auto& [web_bundle_id, app_action] = entry;
@@ -591,6 +615,11 @@
   if (reprocess_policy_needed_) {
     reprocess_policy_needed_ = false;
     ProcessPolicy();
+    return;
+  }
+  if (auto& policy_fully_processed_callback =
+          GetPolicyFullyProcessedEventForTesting()) {
+    policy_fully_processed_callback.Run();
   }
 }
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h
index 97afc0ee4..1574a39 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager.h
@@ -41,6 +41,9 @@
   static void SetOnInstallTaskCompletedCallbackForTesting(
       base::RepeatingCallback<void(web_package::SignedWebBundleId,
                                    IwaInstaller::Result)> callback);
+  // Fired every time policy is processed and does not need reprocessing.
+  static void SetOnPolicyFullyProcessedCallbackForTesting(
+      base::RepeatingClosure callback);
 
   static std::vector<IsolatedWebAppExternalInstallOptions>
   GetIwaInstallForceList(const Profile& profile);
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_browsertest.cc
index 6f88f80..9097ce23 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_browsertest.cc
@@ -309,10 +309,10 @@
 
   void SetIwaAllowlist(
       const std::vector<web_package::SignedWebBundleId>& managed_allowlist) {
-    base::ScopedAllowBlockingForTesting allow_blocking;
-    EXPECT_THAT(test::UpdateKeyDistributionInfoWithAllowlist(
-                    base::Version("1.0.0"), std::move(managed_allowlist)),
-                base::test::HasValue());
+    EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.0"))
+                  .WithManagedAllowlist(managed_allowlist)
+                  .Build()
+                  .UploadFromComponentFolder());
   }
 
   void SetPolicyWithOneApp() {
@@ -560,8 +560,43 @@
 
   run_loop.Run();
 
-  EXPECT_THAT(provider().registrar_unsafe().GetAppById(kAppId1),
-              testing::IsNull());
+  EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(kAppId1));
+}
+
+IN_PROC_BROWSER_TEST_P(IsolatedWebAppPolicyManagerBrowserTest,
+                       AppInBlocklistNotInstalled) {
+  AddUser();
+  // Add also to allowlist to be sure that installation is blocked by blocklist
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0"))
+                .WithManagedAllowlist({kWebBundleId1, kWebBundleId2})
+                .WithBlocklist({kWebBundleId1})
+                .Build()
+                .UploadFromComponentFolder());
+
+  EXPECT_TRUE(
+      IwaKeyDistributionInfoProvider::GetInstance().IsManagedInstallPermitted(
+          kWebBundleId1.id()));
+  EXPECT_TRUE(IwaKeyDistributionInfoProvider::GetInstance().IsBundleBlocklisted(
+      kWebBundleId1.id()));
+
+  base::RunLoop run_loop;
+  IsolatedWebAppPolicyManager::SetOnPolicyFullyProcessedCallbackForTesting(
+      base::BindLambdaForTesting([&]() {
+        // The second app was installed just to catch the final policy processed
+        // callback, both apps are processed together.
+        EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(kAppId1));
+        if (provider().registrar_unsafe().IsInRegistrar(kAppId2) == true) {
+          run_loop.Quit();
+        }
+      }));
+
+  WaitForUserAdded();
+
+  ASSERT_NO_FATAL_FAILURE(StartLogin({}));
+  WaitForSessionStart();
+  SetPolicyWithTwoApps();
+
+  run_loop.Run();
 }
 
 IN_PROC_BROWSER_TEST_P(IsolatedWebAppPolicyManagerBrowserTest, PolicyUpdate) {
@@ -726,6 +761,54 @@
   }
 }
 
+IN_PROC_BROWSER_TEST_P(IsolatedWebAppPolicyManagerBrowserTest,
+                       AppsRemovedAfterBeingBlocklisted) {
+  AddUser();
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0"))
+                .WithManagedAllowlist({kWebBundleId1, kWebBundleId2})
+                .Build()
+                .UploadFromComponentFolder());
+  WaitForUserAdded();
+
+  // Log in to the managed guest session. There is no IWA policy set at the
+  // moment of login.
+  ASSERT_NO_FATAL_FAILURE(StartLogin());
+  WaitForSessionStart();
+
+  // Set the policy with 2 IWAs and wait for the IWAs to be installed.
+  {
+    WebAppTestInstallObserver install_observer(GetProfileForTest());
+    install_observer.BeginListening({kAppId1, kAppId2});
+
+    SetPolicyWithTwoApps();
+    CreateInitialDiscoveryUpdateWaiters({kAppId1, kAppId2});
+    install_observer.Wait();
+
+    EXPECT_EQ(provider().registrar_unsafe().GetInstallState(kAppId1),
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
+    EXPECT_EQ(provider().registrar_unsafe().GetInstallState(kAppId2),
+              proto::InstallState::INSTALLED_WITH_OS_INTEGRATION);
+  }
+
+  // Add apps to the blocklist and check if they are uninstalled
+  {
+    WebAppTestUninstallObserver uninstall_observer(GetProfileForTest());
+    uninstall_observer.BeginListening({kAppId1, kAppId2});
+
+    // Verify uninstallation takes place regardless of app allowlisting
+    EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.1"))
+                  .WithManagedAllowlist({kWebBundleId1})
+                  .WithBlocklist({kWebBundleId1, kWebBundleId2})
+                  .Build()
+                  .UploadFromComponentFolder());
+
+    EXPECT_THAT(uninstall_observer.Wait(), testing::AnyOf(kAppId1, kAppId2));
+
+    EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(kAppId1));
+    EXPECT_FALSE(provider().registrar_unsafe().IsInRegistrar(kAppId2));
+  }
+}
+
 INSTANTIATE_TEST_SUITE_P(
     /***/,
     IsolatedWebAppPolicyManagerBrowserTest,
diff --git a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc
index 0f77579..18effc6 100644
--- a/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/policy/isolated_web_app_policy_manager_unittest.cc
@@ -529,10 +529,10 @@
       future.GetRepeatingCallback());
 
   // Update allowlist
-  EXPECT_THAT(test::UpdateKeyDistributionInfoWithAllowlist(
-                  base::Version("1.0.1"),
-                  /*managed_allowlist=*/{web_bundle_id_1()}),
-              HasValue());
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.1"))
+                .AddToManagedAllowlist(web_bundle_id_1())
+                .Build()
+                .UploadFromComponentFolder());
 
   EXPECT_TRUE(
       IwaKeyDistributionInfoProvider::GetInstance().IsManagedInstallPermitted(
@@ -571,10 +571,10 @@
       future.GetRepeatingCallback());
 
   // Ensure allowlist is empty
-  EXPECT_THAT(
-      test::UpdateKeyDistributionInfoWithAllowlist(base::Version("1.0.1"),
-                                                   /*managed_allowlist=*/{}),
-      HasValue());
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.1"))
+                .WithManagedAllowlist({})  // For clarity only
+                .Build()
+                .UploadFromComponentFolder());
 
   EXPECT_FALSE(
       IwaKeyDistributionInfoProvider::GetInstance().IsManagedInstallPermitted(
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.cc b/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.cc
index ec21257..fcc1f76 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.cc
@@ -61,11 +61,25 @@
   return base_url.Resolve(GetRelativeUpdateManifestUrl(web_bundle_id));
 }
 
+// static
+GURL BundleVersionsStorage::GetBundleUrl(
+    const GURL& base_url,
+    const web_package::SignedWebBundleId& web_bundle_id,
+    const IwaVersion& version) {
+  return base_url.Resolve(GetRelativeWebBundleUrl(web_bundle_id, version));
+}
+
 GURL BundleVersionsStorage::GetUpdateManifestUrl(
     const web_package::SignedWebBundleId& web_bundle_id) const {
   return GetUpdateManifestUrl(*base_url_, web_bundle_id);
 }
 
+GURL BundleVersionsStorage::GetBundleUrl(
+    const web_package::SignedWebBundleId& web_bundle_id,
+    const IwaVersion& version) const {
+  return GetBundleUrl(*base_url_, web_bundle_id, version);
+}
+
 base::Value::Dict BundleVersionsStorage::GetUpdateManifest(
     const web_package::SignedWebBundleId& web_bundle_id) const {
   const auto& bundle_versions =
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.h b/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.h
index 26cd34ce..ce48691 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.h
+++ b/chrome/browser/web_applications/isolated_web_apps/test/bundle_versions_storage.h
@@ -31,6 +31,10 @@
       const GURL& base_url,
       const web_package::SignedWebBundleId& web_bundle_id);
 
+  static GURL GetBundleUrl(const GURL& base_url,
+                           const web_package::SignedWebBundleId& web_bundle_id,
+                           const IwaVersion& version);
+
   // Must be called once at startup.
   void SetBaseUrl(const GURL& base_url);
 
@@ -51,8 +55,12 @@
   GURL GetUpdateManifestUrl(
       const web_package::SignedWebBundleId& web_bundle_id) const;
 
-  // Returns the update manifest for `web_bundle_id`. Will CHECK if there are no
-  // bundles served for this `web_bundle_id`.
+  // Returns the full URL to the bundle for `web_bundle_id` and `version`.
+  GURL GetBundleUrl(const web_package::SignedWebBundleId& web_bundle_id,
+                    const IwaVersion& version) const;
+
+  // Returns the update manifest for `web_bundle_id`. Will CHECK if there
+  // are no bundles served for this `web_bundle_id`.
   base::Value::Dict GetUpdateManifest(
       const web_package::SignedWebBundleId& web_bundle_id) const;
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.cc b/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.cc
index df5dfa3..859ea67 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.cc
@@ -59,6 +59,18 @@
                         std::move(head), json_content, status);
 }
 
+void IwaTestServerConfigurator::SetServedUpdateManifestResponse(
+    const GURL& update_manifest_url,
+    net::HttpStatusCode http_status,
+    std::string_view json_content) {
+  network::mojom::URLResponseHeadPtr head =
+      network::CreateURLResponseHead(http_status);
+  head->mime_type = "application/json";
+  network::URLLoaderCompletionStatus status;
+  factory_->AddResponse(update_manifest_url, std::move(head),
+                        std::string(json_content), status);
+}
+
 // static
 base::Value::Dict IwaTestServerConfigurator::CreateForceInstallPolicyEntry(
     const web_package::SignedWebBundleId& web_bundle_id,
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.h b/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.h
index fbef5c3..6a0bc33 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.h
+++ b/chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.h
@@ -36,6 +36,12 @@
       net::HttpStatusCode http_status,
       std::string_view json_content);
 
+  // Sets the response for a specific update manifest. Used when testing updates
+  // behavior with non-default update manifests.
+  void SetServedUpdateManifestResponse(const GURL& update_manifest_url,
+                                       net::HttpStatusCode http_status,
+                                       std::string_view json_content);
+
   // Generates a policy entry that can be appended to
   // `prefs::kIsolatedWebAppInstallForceList` in order to force-install the IWA.
   // Delegates to `test::CreateForceInstallIwaPolicyEntry()` with a custom
@@ -51,6 +57,11 @@
     return storage_.GetUpdateManifestUrl(web_bundle_id);
   }
 
+  GURL GetBundleUrlForIwa(const web_package::SignedWebBundleId& web_bundle_id,
+                          const IwaVersion& version) {
+    return storage_.GetBundleUrl(web_bundle_id, version);
+  }
+
  private:
   test::BundleVersionsStorage storage_;
 
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.cc b/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.cc
index 0f6fb7ad..e081e02 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.cc
@@ -102,7 +102,7 @@
 KeyDistributionComponentBuilder&
 KeyDistributionComponentBuilder::AddToKeyRotations(
     const web_package::SignedWebBundleId& web_bundle_id,
-    std::optional<std::vector<uint8_t>> expected_key) & {
+    std::optional<base::span<const uint8_t>> expected_key) & {
   IwaKeyRotations::KeyRotationInfo kr_info_proto;
   if (expected_key.has_value()) {
     kr_info_proto.set_expected_key(base::Base64Encode(*expected_key));
@@ -116,7 +116,7 @@
 KeyDistributionComponentBuilder&&
 KeyDistributionComponentBuilder::AddToKeyRotations(
     const web_package::SignedWebBundleId& web_bundle_id,
-    std::optional<std::vector<uint8_t>> expected_key) && {
+    std::optional<base::span<const uint8_t>> expected_key) && {
   return std::move(AddToKeyRotations(web_bundle_id, std::move(expected_key)));
 }
 
@@ -145,33 +145,31 @@
 
 KeyDistributionComponentBuilder& KeyDistributionComponentBuilder::WithBlocklist(
     const std::vector<web_package::SignedWebBundleId>& bundle_ids) & {
-  // TODO(crbug.com/432446316): Implement the blocklist
-  NOTIMPLEMENTED();
+  for (const auto& bundle_id : bundle_ids) {
+    (*component_.component_data.mutable_iwa_access_control()
+          ->mutable_blocklist())[bundle_id.id()] = {};
+  }
   return *this;
 }
 
 KeyDistributionComponentBuilder&&
 KeyDistributionComponentBuilder::WithBlocklist(
     const std::vector<web_package::SignedWebBundleId>& bundle_ids) && {
-  // TODO(crbug.com/432446316): Implement the blocklist
-  NOTIMPLEMENTED();
-  return std::move(*this);
+  return std::move(WithBlocklist(bundle_ids));
 }
 
 KeyDistributionComponentBuilder&
 KeyDistributionComponentBuilder::AddToBlocklist(
     const web_package::SignedWebBundleId& bundle_id) & {
-  // TODO(crbug.com/432446316): Implement the blocklist
-  NOTIMPLEMENTED();
+  (*component_.component_data.mutable_iwa_access_control()
+        ->mutable_blocklist())[bundle_id.id()] = {};
   return *this;
 }
 
 KeyDistributionComponentBuilder&&
 KeyDistributionComponentBuilder::AddToBlocklist(
     const web_package::SignedWebBundleId& bundle_id) && {
-  // TODO(crbug.com/432446316): Implement the blocklist
-  NOTIMPLEMENTED();
-  return std::move(*this);
+  return std::move(AddToBlocklist(bundle_id));
 }
 
 KeyDistributionComponentBuilder&
@@ -230,36 +228,6 @@
   return UpdateKeyDistributionInfo(version, path);
 }
 
-base::expected<void, IwaComponentUpdateError> UpdateKeyDistributionInfo(
-    const base::Version& version,
-    const std::string& web_bundle_id,
-    std::optional<base::span<const uint8_t>> expected_key) {
-  IwaKeyDistribution key_distribution;
-  IwaKeyRotations key_rotations;
-  IwaKeyRotations::KeyRotationInfo kr_info;
-  if (expected_key) {
-    kr_info.set_expected_key(base::Base64Encode(*expected_key));
-  }
-  key_rotations.mutable_key_rotations()->emplace(web_bundle_id,
-                                                 std::move(kr_info));
-  *key_distribution.mutable_key_rotation_data() = std::move(key_rotations);
-  return UpdateKeyDistributionInfo(version, key_distribution);
-}
-
-base::expected<void, IwaComponentUpdateError>
-UpdateKeyDistributionInfoWithAllowlist(
-    const base::Version& version,
-    const std::vector<web_package::SignedWebBundleId>& managed_allowlist) {
-  IwaKeyDistribution key_distribution;
-  for (const auto& bundle_id : managed_allowlist) {
-    auto& managed_allowlist_proto =
-        *key_distribution.mutable_iwa_access_control()
-             ->mutable_managed_allowlist();
-    managed_allowlist_proto[bundle_id.id()] = {};
-  }
-  return UpdateKeyDistributionInfo(version, key_distribution);
-}
-
 base::expected<void, IwaComponentUpdateError>
 InstallIwaKeyDistributionComponent(const base::Version& version,
                                    const IwaKeyDistribution& kd_proto) {
diff --git a/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.h b/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.h
index 36cd01b..226a0d7 100644
--- a/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.h
+++ b/chrome/browser/web_applications/isolated_web_apps/test/key_distribution/test_utils.h
@@ -62,10 +62,10 @@
   // used many times when several key rotations are required.
   KeyDistributionComponentBuilder& AddToKeyRotations(
       const web_package::SignedWebBundleId& web_bundle_id,
-      std::optional<std::vector<uint8_t>> expected_key) &;
+      std::optional<base::span<const uint8_t>> expected_key) &;
   KeyDistributionComponentBuilder&& AddToKeyRotations(
       const web_package::SignedWebBundleId& web_bundle_id,
-      std::optional<std::vector<uint8_t>> expected_key) &&;
+      std::optional<base::span<const uint8_t>> expected_key) &&;
 
   // Sets the special permissions for a specific app
   KeyDistributionComponentBuilder& AddToSpecialAppPermissions(
@@ -114,25 +114,6 @@
     const base::Version& version,
     const IwaKeyDistribution& kd_proto);
 
-// Synchronously updates the key distribution info provider with a protobuf that
-// maps `web_bundle_id` to `expected_key`. If `expected_key` is a nullopt, then
-// the IWA with `web_bundle_id` will fail signature verification.
-// TODO(crbug.com/460419755): Remove and replace with
-// KeyDistributionComponentBuilder.Build().UploadFromComponentFolder()
-base::expected<void, IwaComponentUpdateError> UpdateKeyDistributionInfo(
-    const base::Version& version,
-    const std::string& web_bundle_id,
-    std::optional<base::span<const uint8_t>> expected_key);
-
-// Synchronously updates the key distribution info provider with a protobuf that
-// only contains bundle ids in the managed allowlist
-// TODO(crbug.com/460419755): Remove and replace with
-// KeyDistributionComponentBuilder.Build().UploadFromComponentFolder()
-base::expected<void, IwaComponentUpdateError>
-UpdateKeyDistributionInfoWithAllowlist(
-    const base::Version& version,
-    const std::vector<web_package::SignedWebBundleId>& managed_allowlist);
-
 // Writes `kd_proto` into `DIR_COMPONENT_USER/IwaKeyDistribution/{version}` and
 // triggers the registration process with the component updater. The directory
 // is deleted once IwaKeyDistributionInfoProvider has processed the update
diff --git a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.cc b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.cc
index 73f296b..c8a225c 100644
--- a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.cc
@@ -68,6 +68,12 @@
 
 namespace web_app {
 
+IsolatedWebAppUpdateOptions::IsolatedWebAppUpdateOptions() = default;
+
+IsolatedWebAppUpdateOptions::IsolatedWebAppUpdateOptions(
+    const GURL& update_manifest_url)
+    : update_manifest_url(update_manifest_url) {}
+
 IsolatedWebAppUpdateOptions::IsolatedWebAppUpdateOptions(
     const GURL& update_manifest_url,
     UpdateChannel update_channel,
@@ -181,17 +187,44 @@
   std::optional<ash::KioskIwaUpdateData> kiosk_iwa_policy_data =
       ash::GetCurrentKioskIwaUpdateData();
   if (kiosk_iwa_policy_data) {
-    result.emplace(
-        kiosk_iwa_policy_data->web_bundle_id,
+    result[kiosk_iwa_policy_data->web_bundle_id] =
         IsolatedWebAppUpdateOptions(kiosk_iwa_policy_data->update_manifest_url,
                                     kiosk_iwa_policy_data->update_channel,
                                     kiosk_iwa_policy_data->allow_downgrades,
-                                    kiosk_iwa_policy_data->pinned_version));
+                                    kiosk_iwa_policy_data->pinned_version);
   }
   return result;
 }
 #endif
 
+IwaBundleIdToUpdateOptionsMap GetIsolatedWebAppsWithOnlyUserManagement(
+    Profile* profile) {
+  IwaBundleIdToUpdateOptionsMap result;
+  for (const WebApp& web_app : web_app::WebAppProvider::GetForWebApps(profile)
+                                   ->registrar_unsafe()
+                                   .GetApps()) {
+    if (!web_app.isolation_data() ||
+        web_app.GetSources().HasAny({web_app::WebAppManagement::kKiosk,
+                                     web_app::WebAppManagement::kIwaShimlessRma,
+                                     web_app::WebAppManagement::kIwaPolicy})) {
+      continue;
+    }
+
+    auto url_info = IsolatedWebAppUrlInfo::Create(web_app.start_url());
+    if (!url_info.has_value()) {
+      continue;
+    }
+
+    if (!web_app.isolation_data()->update_manifest_url()) {
+      continue;
+    }
+
+    result[url_info->web_bundle_id()] = IsolatedWebAppUpdateOptions(
+        web_app.isolation_data().value().update_manifest_url().value());
+  }
+  return result;
+}
+
 IwaBundleIdToUpdateOptionsMap GetBundleIdToIsolatedWebAppsUpdateOptionsMap(
     Profile* profile) {
 #if BUILDFLAG(IS_CHROMEOS)
@@ -201,7 +234,15 @@
     return GetKioskPolicyIsolatedWebApps();
   }
 #endif
-  return GetForceInstalledPolicyIsolatedWebApps(profile);
+  IwaBundleIdToUpdateOptionsMap result =
+      GetIsolatedWebAppsWithOnlyUserManagement(profile);
+
+  // Data coming from IWA policy source takes precedence.
+  for (auto& [id, options] : GetForceInstalledPolicyIsolatedWebApps(profile)) {
+    result.insert_or_assign(id, std::move(options));
+  }
+
+  return result;
 }
 
 bool ShouldProceedWithVersionChange(
@@ -551,7 +592,6 @@
       ++num_new_tasks;
     }
   }
-
   task_queue_.MaybeStartNextTask();
 
   MaybeScheduleUpdateDiscoveryCheck();
@@ -563,12 +603,6 @@
     const base::flat_map<web_package::SignedWebBundleId,
                          IsolatedWebAppUpdateOptions>&
         id_to_update_options_map) {
-  // TODO(crbug.com/40274186): In the future, we also need to automatically
-  // update IWAs not installed via policy.
-  if (!web_app.IsIwaPolicyInstalledApp() && !web_app.IsKioskInstalledApp()) {
-    return false;
-  }
-
   const std::optional<IsolationData>& isolation_data = web_app.isolation_data();
   if (!isolation_data) {
     return false;
diff --git a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.h b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.h
index 8440ef4..0f218bf 100644
--- a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.h
+++ b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager.h
@@ -80,6 +80,8 @@
 };
 
 struct IsolatedWebAppUpdateOptions {
+  IsolatedWebAppUpdateOptions();
+  explicit IsolatedWebAppUpdateOptions(const GURL& update_manifest_url);
   IsolatedWebAppUpdateOptions(const GURL& update_manifest_url,
                               UpdateChannel update_channel,
                               bool allow_downgrades,
@@ -90,17 +92,13 @@
   ~IsolatedWebAppUpdateOptions();
 
   GURL update_manifest_url;
-  UpdateChannel update_channel;
-  bool allow_downgrades;
+  UpdateChannel update_channel = UpdateChannel::default_channel();
+  bool allow_downgrades = false;
   std::optional<IwaVersion> pinned_version;
 };
 
 // The `IsolatedWebAppUpdateManager` is responsible for discovery, download, and
-// installation of Isolated Web App updates. Currently, it is only updating
-// policy-installed IWAs on ChromeOS.
-//
-// TODO(crbug.com/40274186): Implement updates for unmanaged IWAs once we have
-// designed that process.
+// installation of Isolated Web App updates.
 class IsolatedWebAppUpdateManager
     : public WebAppInstallManagerObserver,
       public IwaKeyDistributionInfoProvider::Observer {
@@ -162,9 +160,9 @@
       const webapps::AppId& app_id,
       webapps::WebappUninstallSource uninstall_source) override;
 
-  // Queues an update discovery task for the provided `app_id`, assuming that
-  // the corresponding app is policy-installed (prod mode). Returns a boolean
-  // indicating whether an update discovery task was queued successfully.
+  // Queues an update discovery task for the provided `app_id`. Returns a
+  // boolean indicating whether an update discovery task was queued
+  // successfully.
   bool MaybeDiscoverUpdatesForApp(const webapps::AppId& app_id);
 
   // Queues an update discovery task (and potentially an apply update task
diff --git a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_browsertest.cc b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_browsertest.cc
index 901224c..7c7b874 100644
--- a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_browsertest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_browsertest.cc
@@ -202,17 +202,42 @@
             .BuildBundle(GetWebBundleId(), {kKeyPair1}),
         update_channels);
   }
+
+  GURL GetBundleUpdateManifestUrl(
+      const web_package::SignedWebBundleId& web_bundle_id) {
+    return iwa_test_update_server_.GetUpdateManifestUrl(web_bundle_id);
+  }
+
+  std::unique_ptr<ScopedBundledIsolatedWebApp> CreateBundle(
+      const web_package::SignedWebBundleId& web_bundle_id,
+      std::string_view version,
+      std::optional<std::string_view> update_manifest_url = std::nullopt) {
+    auto manifest = ManifestBuilder().SetVersion(version);
+    if (update_manifest_url) {
+      manifest.SetUpdateManifestUrl(GURL(*update_manifest_url));
+    }
+
+    std::unique_ptr<ScopedBundledIsolatedWebApp> app =
+        IsolatedWebAppBuilder(manifest).BuildBundle(
+            web_bundle_id, {test::GetDefaultEd25519KeyPair()});
+    app->TrustSigningKey();
+    return app;
+  }
+
   url::Origin GetAppOrigin() const {
     return IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(GetWebBundleId())
         .origin();
   }
+
   webapps::AppId GetAppId() const {
     return IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(GetWebBundleId())
         .app_id();
   }
+
   web_package::SignedWebBundleId GetWebBundleId() const {
     return kWebBundleId1;
   }
+
   const WebApp* GetIsolatedWebApp(const webapps::AppId& app_id) {
     return provider().registrar_unsafe().GetAppById(app_id);
   }
@@ -1188,6 +1213,42 @@
 }
 
 IN_PROC_BROWSER_TEST_F(IsolatedWebAppUpdateManagerBrowserTest,
+                       SuccessfulUnmanagedUpdate) {
+  webapps::AppId app_id =
+      IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(kWebBundleId1)
+          .app_id();
+  auto update_manifest_url = GetBundleUpdateManifestUrl(kWebBundleId1);
+
+  // Install initial version.
+  CreateBundle(kWebBundleId1, "1.0.0", update_manifest_url.spec())
+      ->InstallChecked(profile());
+  EXPECT_EQ(provider()
+                .registrar_unsafe()
+                .GetAppById(app_id)
+                ->isolation_data()
+                ->version(),
+            *IwaVersion::Create("1.0.0"));
+
+  // Add newer version to the server.
+  iwa_test_update_server_.AddBundle(
+      CreateBundle(kWebBundleId1, "4.0.0", update_manifest_url.spec()));
+
+  WebAppTestManifestUpdatedObserver manifest_updated_observer(
+      &provider().install_manager());
+  manifest_updated_observer.BeginListening({app_id});
+  EXPECT_THAT(provider().iwa_update_manager().DiscoverUpdatesNow(), Eq(1ul));
+  manifest_updated_observer.Wait();
+
+  // Verify the app is updated.
+  EXPECT_EQ(provider()
+                .registrar_unsafe()
+                .GetAppById(app_id)
+                ->isolation_data()
+                ->version(),
+            *IwaVersion::Create("4.0.0"));
+}
+
+IN_PROC_BROWSER_TEST_F(IsolatedWebAppUpdateManagerBrowserTest,
                        PendingUpdateDoesNotGetCleanedUp) {
   profile()->GetPrefs()->SetList(
       prefs::kIsolatedWebAppInstallForceList,
diff --git a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_unittest.cc b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_unittest.cc
index 1df2e2d..0a069ee 100644
--- a/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_unittest.cc
+++ b/chrome/browser/web_applications/isolated_web_apps/update/isolated_web_app_update_manager_unittest.cc
@@ -230,11 +230,16 @@
   }
 
   std::unique_ptr<ScopedBundledIsolatedWebApp> CreateIwa1Bundle(
-      std::string_view version) {
+      std::string_view version,
+      std::optional<std::string_view> update_manifest_url = std::nullopt) {
+    auto manifest = ManifestBuilder().SetVersion(version);
+    if (update_manifest_url) {
+      manifest.SetUpdateManifestUrl(GURL(*update_manifest_url));
+    }
+
     std::unique_ptr<ScopedBundledIsolatedWebApp> app =
-        IsolatedWebAppBuilder(ManifestBuilder().SetVersion(version))
-            .BuildBundle(GetIwa1WebBundleId(),
-                         {test::GetDefaultEd25519KeyPair()});
+        IsolatedWebAppBuilder(manifest).BuildBundle(
+            GetIwa1WebBundleId(), {test::GetDefaultEd25519KeyPair()});
     app->TrustSigningKey();
     app->FakeInstallPageState(profile());
     return app;
@@ -274,6 +279,15 @@
                             kUpdateFoundAndSavedInDatabase));
   }
 
+  void AssertAppDiscoveryTaskFailedWith(
+      const web_package::SignedWebBundleId& web_bundle_id,
+      IsolatedWebAppUpdateDiscoveryTask::Error error) {
+    UpdateDiscoveryTaskFuture future;
+    UpdateDiscoveryTaskResultWaiter waiter(provider(), GetAppId(web_bundle_id),
+                                           future.GetCallback());
+    EXPECT_THAT(future.Take(), ErrorIs(error));
+  }
+
   void AssertInstallationFinish(
       const web_package::SignedWebBundleId& web_bundle_id) {
     WebAppTestManifestUpdatedObserver manifest_updated_observer(
@@ -292,6 +306,18 @@
               version);
   }
 
+  void AssertAppIsolationDataUpdateManifestUrlIs(
+      const web_package::SignedWebBundleId& web_bundle_id,
+      const GURL& expected_update_manifest_url) {
+    ASSERT_EQ(provider()
+                  .registrar_unsafe()
+                  .GetAppById(GetAppId(web_bundle_id))
+                  ->isolation_data()
+                  ->update_manifest_url()
+                  .value(),
+              expected_update_manifest_url);
+  }
+
   void AssertAppNotInstalled(
       const web_package::SignedWebBundleId& web_bundle_id) {
     ASSERT_FALSE(
@@ -738,11 +764,12 @@
       capture_discovery_task_result([&] {
         // Rotate the signing key from ed25519 to ecdsaP256. This will
         // trigger an unsuccessful update.
-        ASSERT_THAT(
-            test::UpdateKeyDistributionInfo(
-                base::Version(kInitialIwaVersion), GetIwa1WebBundleId().id(),
-                test::GetDefaultEcdsaP256KeyPair().public_key.bytes()),
-            base::test::HasValue());
+        ASSERT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.1"))
+                      .AddToKeyRotations(
+                          GetIwa1WebBundleId(),
+                          test::GetDefaultEcdsaP256KeyPair().public_key.bytes())
+                      .Build()
+                      .UploadFromComponentFolder());
       }),
       ErrorIs(_));
 
@@ -797,10 +824,13 @@
     WebAppTestManifestUpdatedObserver manifest_updated_observer(
         &provider().install_manager());
     manifest_updated_observer.BeginListening({app_id});
-    ASSERT_THAT(test::UpdateKeyDistributionInfo(
-                    base::Version(base::StringPrintf("%d.0.0", comp_v)),
-                    web_bundle_id.id(), key_pair.public_key.bytes()),
-                base::test::HasValue());
+
+    ASSERT_OK(test::KeyDistributionComponentBuilder(
+                  base::Version(base::StringPrintf("%d.0.0", comp_v)))
+                  .AddToKeyRotations(web_bundle_id, key_pair.public_key.bytes())
+                  .Build()
+                  .UploadFromComponentFolder());
+
     manifest_updated_observer.Wait();
 
     ASSERT_THAT(provider().registrar_unsafe().GetAppById(app_id),
@@ -839,6 +869,157 @@
                               *IwaVersion::Create(kUpdateIwaVersion));
 }
 
+TEST_F(IsolatedWebAppUpdateManagerUpdateMockTimeTest,
+       SuccessfulUnmanagedUpdate) {
+  auto update_manifest_url =
+      test_update_server().GetUpdateManifestUrlForIwa(GetIwa1WebBundleId());
+  CreateIwa1Bundle(kInitialIwaVersion, update_manifest_url.spec())
+      ->InstallChecked(profile());
+
+  test_update_server().AddBundle(
+      CreateIwa1Bundle(kUpdateIwaVersion, update_manifest_url.spec()));
+
+  AssertAppDiscoveryTaskSuccessful(GetIwa1WebBundleId());
+  AssertInstallationFinish(GetIwa1WebBundleId());
+  AssertAppInstalledAtVersion(GetIwa1WebBundleId(),
+                              *IwaVersion::Create(kUpdateIwaVersion));
+  EXPECT_THAT(
+      UpdateDiscoveryLog(),
+      UnorderedElementsAre(DictionaryHasValue(
+          "result", base::Value("Success::kUpdateFoundAndDryRunSuccessful"))));
+  EXPECT_THAT(UpdateApplyLog(), UnorderedElementsAre(DictionaryHasValue(
+                                    "result", base::Value("Success"))));
+}
+
+TEST_F(IsolatedWebAppUpdateManagerUpdateMockTimeTest,
+       ManagedUpdateTakesPrecedenceDespiteNewerVersionAvailableOnUnmanaged) {
+  // Force-install versions are deliberately set to lower ones than their
+  // unmanaged counterparts.
+  const std::string kManagedInitialVersion = "0.4.0";
+  const std::string kUnmanagedInitialVersion = "1.0.0";
+  const std::string kUnmanagedUpdateVersion = "3.0.0";
+  const std::string kManagedUpdateVersion = "2.4.0";
+
+  GURL managed_update_url =
+      test_update_server().GetUpdateManifestUrlForIwa(GetIwa1WebBundleId());
+  GURL unmanaged_update_url = GURL(managed_update_url.spec() + "-unmanaged");
+
+  CreateIwa1Bundle(kUnmanagedInitialVersion, unmanaged_update_url.spec())
+      ->InstallChecked(profile());
+
+  AssertAppInstalledAtVersion(GetIwa1WebBundleId(),
+                              *IwaVersion::Create(kUnmanagedInitialVersion));
+  AssertAppIsolationDataUpdateManifestUrlIs(GetIwa1WebBundleId(),
+                                            unmanaged_update_url);
+
+  // Make sure that app is force-installed with a correct version. Keep user
+  // installed source despite version change.
+  {
+    WebAppTestInstallObserver install_observer(profile());
+    install_observer.BeginListening({GetAppId(GetIwa1WebBundleId())});
+
+    test::AddForceInstalledIwaToPolicy(
+        profile()->GetPrefs(),
+        test_update_server().CreateForceInstallPolicyEntry(
+            GetIwa1WebBundleId()));
+    test_update_server().AddBundle(
+        CreateIwa1Bundle(kManagedInitialVersion, managed_update_url.spec()));
+
+    EXPECT_EQ(install_observer.Wait(), GetAppId(GetIwa1WebBundleId()));
+    AssertAppInstalledAtVersion(GetIwa1WebBundleId(),
+                                *IwaVersion::Create(kManagedInitialVersion));
+
+    EXPECT_THAT(
+        provider()
+            .registrar_unsafe()
+            .GetAppById(GetAppId(GetIwa1WebBundleId()))
+            ->GetSources(),
+        Eq(WebAppManagementTypes({WebAppManagement::Type::kIwaPolicy,
+                                  WebAppManagement::Type::kIwaUserInstalled})));
+  }
+
+  std::string unmanaged_manifest_json = absl::StrFormat(
+      R"json({
+        "versions": [
+          { "version": "%s", "src": "%s" }
+        ]
+      })json",
+      kUnmanagedUpdateVersion,
+      test_update_server()
+          .GetBundleUrlForIwa(
+              GetIwa1WebBundleId(),
+              IwaVersion::Create(kUnmanagedUpdateVersion).value())
+          .spec());
+
+  // Make manifest from policy empty to see that the update discovery fails
+  // despite having potential versions to install from unmanaged manifest.
+  std::string managed_manifest_json = absl::StrFormat(
+      R"json({
+        "versions": [
+        ]
+      })json");
+
+  // Server setup to control returned manifests.
+  test_update_server().SetServedUpdateManifestResponse(
+      managed_update_url, net::HTTP_OK, managed_manifest_json);
+  test_update_server().SetServedUpdateManifestResponse(
+      unmanaged_update_url, net::HTTP_OK, unmanaged_manifest_json);
+
+  update_manager().DiscoverUpdatesNow();
+
+  // Managed update manifest was empty, no update should have been picked up.
+  AssertAppDiscoveryTaskFailedWith(GetIwa1WebBundleId(),
+                                   IsolatedWebAppUpdateDiscoveryTask::Error::
+                                       kUpdateManifestNoApplicableVersion);
+
+  test_update_server().AddBundle(
+      CreateIwa1Bundle(kManagedUpdateVersion, managed_update_url.spec()));
+
+  // Add newer, managed bundle to the managed manifest.
+  {
+    auto new_managed_manifest_json = absl::StrFormat(
+        R"json({
+        "versions": [
+          { "version": "%s", "src": "%s" }
+        ]
+      })json",
+        kManagedUpdateVersion,
+        test_update_server()
+            .GetBundleUrlForIwa(
+                GetIwa1WebBundleId(),
+                IwaVersion::Create(kManagedUpdateVersion).value())
+            .spec());
+
+    test_update_server().SetServedUpdateManifestResponse(
+        managed_update_url, net::HTTP_OK, new_managed_manifest_json);
+
+    AssertAppDiscoveryTaskSuccessful(GetIwa1WebBundleId());
+    AssertInstallationFinish(GetIwa1WebBundleId());
+
+    AssertAppInstalledAtVersion(GetIwa1WebBundleId(),
+                                *IwaVersion::Create(kManagedUpdateVersion));
+  }
+}
+
+TEST_F(IsolatedWebAppUpdateManagerUpdateMockTimeTest,
+       UnmanagedUpdateFailsIfManifestIsNotFound) {
+  auto update_manifest_url =
+      test_update_server().GetUpdateManifestUrlForIwa(GetIwa1WebBundleId());
+  CreateIwa1Bundle(kInitialIwaVersion, update_manifest_url.spec())
+      ->InstallChecked(profile());
+
+  test_update_server().SetServedUpdateManifestResponse(update_manifest_url,
+                                                       net::HTTP_NOT_FOUND, "");
+
+  update_manager().DiscoverUpdatesNow();
+
+  AssertAppDiscoveryTaskFailedWith(
+      GetIwa1WebBundleId(),
+      IsolatedWebAppUpdateDiscoveryTask::Error::kUpdateManifestDownloadFailed);
+  AssertAppInstalledAtVersion(GetIwa1WebBundleId(),
+                              *IwaVersion::Create(kInitialIwaVersion));
+}
+
 TEST_F(IsolatedWebAppUpdateManagerUpdateTest,
        AppliesUpdatesWithHigherPriorityThanUpdateDiscovery) {
   InitialIwaBundleForceInstall(CreateIwa1Bundle(kInitialIwaVersion));
@@ -906,20 +1087,20 @@
       .SkipManagedAllowlistChecksForTesting(false);
 
   // Add both app to allowlist for installing them
-  EXPECT_THAT(
-      test::UpdateKeyDistributionInfoWithAllowlist(
-          base::Version("1.0.1"),
-          /*managed_allowlist=*/{GetIwa1WebBundleId(), GetIwa2WebBundleId()}),
-      base::test::HasValue());
+  EXPECT_OK(
+      test::KeyDistributionComponentBuilder(base::Version("1.0.1"))
+          .WithManagedAllowlist({GetIwa1WebBundleId(), GetIwa2WebBundleId()})
+          .Build()
+          .UploadFromComponentFolder());
 
   InitialIwaBundleForceInstall(CreateIwa1Bundle(kUpdateIwaVersion));
   InitialIwaBundleForceInstall(CreateIwa2Bundle("3.0.0"));
 
   // Remove the first app from the allowlist
-  EXPECT_THAT(test::UpdateKeyDistributionInfoWithAllowlist(
-                  base::Version("1.0.2"),
-                  /*managed_allowlist=*/{GetIwa2WebBundleId()}),
-              base::test::HasValue());
+  EXPECT_OK(test::KeyDistributionComponentBuilder(base::Version("1.0.2"))
+                .WithManagedAllowlist({GetIwa2WebBundleId()})
+                .Build()
+                .UploadFromComponentFolder());
 
   EXPECT_FALSE(
       IwaKeyDistributionInfoProvider::GetInstance().IsManagedUpdatePermitted(
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 6ca09c6..7a2f72c3 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1764655003-4baa9886ff423b0a8a017c35eb5e587a59d822b4-2482dcff2b694ed29dbf3277bc9a373bf7f6b18e.profdata
+chrome-android32-main-1764676237-d5448192b64bca70c27e85e3c70156fd43eade2b-aefa88521355c8f992ee1b54f2653c6d2aab9d21.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index f47b5fb..d9b3477 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1764655003-68991c8a7b8233cf3f58fc99b0f9ee40aa7d704b-2482dcff2b694ed29dbf3277bc9a373bf7f6b18e.profdata
+chrome-android-desktop-x64-main-1764676237-f9259d46cc535d145c7f2bd2d6fb8e2fd186a8ba-aefa88521355c8f992ee1b54f2653c6d2aab9d21.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index ef3bd39..eaf97e8 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1764669011-8d66c96262b8e7e893cd43fbb1ca3557acae9d37-35842ffebde86a760310e7f44270882a1f14cd72.profdata
+chrome-mac-arm-main-1764683862-a73aeb2bfb1d711eb489589a9046350d424a7525-2b9ef387b6beaf0576f9690e9e1d0b4a160c2d73.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index c2c111c..3102e73 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1764655003-3ca0b6827e08d1ce73d50147b9f450079c6ed072-2482dcff2b694ed29dbf3277bc9a373bf7f6b18e.profdata
+chrome-mac-main-1764676237-0194d5179aa5dc6bb95f9bfb1976b0e44d7d8f9c-aefa88521355c8f992ee1b54f2653c6d2aab9d21.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index c673948..b7b0e86 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1764655003-dce61f5fd564e11bb312a479b305d6fa9b88aa7d-2482dcff2b694ed29dbf3277bc9a373bf7f6b18e.profdata
+chrome-win-arm64-main-1764676237-30973737b2c2cccec6bdb7445b013135e856f446-aefa88521355c8f992ee1b54f2653c6d2aab9d21.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 66b7a1a..4f74b0e 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1764644297-ccb2736363d2668ca09ea06521ffec60dd222545-351cbac9606375bf4c111da64487f5eccbaf94e3.profdata
+chrome-win32-main-1764655003-f2607cb820749e465a37c64f811424549be5c3b3-2482dcff2b694ed29dbf3277bc9a373bf7f6b18e.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 58299aaa..9b33af3 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1764644297-d683933b16407beee7cd9d635df9b76c3ccba494-351cbac9606375bf4c111da64487f5eccbaf94e3.profdata
+chrome-win64-main-1764665864-baf4186ddf546cdd60e675a50d69e1a71a7a4863-80d270023810acec4b3b94caebb9699b9e44c4ca.profdata
diff --git a/chrome/common/BUILD.gn b/chrome/common/BUILD.gn
index 001b9d5..15adcf8 100644
--- a/chrome/common/BUILD.gn
+++ b/chrome/common/BUILD.gn
@@ -181,7 +181,6 @@
     "//chrome/app/theme:theme_resources",
     "//chrome/common:constants",
     "//chrome/common/net",
-    "//chrome/common/privacy_budget",
     "//chrome/common/profiler",
     "//chrome/common/search:mojo_bindings",
     "//chrome/installer/util:with_no_strings",
diff --git a/chrome/common/privacy_budget/BUILD.gn b/chrome/common/privacy_budget/BUILD.gn
deleted file mode 100644
index a67a64fd..0000000
--- a/chrome/common/privacy_budget/BUILD.gn
+++ /dev/null
@@ -1,53 +0,0 @@
-# Copyright 2020 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("privacy_budget") {
-  sources = [
-    "field_trial_param_conversions.cc",
-    "field_trial_param_conversions.h",
-    "order_preserving_set.h",
-    "privacy_budget_features.cc",
-    "privacy_budget_features.h",
-    "privacy_budget_settings_provider.cc",
-    "privacy_budget_settings_provider.h",
-    "types.h",
-  ]
-
-  configs += [ "//build/config/compiler:wexit_time_destructors" ]
-
-  public_deps = [
-    "//base",
-    "//third_party/blink/public/common",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-
-  sources = [
-    "field_trial_param_conversions_unittest.cc",
-    "order_preserving_set_unittest.cc",
-  ]
-
-  deps = [
-    ":privacy_budget",
-    "//base",
-    "//testing/gtest",
-  ]
-}
-
-source_set("test_support") {
-  testonly = true
-
-  sources = [
-    "scoped_privacy_budget_config.cc",
-    "scoped_privacy_budget_config.h",
-  ]
-
-  deps = [
-    ":privacy_budget",
-    "//base/test:test_support",
-    "//third_party/blink/public/common/privacy_budget",
-  ]
-}
diff --git a/chrome/common/privacy_budget/DEPS b/chrome/common/privacy_budget/DEPS
deleted file mode 100644
index 487aca2a2..0000000
--- a/chrome/common/privacy_budget/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-    "+third_party/blink/public/common/privacy_budget"
-]
diff --git a/chrome/common/privacy_budget/DIR_METADATA b/chrome/common/privacy_budget/DIR_METADATA
deleted file mode 100644
index 6d362b2..0000000
--- a/chrome/common/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
diff --git a/chrome/common/privacy_budget/OWNERS b/chrome/common/privacy_budget/OWNERS
deleted file mode 100644
index b3b93e9..0000000
--- a/chrome/common/privacy_budget/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-file://third_party/blink/public/common/privacy_budget/OWNERS
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chrome/common/privacy_budget/README.md b/chrome/common/privacy_budget/README.md
deleted file mode 100644
index 42b3e70..0000000
--- a/chrome/common/privacy_budget/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Privacy Budget: Static Study Settings
-
-See [Privacy Budget: Code
-Locations](../../../docs/privacy_budget/privacy_budget_code_locations.md) for
-details.
-
diff --git a/chrome/common/privacy_budget/field_trial_param_conversions.cc b/chrome/common/privacy_budget/field_trial_param_conversions.cc
deleted file mode 100644
index a26a51f..0000000
--- a/chrome/common/privacy_budget/field_trial_param_conversions.cc
+++ /dev/null
@@ -1,117 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-
-#include <algorithm>
-#include <string_view>
-#include <utility>
-
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/to_string.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace privacy_budget_internal {
-
-bool DecodeIdentifiabilityType(std::string_view s,
-                               blink::IdentifiableSurface* out) {
-  uint64_t hash = 0;
-  if (!base::StringToUint64(s, &hash))
-    return false;
-  *out = blink::IdentifiableSurface::FromMetricHash(hash);
-  return true;
-}
-
-bool DecodeIdentifiabilityType(std::string_view s,
-                               blink::IdentifiableSurface::Type* out) {
-  uint64_t hash = 0;
-  if (!base::StringToUint64(s, &hash))
-    return false;
-  if ((hash & blink::IdentifiableSurface::kTypeMask) != hash)
-    return false;
-  *out = static_cast<blink::IdentifiableSurface::Type>(hash);
-  return true;
-}
-
-bool DecodeIdentifiabilityType(std::string_view s, int* out) {
-  return base::StringToInt(s, out);
-}
-
-bool DecodeIdentifiabilityType(std::string_view s, uint64_t* out) {
-  return base::StringToUint64(s, out);
-}
-
-bool DecodeIdentifiabilityType(std::string_view s, unsigned int* out) {
-  return base::StringToUint(s, out);
-}
-
-bool DecodeIdentifiabilityType(std::string_view s, double* out) {
-  return base::StringToDouble(s, out);
-}
-
-bool DecodeIdentifiabilityType(std::string_view s,
-                               std::vector<blink::IdentifiableSurface>* out) {
-  *out = DecodeIdentifiabilityFieldTrialParam<
-      std::vector<blink::IdentifiableSurface>, ';'>(s);
-  return !out->empty();
-}
-
-bool DecodeIdentifiabilityType(std::string_view s, std::string* out) {
-  *out = std::string(s);
-  return true;
-}
-
-std::string EncodeIdentifiabilityType(const blink::IdentifiableSurface& s) {
-  return base::NumberToString(s.ToUkmMetricHash());
-}
-
-std::string EncodeIdentifiabilityType(
-    const blink::IdentifiableSurface::Type& t) {
-  return base::NumberToString(static_cast<uint64_t>(t));
-}
-
-std::string EncodeIdentifiabilityType(
-    const std::pair<const blink::IdentifiableSurface, int>& v) {
-  return base::StrCat({EncodeIdentifiabilityType(v.first), ";",
-                       base::NumberToString(v.second)});
-}
-
-std::string EncodeIdentifiabilityType(const unsigned int& v) {
-  return base::NumberToString(v);
-}
-
-std::string EncodeIdentifiabilityType(const double& value) {
-  return base::NumberToString(value);
-}
-
-std::string EncodeIdentifiabilityType(const std::string& value) {
-  return value;
-}
-
-std::string EncodeIdentifiabilityType(const uint64_t& value) {
-  return base::NumberToString(value);
-}
-
-std::string EncodeIdentifiabilityType(const int& value) {
-  return base::NumberToString(value);
-}
-
-std::string EncodeIdentifiabilityType(
-    const std::vector<blink::IdentifiableSurface>& value) {
-  std::vector<std::string> parts;
-  std::ranges::transform(value, std::back_inserter(parts),
-                         [](const blink::IdentifiableSurface v) -> std::string {
-                           return EncodeIdentifiabilityType(v);
-                         });
-  return base::JoinString(parts, ";");
-}
-
-}  // namespace privacy_budget_internal
-
-std::string EncodeIdentifiabilityFieldTrialParam(bool source) {
-  return base::ToString(source);
-}
diff --git a/chrome/common/privacy_budget/field_trial_param_conversions.h b/chrome/common/privacy_budget/field_trial_param_conversions.h
deleted file mode 100644
index 8a49df3..0000000
--- a/chrome/common/privacy_budget/field_trial_param_conversions.h
+++ /dev/null
@@ -1,141 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_FIELD_TRIAL_PARAM_CONVERSIONS_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_FIELD_TRIAL_PARAM_CONVERSIONS_H_
-
-#include <algorithm>
-#include <iterator>
-#include <string_view>
-#include <type_traits>
-#include <vector>
-
-#include "base/strings/strcat.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-// The Encode/Decode families of functions are meant to be used to encode
-// various types so that they can be specified via field trial configurations
-// and Prefs.
-
-namespace privacy_budget_internal {
-
-// DecodeIdentifiabilityType() overloads should not be called directly. Instead
-// use either DecodeIdentifiabilityFieldTrialParam() or
-// EncodeIdentifiabilityFieldTrialParam().
-//
-// DecodeIdentifiabilityType(std::string_view s,V* v) decodes a element of type
-// V serialized as a string and referred to via std::string_view s and stores it
-// in *v.
-bool DecodeIdentifiabilityType(const std::string_view,
-                               blink::IdentifiableSurface*);
-bool DecodeIdentifiabilityType(const std::string_view,
-                               blink::IdentifiableSurface::Type*);
-bool DecodeIdentifiabilityType(const std::string_view, int*);
-bool DecodeIdentifiabilityType(const std::string_view, uint64_t*);
-bool DecodeIdentifiabilityType(const std::string_view, unsigned int*);
-bool DecodeIdentifiabilityType(const std::string_view, double*);
-bool DecodeIdentifiabilityType(const std::string_view,
-                               std::vector<blink::IdentifiableSurface>*);
-bool DecodeIdentifiabilityType(const std::string_view, std::string*);
-
-// V is a std::pair<P,R> where P and R are types known to
-// DecodeIdentifiabilityType().
-template <
-    typename V,
-    typename P = typename std::remove_const<typename V::first_type>::type,
-    typename R = typename std::remove_const<typename V::second_type>::type>
-bool DecodeIdentifiabilityType(std::string_view s, V* result) {
-  auto pieces =
-      base::SplitStringPiece(s, ";", base::WhitespaceHandling::TRIM_WHITESPACE,
-                             base::SplitResult::SPLIT_WANT_NONEMPTY);
-  if (pieces.size() != 2)
-    return false;
-  P first;
-  R second;
-  if (!DecodeIdentifiabilityType(pieces[0], &first) ||
-      !DecodeIdentifiabilityType(pieces[1], &second))
-    return false;
-  ::new (result) V(std::move(first), std::move(second));
-  return true;
-}
-
-std::string EncodeIdentifiabilityType(const blink::IdentifiableSurface&);
-std::string EncodeIdentifiabilityType(const blink::IdentifiableSurface::Type&);
-std::string EncodeIdentifiabilityType(const unsigned int&);
-std::string EncodeIdentifiabilityType(const double&);
-std::string EncodeIdentifiabilityType(const uint64_t&);
-std::string EncodeIdentifiabilityType(const int&);
-template <typename T, typename U>
-std::string EncodeIdentifiabilityType(const std::pair<T, U>& v) {
-  return base::StrCat({EncodeIdentifiabilityType(v.first), ";",
-                       base::NumberToString(v.second)});
-}
-std::string EncodeIdentifiabilityType(
-    const std::vector<blink::IdentifiableSurface>& value);
-std::string EncodeIdentifiabilityType(const std::string& value);
-
-template <typename T>
-struct NoOpFilter {
-  bool operator()(T t) { return true; }
-};
-
-// Instantiate with a type and inherit from std::true_type in order to sort the
-// encoded elements of a container. The ordering is undefined but stable across
-// versions of Chrome.
-template <typename T>
-struct SortWhenSerializing : std::false_type {};
-
-}  // namespace privacy_budget_internal
-
-// Decodes a field trial parameter containing a list of values. The result is
-// returned in the form of a container type that must be specified at
-// instantiation. There should be a valid DecodeIdentifiabilityType
-// specialization for the container's value type.
-template <typename T,
-          char Separator = ',',
-          typename V = typename T::value_type,
-          bool ElementDecoder(const std::string_view, V*) =
-              &privacy_budget_internal::DecodeIdentifiabilityType>
-T DecodeIdentifiabilityFieldTrialParam(std::string_view encoded_value) {
-  T result;
-  auto pieces =
-      base::SplitStringPiece(encoded_value, std::string(1, Separator),
-                             base::WhitespaceHandling::TRIM_WHITESPACE,
-                             base::SplitResult::SPLIT_WANT_NONEMPTY);
-  auto inserter = std::inserter(result, result.end());
-  for (const auto& piece : pieces) {
-    V v;
-    if (!ElementDecoder(piece, &v))
-      continue;
-    inserter = v;
-  }
-  return result;
-}
-
-std::string EncodeIdentifiabilityFieldTrialParam(bool source);
-
-// Encodes a field trial parameter that will contain a list of values taken from
-// a container. The container must satisfy the named requirement Container. Its
-// value_type must have a corresponding EncodeIdentifiabilityType
-// specialization.
-template <typename T,
-          std::string ElementEncoder(const typename T::value_type&) =
-              privacy_budget_internal::EncodeIdentifiabilityType>
-std::string EncodeIdentifiabilityFieldTrialParam(const T& source) {
-  std::vector<std::string> encoded_elements;
-  encoded_elements.reserve(source.size());
-  for (const auto& v : source) {
-    encoded_elements.emplace_back(ElementEncoder(v));
-  }
-  if (privacy_budget_internal::SortWhenSerializing<
-          typename std::remove_cv<T>::type>::value) {
-    std::ranges::sort(encoded_elements);
-  }
-  return base::JoinString(encoded_elements, ",");
-}
-
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_FIELD_TRIAL_PARAM_CONVERSIONS_H_
diff --git a/chrome/common/privacy_budget/field_trial_param_conversions_unittest.cc b/chrome/common/privacy_budget/field_trial_param_conversions_unittest.cc
deleted file mode 100644
index 96b9dac..0000000
--- a/chrome/common/privacy_budget/field_trial_param_conversions_unittest.cc
+++ /dev/null
@@ -1,238 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-
-#include <cstddef>
-#include <cstdint>
-#include <limits>
-#include <string>
-#include <vector>
-
-#include "chrome/common/privacy_budget/types.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace privacy_budget_internal {
-
-namespace {
-
-// 100
-constexpr auto kSurface1 = blink::IdentifiableSurface::FromMetricHash(100);
-
-// 257
-constexpr auto kSurface2 = blink::IdentifiableSurface::FromTypeAndToken(
-    blink::IdentifiableSurface::Type::kWebFeature,
-    1);
-
-// 36028797018963968
-constexpr auto kSurface3 =
-    blink::IdentifiableSurface::FromMetricHash(UINT64_C(1) << 55);
-
-// 1
-constexpr auto kType1 = blink::IdentifiableSurface::Type::kWebFeature;
-
-// 9
-constexpr auto kType2 =
-    blink::IdentifiableSurface::Type::kMediaRecorder_IsTypeSupported;
-
-}  // namespace
-
-TEST(FieldTrialParamConversionsTest, EncodeDecodeSingleSurface) {
-  EXPECT_EQ(std::string("100"), EncodeIdentifiabilityType(kSurface1));
-
-  auto decoded_surface = blink::IdentifiableSurface();
-  EXPECT_TRUE(DecodeIdentifiabilityType("257", &decoded_surface));
-  EXPECT_EQ(kSurface2, decoded_surface);
-
-  EXPECT_FALSE(DecodeIdentifiabilityType("", &decoded_surface));
-}
-
-TEST(FieldTrialParamConversionsTest, EncodeDecodeSingleType) {
-  EXPECT_EQ(std::string("1"), EncodeIdentifiabilityType(kType1));
-
-  auto foo = blink::IdentifiableSurface::Type::kReservedInternal;
-  EXPECT_TRUE(DecodeIdentifiabilityType("1", &foo));
-  EXPECT_EQ(kType1, foo);
-
-  EXPECT_FALSE(DecodeIdentifiabilityType("", &foo));
-}
-
-TEST(FieldTrialParamConversionsTest, SurfaceToIntMap) {
-  const std::map<blink::IdentifiableSurface, unsigned int> original_map = {
-      {kSurface1, 5}, {kSurface3, 5}};
-
-  auto encoded = EncodeIdentifiabilityFieldTrialParam(original_map);
-  EXPECT_EQ(std::string("100;5,36028797018963968;5"), encoded);
-
-  auto decoded_map = DecodeIdentifiabilityFieldTrialParam<
-      std::map<blink::IdentifiableSurface, unsigned int>>(encoded);
-  EXPECT_EQ(original_map, decoded_map);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceList) {
-  const IdentifiableSurfaceList kSurfaceList = {kSurface1, kSurface2,
-                                                kSurface3};
-
-  auto encoded_surface_list =
-      EncodeIdentifiabilityFieldTrialParam(kSurfaceList);
-  EXPECT_EQ(std::string("100,257,36028797018963968"), encoded_surface_list);
-
-  auto decoded_surface_list =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceList>(
-          encoded_surface_list);
-  EXPECT_EQ(kSurfaceList, decoded_surface_list);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceTypeList) {
-  const IdentifiableSurfaceTypeList kTypeList = {kType1, kType2};
-
-  auto encoded_type_list = EncodeIdentifiabilityFieldTrialParam(kTypeList);
-  EXPECT_EQ(std::string("1,9"), encoded_type_list);
-
-  auto decoded_type_list =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceTypeList>(
-          encoded_type_list);
-  EXPECT_EQ(kTypeList, decoded_type_list);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceSet) {
-  const IdentifiableSurfaceSet kSurfaceSet = {kSurface1, kSurface2, kSurface3};
-
-  auto encoded_surface_set = EncodeIdentifiabilityFieldTrialParam(kSurfaceSet);
-  EXPECT_EQ(std::string("100,257,36028797018963968"), encoded_surface_set);
-
-  auto decoded_surface_set =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceSet>(
-          encoded_surface_set);
-  EXPECT_EQ(kSurfaceSet, decoded_surface_set);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceTypeSet) {
-  const IdentifiableSurfaceTypeSet kTypeSet = {kType1, kType2};
-
-  auto encoded_type_set = EncodeIdentifiabilityFieldTrialParam(kTypeSet);
-  EXPECT_EQ(std::string("1,9"), encoded_type_set);
-
-  auto decoded_type_set =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceTypeSet>(
-          encoded_type_set);
-  EXPECT_EQ(kTypeSet, decoded_type_set);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceSampleRateMap) {
-  IdentifiableSurfaceSampleRateMap original_map = {{kSurface1, 5},
-                                                   {kSurface2, 6}};
-
-  auto encoded = EncodeIdentifiabilityFieldTrialParam(original_map);
-  EXPECT_EQ(std::string("100;5,257;6"), encoded);
-
-  auto decoded_map =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceSampleRateMap>(
-          encoded);
-  EXPECT_EQ(original_map, decoded_map);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceTypeSampleRateMap) {
-  const IdentifiableSurfaceTypeSampleRateMap original_map = {{kType1, 6},
-                                                             {kType2, 7}};
-
-  auto encoded = EncodeIdentifiabilityFieldTrialParam(original_map);
-  EXPECT_EQ(std::string("1;6,9;7"), encoded);
-
-  auto decoded_map = DecodeIdentifiabilityFieldTrialParam<
-      IdentifiableSurfaceTypeSampleRateMap>(encoded);
-  EXPECT_EQ(original_map, decoded_map);
-
-  // Extraneous bad values should be silently skipped.
-  auto decoded_with_noise = DecodeIdentifiabilityFieldTrialParam<
-      IdentifiableSurfaceTypeSampleRateMap>("1;6,2;3;4,9;7,10");
-  EXPECT_EQ(original_map, decoded_with_noise);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceCostMap) {
-  const IdentifiableSurfaceCostMap original_map = {
-      {kSurface1, 0.5}, {kSurface2, 0.25}, {kSurface3, 0.4}};
-
-  auto encoded =
-      EncodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceCostMap>(
-          original_map);
-  EXPECT_EQ(std::string("100;0.5,257;0.25,36028797018963968;0.4"), encoded);
-
-  auto decoded =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceCostMap>(
-          "100;0.5,257;0.25,36028797018963968;0.4");
-  EXPECT_EQ(original_map, decoded);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceTypeCostMap) {
-  const IdentifiableSurfaceTypeCostMap original_map = {{kType1, 0.5},
-                                                       {kType2, 0.25}};
-
-  auto encoded =
-      EncodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceTypeCostMap>(
-          original_map);
-  EXPECT_EQ(std::string("1;0.5,9;0.25"), encoded);
-
-  auto decoded =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceTypeCostMap>(
-          "1;0.5,9;0.25");
-  EXPECT_EQ(original_map, decoded);
-}
-
-TEST(FieldTrialParamConversionsTest, SurfaceSetEquivalentClassesList) {
-  const SurfaceSetEquivalentClassesList original_classes = {
-      {kSurface1, kSurface2, kSurface3}, {kSurface3, kSurface2, kSurface1}};
-  auto encoded =
-      EncodeIdentifiabilityFieldTrialParam<SurfaceSetEquivalentClassesList>(
-          original_classes);
-  EXPECT_EQ(std::string("100;257;36028797018963968,36028797018963968;257;100"),
-            encoded);
-  auto decoded =
-      DecodeIdentifiabilityFieldTrialParam<SurfaceSetEquivalentClassesList>(
-          encoded);
-  EXPECT_EQ(original_classes, decoded);
-}
-
-TEST(FieldTrialParamConversionsTest, IdentifiableSurfaceBlocks) {
-  const IdentifiableSurfaceBlocks original_classes = {
-      {kSurface1, kSurface2, kSurface3}, {kSurface3, kSurface2, kSurface1}};
-  auto encoded =
-      EncodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceBlocks>(
-          original_classes);
-  EXPECT_EQ(std::string("100;257;36028797018963968,36028797018963968;257;100"),
-            encoded);
-  auto decoded =
-      DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceBlocks>(encoded);
-  EXPECT_EQ(original_classes, decoded);
-}
-
-TEST(FieldTrialParamConversionsTest, VectorOfSizeT) {
-  const std::vector<unsigned int> kNumbers = {1, 3, 1000,
-                                              std::numeric_limits<int>::max()};
-  auto encoded = EncodeIdentifiabilityFieldTrialParam(kNumbers);
-  EXPECT_EQ(std::string("1,3,1000,2147483647"), encoded);
-
-  auto decoded =
-      DecodeIdentifiabilityFieldTrialParam<std::vector<unsigned int>>(
-          "4,  1000,  23");
-  EXPECT_EQ(std::vector<unsigned int>({4, 1000, 23}), decoded);
-}
-
-TEST(FieldTrialParamConversionsTest, DecodeBadValues) {
-  auto decoded_surface = blink::IdentifiableSurface();
-  EXPECT_FALSE(DecodeIdentifiabilityType("foo", &decoded_surface));
-  EXPECT_FALSE(DecodeIdentifiabilityType("-100", &decoded_surface));
-  EXPECT_FALSE(DecodeIdentifiabilityType("100000000000000000000000000",
-                                         &decoded_surface));
-}
-
-TEST(FieldTrialParamConversionsTest, DecodeBadTypes) {
-  auto decoded_type = blink::IdentifiableSurface::Type::kReservedInternal;
-  EXPECT_FALSE(DecodeIdentifiabilityType("foo", &decoded_type));
-  EXPECT_FALSE(DecodeIdentifiabilityType("-100", &decoded_type));
-  EXPECT_FALSE(DecodeIdentifiabilityType("256", &decoded_type));
-}
-
-}  // namespace privacy_budget_internal
diff --git a/chrome/common/privacy_budget/order_preserving_set.h b/chrome/common/privacy_budget/order_preserving_set.h
deleted file mode 100644
index 7a2776baf..0000000
--- a/chrome/common/privacy_budget/order_preserving_set.h
+++ /dev/null
@@ -1,129 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_ORDER_PRESERVING_SET_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_ORDER_PRESERVING_SET_H_
-
-#include <type_traits>
-#include <vector>
-
-#include "base/check.h"
-#include "base/containers/flat_set.h"
-#include "base/stl_util.h"
-
-// A combination of a set and a list. Lookup semantics come from the set,
-// iterator semantics come from the list.
-//
-// Iterators preserve the insertion or initialization order.
-//
-// Implementing Container, ReversibleContainer, AssociativeContainer are
-// non-goals. It has the bare minimum functionality required for the use cases
-// in this directory.
-//
-// It is assumed that there will be waay more lookups than mutations. Otherwise
-// the underlying container choices may not be efficient.
-template <typename T>
-class OrderPreservingSet {
- public:
-  using value_type = typename std::remove_cv_t<T>;
-  using set_type = base::flat_set<value_type>;
-  using list_type = std::vector<value_type>;
-  using const_iterator = typename list_type::const_iterator;
-
-  OrderPreservingSet() = default;
-
-  // Initializes this object with the contents of `base_list` whose elements
-  // *MUST* be distinct. Preserves the order of elements in `base_list`.
-  explicit OrderPreservingSet(list_type&& base_list)
-      : list_(std::move(base_list)), set_(list_.begin(), list_.end()) {
-    DCHECK(CheckModel());
-  }
-
-  template <typename V>
-  OrderPreservingSet(std::initializer_list<V> v)
-      : list_(v), set_(list_.begin(), list_.end()) {}
-
-  // Modifiers:
-  template <typename V>
-  bool Add(V&& v) {
-    auto insertion_result = set_.insert(std::forward<V>(v));
-    if (insertion_result.second)
-      list_.push_back(v);
-    return insertion_result.second;
-  }
-
-  template <typename V>
-  void push_back(V&& v) {
-    Add(std::forward<V>(v));
-  }
-
-  void Clear() {
-    base::STLClearObject(&list_);
-    base::STLClearObject(&set_);
-  }
-
-  void reserve(typename list_type::size_type element_count) {
-    list_.reserve(element_count);
-    set_.reserve(element_count);
-  }
-
-  // Assign the contents of `list` to this object. Elements of `list` *MUST* be
-  // distinct. Preserves the order of elements in `list`.
-  template <typename V>
-  OrderPreservingSet<T>& Assign(V&& list) {
-    list_ = std::forward<V>(list);
-    set_type replacement_set(list_.begin(), list_.end());
-    set_.swap(replacement_set);
-    DCHECK(CheckModel());
-    return *this;
-  }
-
-  // Assign the contents of `list` to this object. Elements of `list` *MUST* be
-  // distinct. Preserves the order of elements in `list`.
-  template <typename V>
-  OrderPreservingSet<T>& operator=(V&& list) {
-    return Assign(std::forward<V>(list));
-  }
-
-  // Inspectors:
-  template <typename V>
-  auto contains(V&& v) const {
-    return set_.contains(std::forward<V>(v));
-  }
-  // Note the absence of a find() method which would need to return
-  // a set_type::iterator that will clash with the list_type::iterator values
-  // returned by the iterators below.
-
-  // Forwards to list_type.
-  auto size() const { return list_.size(); }
-  bool empty() const { return list_.empty(); }
-  value_type operator[](typename list_type::size_type index) const {
-    return list_[index];
-  }
-
-  // Iteration is in order of insertion. Mutable iterators are not supported.
-  // Hence everything is const only.
-  const_iterator begin() const { return list_.begin(); }
-  const_iterator end() const { return list_.end(); }
-  const_iterator rbegin() const { return list_.rbegin(); }
-  const_iterator rend() const { return list_.rend(); }
-
-  const list_type& AsList() const { return list_; }
-
- private:
-#if DCHECK_IS_ON()
-  // Model checking.
-  bool CheckModel() const {
-    set_type normalized(list_.begin(), list_.end());
-    return normalized == set_ && list_.size() == set_.size();
-  }
-#else
-  bool CheckModel() const { return true; }
-#endif
-
-  list_type list_;
-  set_type set_;
-};
-
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_ORDER_PRESERVING_SET_H_
diff --git a/chrome/common/privacy_budget/order_preserving_set_unittest.cc b/chrome/common/privacy_budget/order_preserving_set_unittest.cc
deleted file mode 100644
index 1f58bfe9..0000000
--- a/chrome/common/privacy_budget/order_preserving_set_unittest.cc
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/order_preserving_set.h"
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-TEST(OrderPreservingSetTest, CanInstantiate) {
-  OrderPreservingSet<blink::IdentifiableSurface> default_initialized;
-  EXPECT_TRUE(default_initialized.empty());
-
-  std::vector<blink::IdentifiableSurface> surfaces_list;
-  OrderPreservingSet<blink::IdentifiableSurface> initialized_with_list(
-      std::move(surfaces_list));
-  EXPECT_TRUE(initialized_with_list.empty());
-
-  OrderPreservingSet<blink::IdentifiableSurface> initialized_with_initializers{
-      blink::IdentifiableSurface::FromMetricHash(1)};
-  EXPECT_FALSE(initialized_with_initializers.empty());
-  EXPECT_EQ(1u, initialized_with_initializers[0].ToUkmMetricHash());
-}
-
-TEST(OrderPreservingSetTest, CanMoveAssign) {
-  std::vector<blink::IdentifiableSurface> surfaces_list = {
-      blink::IdentifiableSurface::FromMetricHash(3),  // not in order.
-      blink::IdentifiableSurface::FromMetricHash(1),
-      blink::IdentifiableSurface::FromMetricHash(2),
-  };
-
-  OrderPreservingSet<blink::IdentifiableSurface> surface_set;
-  surface_set = std::move(surfaces_list);
-
-  EXPECT_EQ(3u, surface_set[0].ToUkmMetricHash());
-  EXPECT_EQ(1u, surface_set[1].ToUkmMetricHash());
-  EXPECT_EQ(2u, surface_set[2].ToUkmMetricHash());
-}
-
-TEST(OrderPreservingSetTest, IteratorsPreserveOrder) {
-  OrderPreservingSet<blink::IdentifiableSurface> surface_set{
-      blink::IdentifiableSurface::FromMetricHash(3),  // not in order.
-      blink::IdentifiableSurface::FromMetricHash(1),
-      blink::IdentifiableSurface::FromMetricHash(2),
-  };
-
-  std::vector<blink::IdentifiableSurface> seen;
-  for (const auto v : surface_set) {
-    seen.push_back(v);
-  }
-
-  EXPECT_EQ(3u, surface_set[0].ToUkmMetricHash());
-  EXPECT_EQ(1u, surface_set[1].ToUkmMetricHash());
-  EXPECT_EQ(2u, surface_set[2].ToUkmMetricHash());
-}
-
-TEST(OrderPreservingSetTest, LookupsWork) {
-  OrderPreservingSet<blink::IdentifiableSurface> surface_set{
-      blink::IdentifiableSurface::FromMetricHash(3),  // not in order.
-      blink::IdentifiableSurface::FromMetricHash(1),
-      blink::IdentifiableSurface::FromMetricHash(2),
-  };
-
-  EXPECT_TRUE(
-      surface_set.contains(blink::IdentifiableSurface::FromMetricHash(3)));
-  EXPECT_FALSE(
-      surface_set.contains(blink::IdentifiableSurface::FromMetricHash(4)));
-}
diff --git a/chrome/common/privacy_budget/privacy_budget_features.cc b/chrome/common/privacy_budget/privacy_budget_features.cc
deleted file mode 100644
index 4c4c21b..0000000
--- a/chrome/common/privacy_budget/privacy_budget_features.cc
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/privacy_budget_features.h"
-
-#include <string>
-
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-
-namespace features {
-
-BASE_FEATURE(kIdentifiabilityStudyMetaExperiment,
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
-const base::FeatureParam<double>
-    kIdentifiabilityStudyMetaExperimentActivationProbability = {
-        // The value -1, being outside the interval [0, 1], will be interpreted
-        // as the default probability, which depends on the channel and is
-        // encoded in
-        // chrome/browser/privacy_budget/identifiability_study_state.cc.
-        &kIdentifiabilityStudyMetaExperiment, "ActivationProbability",
-        kIdentifiabilityStudyMetaExperimentDefaultActivationProbability};
-
-BASE_FEATURE(kIdentifiabilityStudy, base::FEATURE_DISABLED_BY_DEFAULT);
-
-const base::FeatureParam<int> kIdentifiabilityStudyGeneration = {
-    &kIdentifiabilityStudy, "Gen", 0};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyBlockedMetrics = {
-    &kIdentifiabilityStudy, "BlockedHashes", ""};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyBlockedTypes = {
-    &kIdentifiabilityStudy, "BlockedTypes", ""};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyAllowedRandomTypes =
-    {&kIdentifiabilityStudy, "AllowedRandomTypes", ""};
-
-const base::FeatureParam<int> kIdentifiabilityStudyExpectedSurfaceCount = {
-    &kIdentifiabilityStudy, "Rho", 0};
-
-const base::FeatureParam<int> kIdentifiabilityStudyActiveSurfaceBudget = {
-    &kIdentifiabilityStudy, "Max", kMaxIdentifiabilityStudyActiveSurfaceBudget};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyPerHashCost = {
-    &kIdentifiabilityStudy, "HashCost", ""};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyPerTypeCost = {
-    &kIdentifiabilityStudy, "TypeCost", ""};
-
-const base::FeatureParam<std::string>
-    kIdentifiabilityStudySurfaceEquivalenceClasses = {&kIdentifiabilityStudy,
-                                                      "Classes", ""};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyBlocks = {
-    &kIdentifiabilityStudy, "Blocks", ""};
-
-const base::FeatureParam<std::string> kIdentifiabilityStudyBlockWeights = {
-    &kIdentifiabilityStudy, "BlockWeights", ""};
-
-}  // namespace features
diff --git a/chrome/common/privacy_budget/privacy_budget_features.h b/chrome/common/privacy_budget/privacy_budget_features.h
deleted file mode 100644
index 94d3da5f..0000000
--- a/chrome/common/privacy_budget/privacy_budget_features.h
+++ /dev/null
@@ -1,345 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_FEATURES_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_FEATURES_H_
-
-#include <string>
-
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-
-namespace features {
-
-// # Encoding of IdentifiableSurfaces:
-//
-// When used in fieldtrial parameters, nn IdentifiableSurface is encoded as the
-// decimal representation of its ToUkmMetricHash() result. An
-// IdentifiableSurface::Type is encoded as the decimal representation of the
-// enum value.
-
-// Feature for the Identifiability Study Meta experiment.
-//
-// If the feature is enabled, the meta experiment is activated on a random set
-// of clients according to the selection probability.
-BASE_DECLARE_FEATURE(kIdentifiabilityStudyMetaExperiment);
-
-// Probability with which the meta experiment will be activated on each client.
-//
-// Parameter name: "ActivationProbability"
-// Parameter type: double
-//
-// A value of the parameter outside the interval [0, 1] will be interpreted as
-// the default probability, which depends on the channel and is encoded in
-// chrome/browser/privacy_budget/identifiability_study_state.cc
-extern const base::FeatureParam<double>
-    kIdentifiabilityStudyMetaExperimentActivationProbability;
-
-// Default activation probability for the Identifiability Study Meta Experiment.
-// This is a value outside [0, 1], which will be replaced by the default
-// probability depending on the channel in
-// chrome/browser/privacy_budget/identifiability_study_state.cc
-constexpr double
-    kIdentifiabilityStudyMetaExperimentDefaultActivationProbability = -1;
-
-// Root feature for all identifiability study logic.
-//
-// If the feature is disabled, then this browser instance will not be
-// participating in the identifiability study. I.e. no identifiability metrics
-// will be recorded or reported.
-//
-// Enabling the feature doesn't automatically make this client part of the study
-// either.
-BASE_DECLARE_FEATURE(kIdentifiabilityStudy);
-
-// Each time the key study parameters change, the study generation also
-// increments. Reporting the study generation alongside metrics allows the data
-// from different study generations to be grouped independently.
-//
-// Changes to the study generation resets all persisted state for the
-// identifiability study.
-//
-// Parameter name: "Gen"
-// Parameter type: int
-extern const base::FeatureParam<int> kIdentifiabilityStudyGeneration;
-
-// Surfaces that should be excluded from reports.
-//
-// Parameter name: "BlockedHashes"
-// Parameter type: Comma separated list of decimal integers, each of which
-//     represents an IdentifiableSurface.
-//
-// When specifying these values on the command-line, the commas should be
-// escaped using URL encoding. I.e. '1,2' -> '1%2C2'.
-//
-// E.g.:
-//  * "258, 257" : Matches IdentifiableSurface::FromTypeAndToken(kWebFeature, 1)
-//                 and IdentifiableSurface::FromTypeAndToken(kWebFeature, 2)
-//
-// From 03/2021 the code no longer supports revoking a surface that was once
-// blocked either via "BlockedHashes" or "BlockedTypes".
-extern const base::FeatureParam<std::string>
-    kIdentifiabilityStudyBlockedMetrics;
-
-// Surface types that should be excluded from reports.
-//
-// Parameter name: "BlockedTypes"
-// Parameter type: Comma separated list of decimal integers, each of which
-//                 represents an IdentifiableSurface::Type.
-//
-// When specifying these values on the command-line, the commas should be
-// escaped using URL encoding. I.e. '1,2' -> '1%2C2'.
-//
-// E.g.:
-//  * "1, 2" : Matches all surfaces with types kWebFeature and kCanvasReadback.
-//
-// From 03/2021 the code no longer supports revoking a surface that was once
-// blocked either via "BlockedHashes" or "BlockedTypes".
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyBlockedTypes;
-
-// Number of expected identifiable surfaces that will be sampled.
-//
-// Each site you visit implicitly or explicitly observes various identifiable
-// bits of information. This is the number of potentially identifiable surfaces
-// that we expect will be sampled per client.
-//
-// This parameter only affects random sampling of surfaces. Setting this to 0
-// will disable random sampling.
-//
-// Parameter name: "Rho"
-// Parameter type: int
-extern const base::FeatureParam<int> kIdentifiabilityStudyExpectedSurfaceCount;
-
-// Surface types allowed in the random assignment. If the parameter is empty or
-// invalid all types can be sampled.
-
-// This does not have any effect on meta surfaces (type 7), nor on reserved
-// surfaces (type 0), which are sampled in any case. In particular, enabling
-// random sampling and setting this parameter to "0" is a valid way to only
-// enable the meta surfaces experiment.
-//
-// Parameter name: "AllowedRandomTypes"
-// Parameter type: Comma separated list of decimal integers, each of which
-//     represents an IdentifiableSurface::Type.
-//
-// When specifying these values on the command-line, the commas should be
-// escaped using URL encoding. I.e. '1,2' -> '1%2C2'.
-//
-// E.g.:
-//  * "1, 2" : Matches all surfaces with types kWebFeature and kCanvasReadback.
-extern const base::FeatureParam<std::string>
-    kIdentifiabilityStudyAllowedRandomTypes;
-
-// Largest meaningful surface count. Based on observed data. In very rare cases
-// the overall number of surfaces will exceed this limit, but based on prior
-// measurements these cases account for a tiny fraction of the entire
-// population.
-inline constexpr int kMaxIdentifiabilityStudyExpectedSurfaceCount = 1500;
-
-// The limit for the optimistic naive budget for the identifiability study.
-//
-// Each surface that's reported back via metrics reduces the available budget.
-// No report sent back should exceed this budget. The unit of measurement for
-// the budget is currently one _median_ identifiable surface. Some surfaces may
-// be more expensive and some may be less expensive.
-//
-// This value cannot exceed kMaxIdentifiabilityStudyActiveSurfaceBudget.
-//
-// Parameter name: "Max"
-// Parameter type: int
-extern const base::FeatureParam<int> kIdentifiabilityStudyActiveSurfaceBudget;
-
-// This is a hardcoded maximum for the identifiability study budget. The actual
-// budget cannot exceed this value even if it's sent via a server-side
-// configuration.
-//
-// I.e. the following is always true:
-//
-//     active_surface_budget_ <= kMaxIdentifiabilityStudyActiveSurfaceBudget
-//
-// This restriction prevents `active_surface_budget_` being increased past this
-// hardcoded limit from a server-side configuration.
-inline constexpr int kMaxIdentifiabilityStudyActiveSurfaceBudget = 40;
-
-// Relative cost of individual surfaces.
-//
-// Parameter name: "HashCost"
-// Parameter type: Comma separated list of <surface-hash-in-decimal;cost-factor>
-//                 pairs.
-//
-// By default all surfaces cost 1 _average_ surface. Exceptions are noted
-// individually and by type. This parameter contains the per-surface costs.
-//
-// Costs are always specified in units of _average_ surface. The value can be
-// a float expressed in decimal.
-//
-// When specifying these values on the command-line, the commas and semicolons
-// should be escaped using URL encoding. I.e. '1;2,3;4' -> '1%3B2%2C3%3B4'.
-//
-// E.g.:
-//   * "257;0.5" : Sets the relative cost of 0.5 for
-//                 IdentifiableSurface::FromTypeAndToken(kWebFeature, 1).
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyPerHashCost;
-
-// Selection rate for clusters of related surfaces.
-// Surface equivalence classes.
-//
-// Parameter name: "Classes"
-// Parameter type: Comma separated list of classes. Each class is a semicolon
-//                 separated list of surfaces. See examples below.
-//
-// The first surface in the list is the representative surface that forms the
-// basis for determining the cost for the entire class. I.e. the cost of the
-// first surface in the list is assumed to be the cost of _any subset_ of
-// surfaces in the set.
-//
-// Every surface in an equivalence class is assumed to be pairwise perfectly
-// correlated with all other surfaces in the set. For more details see
-// definition of SurfaceSetValuation::EquivalenceClassIdentifierMap.
-//
-// It is an error for a surface to appear in more than one equivalence class.
-//
-// For more details see `SurfaceSetValuation`.
-//
-// E.g.:
-//   * "1;2;3,4;5;6" : Defines two classes: {1,2,3} and {4,5,6}. The surface
-//     with ID 1 defines the cost of the entire class {1,2,3}. Similarly the
-//     surface with ID 4 defines the cost of the entire class {4,5,6}.
-//
-extern const base::FeatureParam<std::string>
-    kIdentifiabilityStudySurfaceEquivalenceClasses;
-
-// Selection rate for clusters of related surface types.
-//
-// Parameter name: "TypeCost"
-// Parameter type: Comma separated list of <surface-type-in-decimal;cost-factor>
-//                 pairs.
-//
-// By default all surfaces cost 1 _average_ surface. Exceptions are noted
-// individually and by type. This parameter contains the per-type costs.
-//
-// Costs are always specified in units of _average_ surface. The value can be
-// a float expressed in decimal.
-//
-// When specifying these values on the command-line, the commas and semicolons
-// should be escaped using URL encoding. I.e. '1;2,3;4' -> '1%3B2%2C3%3B4'.
-//
-// E.g.:
-//   * "1;0.5" : Sets the relative cost of 0.5 for all surfaces of type
-//               kWebFeature.
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyPerTypeCost;
-
-// Surface Sampling Blocks.
-//
-// Parameter name: "Blocks"
-// Parameter type: Comma separated list of blocks. Each block is a semicolon
-//                 separated list of surfaces. See examples below.
-//
-// If this parameter specifies more than one block then at the start of an
-// experiment generation the browser picks one of the blocks at random (see
-// `BlockWeights` for details on the random distribution). All surfaces in the
-// selected block are considered to be in the active set.
-//
-// * It is valid for a single surface to be a member of multiple blocks. The
-//   study only uses one block.
-//
-// * The index of the selected block is persisted. If a new configuration has
-//   the same generation (Gen) but a different value for the `Blocks` parameter,
-//   the client will select the block at the same offset as the one it
-//   previously selected.
-//
-// * Specifying a surface that is blocked (either via `BlockedHashes` or
-//   `BlockedTypes`) is an error.
-//
-// * A non-empty value for this parameter enables assigned block sampling and
-//   disables random sampling.
-//
-// E.g.:
-//   * "1;2;3,4;5;6,7;8;9" : Defines three blocks: {1,2,3}, {4,5,6}, and
-//     {7,8,9}.
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyBlocks;
-
-// Selection Weights for Blocks.
-//
-// Parameter name: "BlockWeights"
-// Parameter type: Comma separated list of relative weights expressed as
-//                 integers.
-//
-// If this parameter is specified then it must specify a weight for each block
-// that is defined using the `Blocks` parameter. Each integer defines the
-// relative weight assigned to the block of surfaces at the corresponding index.
-// Random selection of a block uses the multinomial distribution resulting from
-// normalizing the weights.
-//
-// * All weights must be non-zero positive integers.
-//
-// * There must be exactly as many weights as there are blocks. If not, the
-//   client assumes that the distribution should be uniform.
-//
-// * If this parameter is not specified, then the client assumes that the blocks
-//   are to be selected based on a uniform distribution.
-//
-// E.g.:
-//   * "5,7,3" assigns the probabilities ⅓, 7/15, ⅕ respectively to the three
-//     blocks defined in `Blocks`.
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyBlockWeights;
-
-// Per surface relative cost.
-//
-// Parameter name: "HashCost"
-// Parameter type: Comma separated list of <surface;cost> pairs.
-//
-// By default all surfaces cost 1 *average* surface. Exceptions are noted
-// individually and by type. This parameter contains individual costs.
-//
-// Costs are always specified in units of _average_ surface. The value can be
-// a float expressed in decimal.
-//
-// When specifying these values on the command-line, the commas and semicolons
-// should be escaped using URL encoding. I.e. '1;2,3;4' -> '1%3B2%2C3%3B4'.
-//
-// See SurfaceSetValuation for details on the costing model.
-//
-// E.g.:
-//   * "261;0.5" : Sets the relative cost of 0.5 for surface with ID 261, which
-//   is a surface of type kWebFeature and token 1.
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyPerHashCost;
-
-// Per type relative cost.
-//
-// Parameter name: "TypeCost"
-// Parameter type: Comma separated list of <surface-type;cost> pairs.
-//
-// By default all surfaces cost 1 _average_ surface. Exceptions are noted
-// individually and by type. This parameter contains the per-type costs.
-//
-// Costs are always specified in units of _average_ surface. The value can be
-// a float expressed in decimal.
-//
-// When specifying these values on the command-line, the commas and semicolons
-// should be escaped using URL encoding. I.e. '1;2,3;4' -> '1%3B2%2C3%3B4'.
-//
-// See SurfaceSetValuation for details on the costing model.
-//
-// E.g.:
-//   * "1;0.5" : Sets the relative cost of 0.5 for all surfaces of type
-//               kWebFeature.
-extern const base::FeatureParam<std::string> kIdentifiabilityStudyPerTypeCost;
-
-// This is a hardcoded maximum for the probability of any single surface to be
-// reported as part of the experiment.
-//
-// For example, given the following parameters:
-//     kIdentifiabilityStudyBlocks = "1;2,1;3,4;5"
-//     kIdentifiabilityStudyBlockWeights = "1,1,1"
-// the surface 1 has probability 2/3 to be chosen.
-//
-// If, in the finch client configuration, a surface appears with total
-// probability higher than this threshold, the study will be deactivated for
-// this client and this client will not report any surface.
-inline constexpr double kMaxProbabilityPerSurface = 0.5;
-
-}  // namespace features
-
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_FEATURES_H_
diff --git a/chrome/common/privacy_budget/privacy_budget_settings_provider.cc b/chrome/common/privacy_budget/privacy_budget_settings_provider.cc
deleted file mode 100644
index 5e3ffbe..0000000
--- a/chrome/common/privacy_budget/privacy_budget_settings_provider.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/privacy_budget_settings_provider.h"
-
-#include <algorithm>
-#include <memory>
-
-#include "base/containers/contains.h"
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-#include "chrome/common/privacy_budget/privacy_budget_features.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-PrivacyBudgetSettingsProvider::PrivacyBudgetSettingsProvider(
-    bool meta_experiment_active)
-    : blocked_surfaces_(
-          DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceSet>(
-              features::kIdentifiabilityStudyBlockedMetrics.Get())),
-      blocked_types_(
-          DecodeIdentifiabilityFieldTrialParam<IdentifiableSurfaceTypeSet>(
-              features::kIdentifiabilityStudyBlockedTypes.Get())),
-      enabled_(base::FeatureList::IsEnabled(features::kIdentifiabilityStudy)),
-      meta_experiment_active_(meta_experiment_active) {}
-
-PrivacyBudgetSettingsProvider::PrivacyBudgetSettingsProvider(
-    const PrivacyBudgetSettingsProvider&) = default;
-PrivacyBudgetSettingsProvider::PrivacyBudgetSettingsProvider(
-    PrivacyBudgetSettingsProvider&&) = default;
-PrivacyBudgetSettingsProvider::~PrivacyBudgetSettingsProvider() = default;
-
-bool PrivacyBudgetSettingsProvider::IsMetaExperimentActive() const {
-  return meta_experiment_active_;
-}
-
-bool PrivacyBudgetSettingsProvider::IsActive() const {
-  return enabled_;
-}
-
-bool PrivacyBudgetSettingsProvider::IsAnyTypeOrSurfaceBlocked() const {
-  return !blocked_surfaces_.empty() || !blocked_types_.empty();
-}
-
-bool PrivacyBudgetSettingsProvider::IsSurfaceAllowed(
-    blink::IdentifiableSurface surface) const {
-  return !base::Contains(blocked_surfaces_, surface) &&
-         IsTypeAllowed(surface.GetType());
-}
-
-bool PrivacyBudgetSettingsProvider::IsTypeAllowed(
-    blink::IdentifiableSurface::Type type) const {
-  return !base::Contains(blocked_types_, type);
-}
diff --git a/chrome/common/privacy_budget/privacy_budget_settings_provider.h b/chrome/common/privacy_budget/privacy_budget_settings_provider.h
deleted file mode 100644
index 6c48281..0000000
--- a/chrome/common/privacy_budget/privacy_budget_settings_provider.h
+++ /dev/null
@@ -1,65 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_SETTINGS_PROVIDER_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_SETTINGS_PROVIDER_H_
-
-#include "chrome/common/privacy_budget/types.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-// A IdentifiabilityStudySettingsProvider that's based on the identifiability
-// study feature flags and field trial configuration.
-//
-// These features and field trial parameters are found in
-// privacy_budget_features.h.
-//
-// In the browser process these settings are used to filter out metrics that
-// should be excluded from the study. In the renderer they are used to prevent
-// certain surfaces from being sampled at all.
-//
-// Note: The ONLY parameters that should be exposed to the renderer are those
-//   that are shared across a large number of clients since it is possible to
-//   indirectly observe the set of surfaces that are sampled. Thus the set of
-//   sampled surfaces itself could become an identifier.
-//
-//   Renderer-exposed controls are meant to act as a granular kill switches in
-//   cases where the act of sampling itself has unforeseen adverse side-effects.
-//   Filtering done in the browser are privacy controls and cannot address
-//   issues arising at the point of sampling.
-class PrivacyBudgetSettingsProvider final
-    : public blink::IdentifiabilityStudySettingsProvider {
- public:
-  explicit PrivacyBudgetSettingsProvider(bool meta_experiment_active);
-  PrivacyBudgetSettingsProvider(const PrivacyBudgetSettingsProvider&);
-  PrivacyBudgetSettingsProvider(PrivacyBudgetSettingsProvider&&);
-  ~PrivacyBudgetSettingsProvider() override;
-
-  bool operator=(const PrivacyBudgetSettingsProvider&) const = delete;
-  bool operator=(const PrivacyBudgetSettingsProvider&&) const = delete;
-
-  // blink::IdentifiabilityStudySettingsProvider
-  bool IsMetaExperimentActive() const override;
-  bool IsActive() const override;
-  bool IsAnyTypeOrSurfaceBlocked() const override;
-  bool IsSurfaceAllowed(blink::IdentifiableSurface surface) const override;
-  bool IsTypeAllowed(blink::IdentifiableSurface::Type type) const override;
-
- private:
-  // Set of identifiable surfaces for which we will NOT collect metrics. This
-  // list is server controlled.
-  const IdentifiableSurfaceSet blocked_surfaces_;
-
-  // Set of identifiable surface types for which we will NOT collect metrics.
-  // This list is server controlled.
-  const IdentifiableSurfaceTypeSet blocked_types_;
-
-  // True if identifiability study is enabled.
-  const bool enabled_ = false;
-
-  // True if the meta experiment is enabled for this client.
-  const bool meta_experiment_active_ = false;
-};
-
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_PRIVACY_BUDGET_SETTINGS_PROVIDER_H_
diff --git a/chrome/common/privacy_budget/scoped_privacy_budget_config.cc b/chrome/common/privacy_budget/scoped_privacy_budget_config.cc
deleted file mode 100644
index b8d1261..0000000
--- a/chrome/common/privacy_budget/scoped_privacy_budget_config.cc
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
-
-#include "base/check.h"
-#include "base/metrics/field_trial_params.h"
-#include "base/strings/string_number_conversions.h"
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-#include "chrome/common/privacy_budget/privacy_budget_features.h"
-#include "chrome/common/privacy_budget/types.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace test {
-
-// Are you happy now linker?
-const int ScopedPrivacyBudgetConfig::kDefaultGeneration;
-constexpr int kSelectAllSurfacesExpectedSurfaceCount = 1;
-
-ScopedPrivacyBudgetConfig::Parameters::Parameters() = default;
-ScopedPrivacyBudgetConfig::Parameters::Parameters(const Parameters&) = default;
-ScopedPrivacyBudgetConfig::Parameters::Parameters(Parameters&&) = default;
-ScopedPrivacyBudgetConfig::Parameters::~Parameters() = default;
-
-ScopedPrivacyBudgetConfig::Parameters::Parameters(Presets presets) {
-  switch (presets) {
-    case Presets::kEnableRandomSampling:
-      expected_surface_count = kSelectAllSurfacesExpectedSurfaceCount;
-      break;
-
-    case Presets::kDisable:
-      enabled = false;
-      break;
-  }
-}
-
-ScopedPrivacyBudgetConfig::~ScopedPrivacyBudgetConfig() {
-  DCHECK(applied_) << "ScopedPrivacyBudgetConfig instance created but not "
-                      "applied. Did you forget to call Apply()?";
-}
-
-ScopedPrivacyBudgetConfig::ScopedPrivacyBudgetConfig() = default;
-
-ScopedPrivacyBudgetConfig::ScopedPrivacyBudgetConfig(
-    const Parameters& parameters) {
-  Apply(parameters);
-}
-
-ScopedPrivacyBudgetConfig::ScopedPrivacyBudgetConfig(Presets presets) {
-  Apply(Parameters(presets));
-}
-
-void ScopedPrivacyBudgetConfig::Apply(const Parameters& parameters) {
-  blink::IdentifiabilityStudySettings::ResetStateForTesting();
-  DCHECK(!applied_);
-  applied_ = true;
-
-  if (!parameters.enabled) {
-    scoped_feature_list_.InitAndDisableFeature(features::kIdentifiabilityStudy);
-    return;
-  }
-
-  Parameters defaults;
-
-  base::FieldTrialParams ftp;
-
-  ftp.insert({features::kIdentifiabilityStudyGeneration.name,
-              base::NumberToString(parameters.generation)});
-
-  if (!parameters.blocked_surfaces.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyBlockedMetrics.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.blocked_surfaces)});
-  }
-  if (!parameters.blocked_types.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyBlockedTypes.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.blocked_types)});
-  }
-
-  if (!parameters.allowed_random_types.empty()) {
-    ftp.insert({features::kIdentifiabilityStudyAllowedRandomTypes.name,
-                EncodeIdentifiabilityFieldTrialParam(
-                    parameters.allowed_random_types)});
-  }
-
-  ftp.insert({features::kIdentifiabilityStudyExpectedSurfaceCount.name,
-              base::NumberToString(parameters.expected_surface_count)});
-
-  if (parameters.active_surface_budget != defaults.active_surface_budget) {
-    ftp.insert({features::kIdentifiabilityStudyActiveSurfaceBudget.name,
-                base::NumberToString(parameters.active_surface_budget)});
-  }
-  if (!parameters.per_surface_cost.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyPerHashCost.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.per_surface_cost)});
-  }
-  if (!parameters.per_type_cost.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyPerTypeCost.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.per_type_cost)});
-  }
-  if (!parameters.equivalence_classes.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudySurfaceEquivalenceClasses.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.equivalence_classes)});
-  }
-  if (!parameters.blocks.empty()) {
-    ftp.insert({features::kIdentifiabilityStudyBlocks.name,
-                EncodeIdentifiabilityFieldTrialParam(parameters.blocks)});
-  }
-  if (!parameters.block_weights.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyBlockWeights.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.block_weights)});
-  }
-  if (!parameters.per_surface_cost.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyPerHashCost.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.per_surface_cost)});
-  }
-  if (!parameters.per_type_cost.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudyPerTypeCost.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.per_type_cost)});
-  }
-  if (!parameters.equivalence_classes.empty()) {
-    ftp.insert(
-        {features::kIdentifiabilityStudySurfaceEquivalenceClasses.name,
-         EncodeIdentifiabilityFieldTrialParam(parameters.equivalence_classes)});
-  }
-
-  scoped_feature_list_.InitAndEnableFeatureWithParameters(
-      features::kIdentifiabilityStudy, ftp);
-}
-
-}  // namespace test
diff --git a/chrome/common/privacy_budget/scoped_privacy_budget_config.h b/chrome/common/privacy_budget/scoped_privacy_budget_config.h
deleted file mode 100644
index be206a79..0000000
--- a/chrome/common/privacy_budget/scoped_privacy_budget_config.h
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_SCOPED_PRIVACY_BUDGET_CONFIG_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_SCOPED_PRIVACY_BUDGET_CONFIG_H_
-
-#include <limits>
-#include <map>
-#include <vector>
-
-#include "base/test/scoped_feature_list.h"
-#include "chrome/common/privacy_budget/types.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace test {
-
-// Configures the privacy budget feature settings for testing. One can also
-// configure the service manually by setting the global feature lists
-// directly. This class is merely a convenience.
-//
-// For testing only.
-//
-// Note 1: Since we are changing feature lists, the same caveats as
-//     base::test::ScopedFeatureList apply. E.g. The Apply() method should be
-//     called prior to starting the threads in multi threaded environments.
-//
-// Note 2: The configuration applied by this class is *scoped*. The destructor
-//     reverts the configuration changes.
-class ScopedPrivacyBudgetConfig {
- public:
-  // The default generation is arbitrary. The only thing special about this
-  // number is that it is the default.
-  constexpr static int kDefaultGeneration = 17;
-
-  enum class Presets {
-    // Enables the study with random sampling and with a probability of 1 of
-    // selecting each surface.
-    kEnableRandomSampling,
-
-    // Disables the study. The other parameters are undefined and should not be
-    // relied upon.
-    kDisable
-  };
-
-  // These fields correspond to the equivalent features described in
-  // privacy_budget_features.h
-  struct Parameters {
-    Parameters();
-    explicit Parameters(Presets);
-    Parameters(const Parameters&);
-    Parameters(Parameters&&);
-    ~Parameters();
-
-    bool enabled = true;
-    int generation = kDefaultGeneration;
-
-    IdentifiableSurfaceList blocked_surfaces;
-    IdentifiableSurfaceTypeList blocked_types;
-    int expected_surface_count = 0;
-    int active_surface_budget = std::numeric_limits<int>::max();
-    IdentifiableSurfaceCostMap per_surface_cost;
-    IdentifiableSurfaceTypeCostMap per_type_cost;
-    SurfaceSetEquivalentClassesList equivalence_classes;
-    IdentifiableSurfaceBlocks blocks;
-    std::vector<double> block_weights;
-    std::vector<blink::IdentifiableSurface::Type> allowed_random_types;
-  };
-
-  // Doesn't do anything until Apply() is called.
-  ScopedPrivacyBudgetConfig();
-
-  // Applies the configuration indicated by `preset`.
-  explicit ScopedPrivacyBudgetConfig(Presets preset);
-
-  // Constructs and applies the configuration described in `parameters`. No need
-  // to call Apply()
-  explicit ScopedPrivacyBudgetConfig(const Parameters& parameters);
-
-  ~ScopedPrivacyBudgetConfig();
-
-  // Apply the configuration as described in `parameters`. Should only be called
-  // once per instance.
-  void Apply(const Parameters& parameters);
-
-  ScopedPrivacyBudgetConfig(const ScopedPrivacyBudgetConfig&) = delete;
-  ScopedPrivacyBudgetConfig& operator=(const ScopedPrivacyBudgetConfig&) =
-      delete;
-
- private:
-  base::test::ScopedFeatureList scoped_feature_list_;
-  bool applied_ = false;
-};
-
-}  // namespace test
-
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_SCOPED_PRIVACY_BUDGET_CONFIG_H_
diff --git a/chrome/common/privacy_budget/types.h b/chrome/common/privacy_budget/types.h
deleted file mode 100644
index 0e6fb8d..0000000
--- a/chrome/common/privacy_budget/types.h
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROME_COMMON_PRIVACY_BUDGET_TYPES_H_
-#define CHROME_COMMON_PRIVACY_BUDGET_TYPES_H_
-
-#include <type_traits>
-#include <vector>
-
-#include "base/containers/flat_map.h"
-#include "base/containers/flat_set.h"
-#include "chrome/common/privacy_budget/field_trial_param_conversions.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-// Common container and map types. In order to verify successful encoding and
-// decoding, each of these must be tested in
-// field_trial_param_conversions_unittest.cc.
-//
-// In all cases, the choice of container assumes that:
-//   1. Size is relatively low: Use of a contiguous container helps with data
-//      locality.
-//   2. Mutations are uncommon: A contiguous container is usually expensive to
-//      mutate, but fast lookups and locality make up for it.
-//
-// If other characteristics are desired, then we should consider other container
-// types. Please test encoding/decoding when using new container types.
-
-using IdentifiableSurfaceSet = base::flat_set<blink::IdentifiableSurface>;
-
-using IdentifiableSurfaceTypeSet =
-    base::flat_set<blink::IdentifiableSurface::Type>;
-
-using IdentifiableSurfaceList = std::vector<blink::IdentifiableSurface>;
-
-using IdentifiableSurfaceTypeList =
-    std::vector<blink::IdentifiableSurface::Type>;
-
-// Sampling rates are represented as the denominator of a quotient 1/R. I.e.
-// A sampling rate of 1 in 100 is represented using the integer 100.
-using IdentifiableSurfaceSampleRateMap =
-    base::flat_map<blink::IdentifiableSurface, unsigned int>;
-
-// Sampling rates are represented as the denominator of a quotient 1/R. I.e.
-// A sampling rate of 1 in 100 is represented using the integer 100.
-using IdentifiableSurfaceTypeSampleRateMap =
-    base::flat_map<blink::IdentifiableSurface::Type, unsigned int>;
-
-// See SurfaceSetValuation for details on the costing model and the units for
-// cost.
-using PrivacyBudgetCost = double;
-
-using IdentifiableSurfaceCostMap =
-    base::flat_map<blink::IdentifiableSurface, PrivacyBudgetCost>;
-
-using IdentifiableSurfaceTypeCostMap =
-    base::flat_map<blink::IdentifiableSurface::Type, PrivacyBudgetCost>;
-
-// See SurfaceSetEquivalence for details on how equivalence classes work.
-// SurfaceSetEquivalentClassesList contains a list of equivalence classes. Each
-// class is encoded as a list of surfaces.
-//
-// **The first element in the list is considered to be the representative
-// surface for that class.
-//
-// Obv an equivalence set which contains just zero or one members is
-// nonsensical. For the purpose of ecoding/decoding such instances are ignored.
-using SurfaceSetEquivalentClassesList = std::vector<IdentifiableSurfaceList>;
-
-// Similar to the SurfaceSetEquivalentClassesList, but is semantically different
-// in that the ordering doesn't matter. There's no assumption that the first
-// element of each list is special in any meaningful way.
-using IdentifiableSurfaceBlocks = std::vector<IdentifiableSurfaceList>;
-
-namespace privacy_budget_internal {
-
-template <>
-struct SortWhenSerializing<IdentifiableSurfaceSet> : std::true_type {};
-template <>
-struct SortWhenSerializing<IdentifiableSurfaceTypeSet> : std::true_type {};
-
-}  // namespace privacy_budget_internal
-#endif  // CHROME_COMMON_PRIVACY_BUDGET_TYPES_H_
diff --git a/chrome/renderer/chrome_content_renderer_client_unittest.cc b/chrome/renderer/chrome_content_renderer_client_unittest.cc
index 198146bb..1fda4c3 100644
--- a/chrome/renderer/chrome_content_renderer_client_unittest.cc
+++ b/chrome/renderer/chrome_content_renderer_client_unittest.cc
@@ -15,7 +15,6 @@
 #include "base/command_line.h"
 #include "base/values.h"
 #include "build/build_config.h"
-#include "chrome/common/privacy_budget/scoped_privacy_budget_config.h"
 #include "content/public/common/content_switches.h"
 #include "extensions/buildflags/buildflags.h"
 #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 0884b528..0199fd4 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -7071,8 +7071,6 @@
     "//chrome/common:test_support",
     "//chrome/common:version_header",
     "//chrome/common/notifications",
-    "//chrome/common/privacy_budget:test_support",
-    "//chrome/common/privacy_budget:unit_tests",
     "//chrome/common/profiler:unit_tests",
     "//chrome/common/request_header_integrity:unit_tests",
     "//chrome/common/themes:autogenerated_theme_util",
@@ -7405,7 +7403,6 @@
     "//testing/gtest",
     "//testing/perf:unit_tests",
     "//third_party/abseil-cpp:absl",
-    "//third_party/blink/public/common/privacy_budget:test_support",
     "//third_party/icu",
     "//third_party/leveldatabase",
     "//third_party/libaddressinput",
@@ -9723,7 +9720,6 @@
 
       # This will add all of the unit tests for the schema compiler to this
       # target.
-      "//third_party/blink/common/privacy_budget:test_support",
       "//tools/json_schema_compiler/test:unit_tests",
     ]
 
diff --git a/chrome/test/data/media/tab_media_indicator.html b/chrome/test/data/media/tab_media_indicator.html
new file mode 100644
index 0000000..583071f
--- /dev/null
+++ b/chrome/test/data/media/tab_media_indicator.html
@@ -0,0 +1,18 @@
+<!DOCTYPE html>
+<html>
+<head>
+  <title>Tab Media Indicator Test</title>
+</head>
+<body>
+  <video id="video" playsinline width="200">
+    <source src="bigbuck.webm" type="video/webm">
+  </video>
+  <button id="muteButton">Mute</button>
+  <button id="unmuteButton">Unmute</button>
+  <script>
+    const video = document.getElementById('video');
+    document.getElementById('muteButton').onclick = () => video.muted = true;
+    document.getElementById('unmuteButton').onclick = () => video.muted = false;
+  </script>
+</body>
+</html>
diff --git a/clank b/clank
index 9c5c23a..2719afc 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 9c5c23a8cfe0538d87debe05f72e848c017b3121
+Subproject commit 2719afc3e384f88d83a0ce8b2cb29ab09214dbbc
diff --git a/components/BUILD.gn b/components/BUILD.gn
index 6558eb4..f3128ab 100644
--- a/components/BUILD.gn
+++ b/components/BUILD.gn
@@ -60,7 +60,7 @@
       sources = [
         "//third_party/dom_distiller_js/dist/test/data/out/domdistillerjstest.js",
         "//third_party/dom_distiller_js/dist/test/data/war/test.html",
-        "//third_party/node/node_modules/chai/chai.js",
+        "//third_party/node/node_modules/chai/index.js",
         "//third_party/node/node_modules/mocha/mocha.js",
         "dom_distiller/core/javascript/dom_distiller_viewer.js",
         "dom_distiller/core/javascript/domdistiller.js",
@@ -371,6 +371,7 @@
     "//components/sync_device_info:unit_tests",
     "//components/sync_preferences:unit_tests",
     "//components/sync_preferences/cross_device_pref_tracker:unit_tests",
+    "//components/sync_preferences/synced_set_up:unit_tests",
     "//components/sync_user_events:unit_tests",
     "//components/system_cpu:unit_tests",
     "//components/system_media_controls:unit_tests",
diff --git a/components/autofill/core/browser/filling/form_filler.cc b/components/autofill/core/browser/filling/form_filler.cc
index 27d2a4ef..ccbaac3 100644
--- a/components/autofill/core/browser/filling/form_filler.cc
+++ b/components/autofill/core/browser/filling/form_filler.cc
@@ -54,6 +54,7 @@
 #include "components/autofill/core/common/mojom/autofill_types.mojom-shared.h"
 #include "components/autofill/core/common/unique_ids.h"
 #include "third_party/abseil-cpp/absl/functional/overload.h"
+#include "third_party/libphonenumber/phonenumber_api.h"
 
 namespace autofill {
 
@@ -212,6 +213,23 @@
     return false;
   }
 
+  // Pre-filled country calling codes (e.g., "+1" or "+49") may be overwritten.
+  if (field.Type().GetGroups().contains(FieldTypeGroup::kPhone) &&
+      base::FeatureList::IsEnabled(
+          features::kAutofillOverwriteCountryCallingCodes)) {
+    int maybe_country_calling_code = 0;
+    if (base::StringToInt(
+            base::TrimWhitespace(field.value(), base::TrimPositions::TRIM_ALL),
+            &maybe_country_calling_code)) {
+      std::set<int> country_codes;
+      ::i18n::phonenumbers::PhoneNumberUtil::GetInstance()
+          ->GetSupportedCallingCodes(&country_codes);
+      if (country_codes.contains(maybe_country_calling_code)) {
+        return false;
+      }
+    }
+  }
+
   // If kAutofillSkipPreFilledFields is enabled:
   // Fields that are non-empty on page load are not meant to be overwritten.
   //
diff --git a/components/autofill/core/browser/filling/form_filler_unittest.cc b/components/autofill/core/browser/filling/form_filler_unittest.cc
index 50a996b9..66b83c64 100644
--- a/components/autofill/core/browser/filling/form_filler_unittest.cc
+++ b/components/autofill/core/browser/filling/form_filler_unittest.cc
@@ -1548,6 +1548,51 @@
   EXPECT_EQ(std::u16string(), filled_fields[5].value());
 }
 
+// Tests that a prefilled country calling code does not prevent an Autofill.
+TEST_F(FormFillerTest, FillPhoneNumber_OverwriteCountryCallingCode) {
+  base::test::ScopedFeatureList feature_list(
+      features::kAutofillOverwriteCountryCallingCodes);
+
+  FormData form = test::GetFormData(
+      {.fields = {{.role = NAME_FULL, .autocomplete_attribute = "name"},
+                  {.role = PHONE_HOME_WHOLE_NUMBER,
+                   .value = u"+49",
+                   .autocomplete_attribute = "tel"}}});
+  FormsSeen({form});
+
+  AutofillProfile profile = test::GetFullProfile();
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567");
+  std::vector<FormFieldData> filled_fields =
+      AutofillForm(form, form.fields().front(), &profile).fields();
+
+  ASSERT_EQ(2U, filled_fields.size());
+  EXPECT_EQ(filled_fields[0].value(), u"John H. Doe");
+  EXPECT_THAT(filled_fields[1], AutofilledWith(u"16505554567"));
+}
+
+// Tests that a overwriting of country calling codes is limited to *valid* ones.
+TEST_F(FormFillerTest,
+       FillPhoneNumber_DoNotOverwriteInvalidCountryCallingCode) {
+  base::test::ScopedFeatureList feature_list(
+      features::kAutofillOverwriteCountryCallingCodes);
+
+  FormData form = test::GetFormData(
+      {.fields = {{.role = NAME_FULL, .autocomplete_attribute = "name"},
+                  {.role = PHONE_HOME_WHOLE_NUMBER,
+                   .value = u"+12",
+                   .autocomplete_attribute = "tel"}}});
+  FormsSeen({form});
+
+  AutofillProfile profile = test::GetFullProfile();
+  profile.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, u"16505554567");
+  std::vector<FormFieldData> filled_fields =
+      AutofillForm(form, form.fields().front(), &profile).fields();
+
+  ASSERT_EQ(2U, filled_fields.size());
+  EXPECT_EQ(filled_fields[0].value(), u"John H. Doe");
+  EXPECT_EQ(filled_fields[1].value(), u"+12");
+}
+
 TEST_F(FormFillerTest, FillPassportEntity) {
   base::test::ScopedFeatureList feature_list(
       features::kAutofillAiWithDataSchema);
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc
index 9ec6b17..41caf59 100644
--- a/components/autofill/core/common/autofill_features.cc
+++ b/components/autofill/core/common/autofill_features.cc
@@ -753,6 +753,12 @@
 BASE_FEATURE(kAutofillNewSuggestionGeneration,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// If enabled, prefilled country calling codes like "+49" do not prevent
+// autofilling.
+// TODO(crbug.com/453076638): Cleanup after M146 (after Feb 10, 2026).
+BASE_FEATURE(kAutofillOverwriteCountryCallingCodes,
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Enables detection of language from Translate.
 // TODO(crbug.com/40158074): Cleanup when launched.
 BASE_FEATURE(kAutofillPageLanguageDetection, base::FEATURE_DISABLED_BY_DEFAULT);
@@ -949,6 +955,10 @@
 BASE_FEATURE(kFieldClassificationModelCaching,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+// If enabled, Autofill will retrieve one-time passwords from Gmail.
+// TODO(crbug.com/452607505): Clean up when launched.
+BASE_FEATURE(kGmailOtpRetrievalService, base::FEATURE_DISABLED_BY_DEFAULT);
+
 // When enabled, a HaTS survey is shown after the successful first time creation
 // flow.
 // TODO: crbug.com/348139343 - Move back to components/plus_addresses.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h
index be8af75de..2d97cd81 100644
--- a/components/autofill/core/common/autofill_features.h
+++ b/components/autofill/core/common/autofill_features.h
@@ -262,6 +262,8 @@
                            kAutofillMoreProminentPopupMaxOffsetToCenterParam);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kAutofillNewSuggestionGeneration);
+COMPONENT_EXPORT(AUTOFILL)
+BASE_DECLARE_FEATURE(kAutofillOverwriteCountryCallingCodes);
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillPageLanguageDetection);
 COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillPaymentsFieldSwapping);
 COMPONENT_EXPORT(AUTOFILL)
@@ -323,6 +325,7 @@
 
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kFieldClassificationModelCaching);
+COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kGmailOtpRetrievalService);
 COMPONENT_EXPORT(AUTOFILL)
 BASE_DECLARE_FEATURE(kPlusAddressAcceptedFirstTimeCreateSurvey);
 COMPONENT_EXPORT(AUTOFILL)
diff --git a/components/browser_ui/accessibility/android/java/res/drawable/page_zoom_background.xml b/components/browser_ui/accessibility/android/java/res/drawable/page_zoom_background.xml
index d141af5..cfdcb4a 100644
--- a/components/browser_ui/accessibility/android/java/res/drawable/page_zoom_background.xml
+++ b/components/browser_ui/accessibility/android/java/res/drawable/page_zoom_background.xml
@@ -6,6 +6,6 @@
 -->
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android">
-    <solid android:color="@macro/default_bg_color"/>
+    <solid android:color="?attr/colorSurfaceBright"/>
     <corners android:radius="@dimen/page_zoom_view_corner_radius"/>
 </shape>
\ No newline at end of file
diff --git a/components/content_settings/core/browser/BUILD.gn b/components/content_settings/core/browser/BUILD.gn
index 98422cd..7c4ca05 100644
--- a/components/content_settings/core/browser/BUILD.gn
+++ b/components/content_settings/core/browser/BUILD.gn
@@ -61,7 +61,6 @@
     "//components/pref_registry",
     "//components/prefs",
     "//components/privacy_sandbox:features",
-    "//components/privacy_sandbox:tracking_protection_prefs",
     "//components/tpcd/metadata/browser",
     "//components/url_formatter",
     "//extensions/buildflags",
@@ -106,7 +105,6 @@
     "//components/pref_registry",
     "//components/prefs",
     "//components/privacy_sandbox:features",
-    "//components/privacy_sandbox:tracking_protection_prefs",
     "//components/privacy_sandbox:tracking_protection_settings",
     "//components/tpcd/metadata/browser",
     "//extensions/buildflags",
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index e93b83e..bf5b41c 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -30,7 +30,6 @@
 #include "components/prefs/pref_change_registrar.h"
 #include "components/prefs/pref_service.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 #include "components/privacy_sandbox/tracking_protection_settings.h"
 #include "components/tpcd/metadata/browser/manager.h"
 #include "extensions/buildflags/buildflags.h"
diff --git a/components/content_settings/core/browser/cookie_settings_policy_handler.cc b/components/content_settings/core/browser/cookie_settings_policy_handler.cc
index a6a25798..29363e8 100644
--- a/components/content_settings/core/browser/cookie_settings_policy_handler.cc
+++ b/components/content_settings/core/browser/cookie_settings_policy_handler.cc
@@ -10,7 +10,6 @@
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 
 namespace content_settings {
 
diff --git a/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc b/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
index f0dcd98..fae493d 100644
--- a/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_policy_handler_unittest.cc
@@ -15,7 +15,6 @@
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/testing_pref_service.h"
-#include "components/privacy_sandbox/tracking_protection_prefs.h"
 
 namespace content_settings {
 
diff --git a/components/history/core/browser/browsing_history_service.cc b/components/history/core/browser/browsing_history_service.cc
index 6153f89..f1569332 100644
--- a/components/history/core/browser/browsing_history_service.cc
+++ b/components/history/core/browser/browsing_history_service.cc
@@ -265,23 +265,40 @@
 
   WebHistoryService* web_history = driver_->GetWebHistoryService();
   if (web_history) {
-    // Run WebHistory query for full history. App-specific history uses the
-    // results from the local database only, since the legacy json API service
-    // WebHistory relies on can't be updated to process app_id.
-    if (state->original_options.app_id == kNoAppIdFilter) {
-      if (state->remote_results.size() < desired_count &&
-          state->remote_status != REACHED_BEGINNING) {
-        // Start a timer with timeout before we make the actual query, otherwise
-        // tests get confused when completion callback is run synchronously.
-        web_history_timer_->Start(
-            FROM_HERE, base::Seconds(kWebHistoryTimeoutSeconds),
-            base::BindOnce(&BrowsingHistoryService::WebHistoryTimeout,
-                           weak_factory_.GetWeakPtr(), state));
+    // Test the existence of other forms of browsing history, to display the
+    // privacy disclaimer in the UI. This needs to happen independently of
+    // whether an actual remote history query is happening (yet).
+    driver_->ShouldShowNoticeAboutOtherFormsOfBrowsingHistory(
+        sync_service_, web_history,
+        base::BindOnce(
+            &BrowsingHistoryService::OtherFormsOfBrowsingHistoryQueryComplete,
+            weak_factory_.GetWeakPtr()));
 
-        net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
-            net::DefinePartialNetworkTrafficAnnotation("web_history_query",
-                                                       "web_history_service",
-                                                       R"(
+    // If necessary, run a WebHistory query for remote history.
+    bool should_query_remote = state->remote_results.size() < desired_count &&
+                               state->remote_status != REACHED_BEGINNING;
+
+    // App-specific history uses the results from the local database only, since
+    // the legacy json API service WebHistory relies on can't be updated to
+    // process app_id.
+    // TODO(crbug.com/460361854): Once migrated to a non-legacy API, also query
+    // remote app-specific history.
+    if (state->original_options.app_id != kNoAppIdFilter) {
+      should_query_remote = false;
+    }
+
+    if (should_query_remote) {
+      // Start a timer with timeout before we make the actual query, otherwise
+      // tests get confused when completion callback is run synchronously.
+      web_history_timer_->Start(
+          FROM_HERE, base::Seconds(kWebHistoryTimeoutSeconds),
+          base::BindOnce(&BrowsingHistoryService::WebHistoryTimeout,
+                         weak_factory_.GetWeakPtr(), state));
+
+      net::PartialNetworkTrafficAnnotationTag partial_traffic_annotation =
+          net::DefinePartialNetworkTrafficAnnotation("web_history_query",
+                                                     "web_history_service",
+                                                     R"(
             semantics {
               description:
                 "If history sync is enabled, this downloads the synced "
@@ -305,23 +322,15 @@
                 }
               }
             })");
-        should_return_results_immediately = false;
-        web_history_request_ = web_history->QueryHistory(
-            state->search_text,
-            OptionsWithEndTime(state->original_options,
-                               state->remote_end_time_for_continuation),
-            base::BindOnce(&BrowsingHistoryService::WebHistoryQueryComplete,
-                           weak_factory_.GetWeakPtr(), state, clock_->Now()),
-            partial_traffic_annotation);
-      }
+      should_return_results_immediately = false;
+      web_history_request_ = web_history->QueryHistory(
+          state->search_text,
+          OptionsWithEndTime(state->original_options,
+                             state->remote_end_time_for_continuation),
+          base::BindOnce(&BrowsingHistoryService::WebHistoryQueryComplete,
+                         weak_factory_.GetWeakPtr(), state, clock_->Now()),
+          partial_traffic_annotation);
     }
-    // Test the existence of other forms of browsing history. Performed for both
-    // full/app-specific history to display the privacy disclaimer on UI.
-    driver_->ShouldShowNoticeAboutOtherFormsOfBrowsingHistory(
-        sync_service_, web_history,
-        base::BindOnce(
-            &BrowsingHistoryService::OtherFormsOfBrowsingHistoryQueryComplete,
-            weak_factory_.GetWeakPtr()));
   } else {
     state->remote_status = NO_DEPENDENCY;
     // The notice could not have been shown, because there is no web history.
@@ -695,6 +704,7 @@
           state->local_results.rbegin()->time;
     }
     results = std::move(state->local_results);
+    state->local_results.clear();
   }
 
   QueryResultsInfo info;
diff --git a/components/one_time_tokens/android/backend/sms/BUILD.gn b/components/one_time_tokens/android/backend/sms/BUILD.gn
index 481b996..d8d069c9 100644
--- a/components/one_time_tokens/android/backend/sms/BUILD.gn
+++ b/components/one_time_tokens/android/backend/sms/BUILD.gn
@@ -16,6 +16,8 @@
     "android_sms_otp_fetch_receiver_bridge.h",
     "android_sms_otp_fetch_receiver_bridge_interface.h",
     "sms_otp_retrieval_api_error_codes.h",
+    "sms_otp_to_one_time_token_retrieval_error_converter.cc",
+    "sms_otp_to_one_time_token_retrieval_error_converter.h",
   ]
 
   deps = [
@@ -94,7 +96,10 @@
 
 source_set("unit_tests") {
   testonly = true
-  sources = [ "android_sms_otp_backend_unittest.cc" ]
+  sources = [
+    "android_sms_otp_backend_unittest.cc",
+    "sms_otp_to_one_time_token_retrieval_error_converter_unittest.cc",
+  ]
 
   deps = [
     ":backend",
diff --git a/components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h b/components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h
index b3b39e93..32ebe79 100644
--- a/components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h
+++ b/components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h
@@ -13,9 +13,7 @@
 //
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
-//
-// Needs to be kept in sync with SmsOtpRetrievalApiErrorCode in
-// tools/metrics/histograms/enums.xml.
+// LINT.IfChange
 enum class SmsOtpRetrievalApiErrorCode {
   // CommonStatusCodes.ERROR
   kError = 13,
@@ -28,6 +26,10 @@
   // permission denied by the user.
   kUserPermissionRequired = 36502
 };
+// LINT.ThenChange(
+//   //components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.cc,
+//   //tools/metrics/histograms/enums.xml
+// )
 
 }  // namespace one_time_tokens
 
diff --git a/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.cc b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.cc
new file mode 100644
index 0000000..75942eac
--- /dev/null
+++ b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.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 "components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.h"
+
+#include "components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h"
+#include "components/one_time_tokens/core/browser/one_time_token_retrieval_error.h"
+
+namespace one_time_tokens {
+
+OneTimeTokenRetrievalError ConvertSmsOtpRetrievalApiErrorCode(
+    SmsOtpRetrievalApiErrorCode error_code) {
+  // LINT.IfChange
+  switch (error_code) {
+    case SmsOtpRetrievalApiErrorCode::kError:
+      return OneTimeTokenRetrievalError::kSmsOtpBackendError;
+    case SmsOtpRetrievalApiErrorCode::kTimeout:
+      return OneTimeTokenRetrievalError::kSmsOtpBackendTimeout;
+    case SmsOtpRetrievalApiErrorCode::kPlatformNotSupported:
+      return OneTimeTokenRetrievalError::kSmsOtpBackendPlatformNotSupported;
+    case SmsOtpRetrievalApiErrorCode::kApiNotAvailable:
+      return OneTimeTokenRetrievalError::kSmsOtpBackendApiNotAvailable;
+    case SmsOtpRetrievalApiErrorCode::kUserPermissionRequired:
+      return OneTimeTokenRetrievalError::kSmsOtpBackendUserPermissionRequired;
+  }
+  // LINT.ThenChange(//components/one_time_tokens/core/browser/one_time_token_retrieval_error.h)
+}
+
+}  // namespace one_time_tokens
diff --git a/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.h b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.h
new file mode 100644
index 0000000..51fc4d6
--- /dev/null
+++ b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.h
@@ -0,0 +1,18 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_ONE_TIME_TOKENS_ANDROID_BACKEND_SMS_SMS_OTP_TO_ONE_TIME_TOKEN_RETRIEVAL_ERROR_CONVERTER_H_
+#define COMPONENTS_ONE_TIME_TOKENS_ANDROID_BACKEND_SMS_SMS_OTP_TO_ONE_TIME_TOKEN_RETRIEVAL_ERROR_CONVERTER_H_
+
+namespace one_time_tokens {
+
+enum class OneTimeTokenRetrievalError;
+enum class SmsOtpRetrievalApiErrorCode;
+
+OneTimeTokenRetrievalError ConvertSmsOtpRetrievalApiErrorCode(
+    SmsOtpRetrievalApiErrorCode error_code);
+
+}  // namespace one_time_tokens
+
+#endif  // COMPONENTS_ONE_TIME_TOKENS_ANDROID_BACKEND_SMS_SMS_OTP_TO_ONE_TIME_TOKEN_RETRIEVAL_ERROR_CONVERTER_H_
diff --git a/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter_unittest.cc b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter_unittest.cc
new file mode 100644
index 0000000..542b210
--- /dev/null
+++ b/components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/one_time_tokens/android/backend/sms/sms_otp_to_one_time_token_retrieval_error_converter.h"
+
+#include "components/one_time_tokens/android/backend/sms/sms_otp_retrieval_api_error_codes.h"
+#include "components/one_time_tokens/core/browser/one_time_token_retrieval_error.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace one_time_tokens {
+
+TEST(SmsOtpToOnetimeTokenRetrievalErrorConverterTest, Smoke) {
+  EXPECT_EQ(
+      ConvertSmsOtpRetrievalApiErrorCode(SmsOtpRetrievalApiErrorCode::kError),
+      OneTimeTokenRetrievalError::kSmsOtpBackendError);
+  EXPECT_EQ(
+      ConvertSmsOtpRetrievalApiErrorCode(SmsOtpRetrievalApiErrorCode::kTimeout),
+      OneTimeTokenRetrievalError::kSmsOtpBackendTimeout);
+  EXPECT_EQ(ConvertSmsOtpRetrievalApiErrorCode(
+                SmsOtpRetrievalApiErrorCode::kPlatformNotSupported),
+            OneTimeTokenRetrievalError::kSmsOtpBackendPlatformNotSupported);
+  EXPECT_EQ(ConvertSmsOtpRetrievalApiErrorCode(
+                SmsOtpRetrievalApiErrorCode::kApiNotAvailable),
+            OneTimeTokenRetrievalError::kSmsOtpBackendApiNotAvailable);
+  EXPECT_EQ(ConvertSmsOtpRetrievalApiErrorCode(
+                SmsOtpRetrievalApiErrorCode::kUserPermissionRequired),
+            OneTimeTokenRetrievalError::kSmsOtpBackendUserPermissionRequired);
+}
+
+}  // namespace one_time_tokens
diff --git a/components/one_time_tokens/core/browser/one_time_token_retrieval_error.h b/components/one_time_tokens/core/browser/one_time_token_retrieval_error.h
index 905b81c..2f607c9 100644
--- a/components/one_time_tokens/core/browser/one_time_token_retrieval_error.h
+++ b/components/one_time_tokens/core/browser/one_time_token_retrieval_error.h
@@ -11,7 +11,13 @@
 // numeric values should never be reused.
 enum class OneTimeTokenRetrievalError {
   kUnknown = 0,
-  kMaxValue = kUnknown,
+  // The following map to SmsOtpRetrievalApiErrorCode.
+  kSmsOtpBackendError = 1,
+  kSmsOtpBackendTimeout = 2,
+  kSmsOtpBackendPlatformNotSupported = 3,
+  kSmsOtpBackendApiNotAvailable = 4,
+  kSmsOtpBackendUserPermissionRequired = 5,
+  kMaxValue = kSmsOtpBackendUserPermissionRequired,
 };
 
 }  // namespace one_time_tokens
diff --git a/components/one_time_tokens/core/browser/one_time_token_type.h b/components/one_time_tokens/core/browser/one_time_token_type.h
index c59980bd..f1927cd 100644
--- a/components/one_time_tokens/core/browser/one_time_token_type.h
+++ b/components/one_time_tokens/core/browser/one_time_token_type.h
@@ -8,7 +8,7 @@
 namespace one_time_tokens {
 
 // Do not change or reuse values.
-enum class OneTimeTokenType { kSmsOtp = 0, kMaxValue = kSmsOtp };
+enum class OneTimeTokenType { kSmsOtp = 0, kGmail = 1, kMaxValue = kGmail };
 
 }  // namespace one_time_tokens
 
diff --git a/components/paint_preview/common/file_stream.cc b/components/paint_preview/common/file_stream.cc
index aefda0a..4a288e1 100644
--- a/components/paint_preview/common/file_stream.cc
+++ b/components/paint_preview/common/file_stream.cc
@@ -6,9 +6,11 @@
 
 #include <stdint.h>
 
+#include <optional>
 #include <utility>
 
 #include "base/compiler_specific.h"
+#include "base/containers/span.h"
 
 namespace paint_preview {
 
@@ -54,14 +56,14 @@
     has_write_failed_ = true;
     return false;
   }
-  int bytes = UNSAFE_TODO(
-      file_.WriteAtCurrentPos(reinterpret_cast<const char*>(buffer), size));
-  if (bytes < 0) {
+  std::optional<size_t> bytes_written = file_.WriteAtCurrentPos(
+      UNSAFE_TODO(base::span(reinterpret_cast<const uint8_t*>(buffer), size)));
+  if (!bytes_written) {
     has_write_failed_ = true;
     return false;
   }
-  bytes_written_ += bytes;
-  if (static_cast<size_t>(bytes) != size) {
+  bytes_written_ += *bytes_written;
+  if (*bytes_written != size) {
     has_write_failed_ = true;
     return false;
   }
@@ -101,15 +103,18 @@
     if (origin < 0)
       return 0;
     num_bytes = file_.Seek(base::File::FROM_CURRENT, size);
-    if (num_bytes < 0)
+    if (num_bytes < 0 || num_bytes < origin) {
       return 0;
+    }
     num_bytes = num_bytes - origin;
   } else {
-    num_bytes = UNSAFE_TODO(
-        file_.ReadAtCurrentPos(reinterpret_cast<char*>(buffer), size));
+    const std::optional<size_t> bytes_read = file_.ReadAtCurrentPos(
+        UNSAFE_TODO(base::span(reinterpret_cast<uint8_t*>(buffer), size)));
+    if (!bytes_read) {
+      return 0;
+    }
+    num_bytes = *bytes_read;
   }
-  if (num_bytes < 0)
-    return 0;
   bytes_read_ += num_bytes;
   return num_bytes;
 }
diff --git a/components/paint_preview/common/serial_utils.cc b/components/paint_preview/common/serial_utils.cc
index 4faaa74..b68f76c5 100644
--- a/components/paint_preview/common/serial_utils.cc
+++ b/components/paint_preview/common/serial_utils.cc
@@ -51,7 +51,7 @@
 #pragma pack(pop)
 
 // Serializes a SkPicture representing a subframe as a custom data placeholder.
-sk_sp<SkData> SerializePictureAsRectData(SkPicture* picture, void* ctx) {
+SkSerialReturnType SerializePictureAsRectData(SkPicture* picture, void* ctx) {
   TRACE_EVENT0("paint_preview", "SerializePictureAsRectData");
   const PictureSerializationContext* context =
       reinterpret_cast<PictureSerializationContext*>(ctx);
@@ -75,7 +75,7 @@
 // De-duplicates and subsets used typefaces and discards any unused typefaces.
 // If subsetting fails (or on Android) this returns data only for non-system
 // fonts. This means the resulting SkPicture is not portable across devices.
-sk_sp<SkData> SerializeTypeface(SkTypeface* typeface, void* ctx) {
+SkSerialReturnType SerializeTypeface(SkTypeface* typeface, void* ctx) {
   TRACE_EVENT0("paint_preview", "SerializeTypeface");
   TypefaceSerializationContext* context =
       reinterpret_cast<TypefaceSerializationContext*>(ctx);
@@ -140,7 +140,7 @@
          SkWebpDecoder::IsWebp(data->data(), data->size());
 }
 
-sk_sp<SkData> SerializeImage(SkImage* image, void* ctx) {
+SkSerialReturnType SerializeImage(SkImage* image, void* ctx) {
   TRACE_EVENT0("paint_preview", "SerializeImage");
   ImageSerializationContext* context =
       reinterpret_cast<ImageSerializationContext*>(ctx);
@@ -184,7 +184,6 @@
     }
     context->remaining_image_size -= encoded_data->size();
   }
-
   return encoded_data;
 }
 
diff --git a/components/paint_preview/common/serial_utils_unittest.cc b/components/paint_preview/common/serial_utils_unittest.cc
index b9856c00f..b8ae7d25 100644
--- a/components/paint_preview/common/serial_utils_unittest.cc
+++ b/components/paint_preview/common/serial_utils_unittest.cc
@@ -72,7 +72,7 @@
 
   // Check that serializing then deserialize the picture works produces a
   // correct clip rect.
-  sk_sp<SkData> serial_pic_data =
+  auto serial_pic_data =
       serial_procs.fPictureProc(pic.get(), serial_procs.fPictureCtx);
   sk_sp<SkPicture> deserial_pic = deserial_procs.fPictureProc(
       serial_pic_data->data(), serial_pic_data->size(),
diff --git a/components/plus_addresses/core/browser/plus_address_http_client_impl.cc b/components/plus_addresses/core/browser/plus_address_http_client_impl.cc
index 4acc1bf..f3c085e3 100644
--- a/components/plus_addresses/core/browser/plus_address_http_client_impl.cc
+++ b/components/plus_addresses/core/browser/plus_address_http_client_impl.cc
@@ -214,8 +214,7 @@
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory)
     : identity_manager_(CHECK_DEREF(identity_manager)),
       url_loader_factory_(std::move(url_loader_factory)),
-      server_url_(ValidateAndGetUrl()),
-      scopes_({features::kEnterprisePlusAddressOAuthScope.Get()}) {}
+      server_url_(ValidateAndGetUrl()) {}
 
 PlusAddressHttpClientImpl::~PlusAddressHttpClientImpl() = default;
 
@@ -481,8 +480,8 @@
   }
   access_token_fetcher_ =
       std::make_unique<signin::PrimaryAccountAccessTokenFetcher>(
-          /*consumer_name=*/"PlusAddressHttpClientImpl",
-          &identity_manager_.get(), scopes_,
+          signin::OAuthConsumerId::kEnterprisePlusAddress,
+          &identity_manager_.get(),
           base::BindOnce(&PlusAddressHttpClientImpl::OnTokenFetched,
                          // It is safe to use base::Unretained as
                          // `this` owns `access_token_fetcher_`.
diff --git a/components/plus_addresses/core/browser/plus_address_http_client_impl.h b/components/plus_addresses/core/browser/plus_address_http_client_impl.h
index b526a00..684ffff 100644
--- a/components/plus_addresses/core/browser/plus_address_http_client_impl.h
+++ b/components/plus_addresses/core/browser/plus_address_http_client_impl.h
@@ -17,7 +17,6 @@
 #include "base/types/optional_ref.h"
 #include "components/plus_addresses/core/browser/plus_address_http_client.h"
 #include "components/plus_addresses/core/browser/plus_address_types.h"
-#include "components/signin/public/identity_manager/scope_set.h"
 #include "url/gurl.h"
 
 class GoogleServiceAuthError;
@@ -139,8 +138,6 @@
 
   const std::optional<GURL> server_url_;
 
-  const signin::ScopeSet scopes_;
-
   std::unique_ptr<signin::PrimaryAccountAccessTokenFetcher>
       access_token_fetcher_ GUARDED_BY_CONTEXT(sequence_checker_);
 
diff --git a/components/plus_addresses/core/browser/plus_address_http_client_impl_unittest.cc b/components/plus_addresses/core/browser/plus_address_http_client_impl_unittest.cc
index 8612b78..e736923 100644
--- a/components/plus_addresses/core/browser/plus_address_http_client_impl_unittest.cc
+++ b/components/plus_addresses/core/browser/plus_address_http_client_impl_unittest.cc
@@ -338,8 +338,9 @@
 
   // ConfirmPlusAddress will run `callback` after an OAuth token is retrieved.
   identity_env()
-      .WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
-          "token", base::Time::Max(), "id", {kTestScope});
+      .WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForConsumerId(
+          "token", base::Time::Max(),
+          signin::OAuthConsumerId::kEnterprisePlusAddress);
 
   // Unblock the pending request.
   ASSERT_EQ(url_loader_factory().NumPending(), 1);
@@ -700,7 +701,6 @@
 
   static constexpr base::TimeDelta kTestTokenLifetime = base::Seconds(1000);
   static constexpr char kTestToken[] = "access_token";
-  static constexpr char kTestScope[] = "https://googleapis.com/test.scope";
 
  protected:
   PlusAddressHttpClientImpl& client() { return *client_; }
@@ -721,8 +721,9 @@
 
   void WaitAndRespondToTokenRequest(base::Time expiration) {
     identity_env()
-        .WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForScopes(
-            kTestToken, expiration, "unused", {kTestScope});
+        .WaitForAccessTokenRequestIfNecessaryAndRespondWithTokenForConsumerId(
+            kTestToken, expiration,
+            signin::OAuthConsumerId::kEnterprisePlusAddress);
   }
 
  private:
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/StaticStorageQuotaEnabled.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/StaticStorageQuotaEnabled.yaml
index 82020f5..51f6ad82 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/StaticStorageQuotaEnabled.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/StaticStorageQuotaEnabled.yaml
@@ -3,7 +3,7 @@
 desc: |-
   When enabled, the storage quota APIs will return a static value equal to usage + min(10 GiB, disk rounded up to the nearest 1 GiB).
   When disabled, the storage quota APIs will generally return a dynamic value proportional to the total space available on the device, regardless of usage.
-  If unset, the predictable reported storage quota feature launch or flags will determine behavior.
+  If unset, the storage quota APIs will use the default Chrome behavior.
   Sites with unlimited storage permissions are unaffected by this setting. Enforced quota is also unaffected.
 example_value: true
 features:
diff --git a/components/signin/public/base/BUILD.gn b/components/signin/public/base/BUILD.gn
index c9ca3572..1f450c1 100644
--- a/components/signin/public/base/BUILD.gn
+++ b/components/signin/public/base/BUILD.gn
@@ -112,12 +112,13 @@
 
   deps = [
     "//base/test:test_support",
+    "//components/plus_addresses/core/common:features",
     "//components/prefs",
+    "//crypto",
+    "//google_apis:test_support",
 
     # TODO(b/309104936): Remove this unwanted dependency.
     "//components/signin/public/identity_manager",
-    "//crypto",
-    "//google_apis:test_support",
   ]
 
   public_deps = [
diff --git a/components/signin/public/base/oauth_consumer_id.h b/components/signin/public/base/oauth_consumer_id.h
index e8ec050..8580eab28 100644
--- a/components/signin/public/base/oauth_consumer_id.h
+++ b/components/signin/public/base/oauth_consumer_id.h
@@ -7,6 +7,11 @@
 
 namespace signin {
 
+namespace oauth_consumer_name {
+inline extern const char kEnterprisePlusAddressName[] =
+    "enterprise_plus_address";
+}
+
 // LINT.IfChange(OAuthConsumerId)
 // These values are persisted to logs. Entries should not be renumbered and
 // numeric values should never be reused.
@@ -91,7 +96,8 @@
   kAuthServiceTasksClient = 76,
   kYouTubeMusic = 77,
   kContextualTasks = 78,
-  kMaxValue = kContextualTasks,
+  kEnterprisePlusAddress = 79,
+  kMaxValue = kEnterprisePlusAddress,
 };
 // LINT.ThenChange(//tools/metrics/histograms/metadata/signin/enums.xml:OAuthConsumerId)
 
diff --git a/components/signin/public/base/oauth_consumer_registry.cc b/components/signin/public/base/oauth_consumer_registry.cc
index d6ff3dc..8358436 100644
--- a/components/signin/public/base/oauth_consumer_registry.cc
+++ b/components/signin/public/base/oauth_consumer_registry.cc
@@ -473,6 +473,8 @@
           /*name=*/kContextualTasksName,
           /*scopes=*/{GaiaConstants::kChromeSyncOAuth2Scope,
                       GaiaConstants::kClearCutOAuth2Scope});
+    case OAuthConsumerId::kEnterprisePlusAddress:
+      return GetOAuthConsumerForEnterprisePlusAddress();
   }
 }
 
diff --git a/components/signin/public/base/oauth_consumer_registry.h b/components/signin/public/base/oauth_consumer_registry.h
index 3f9e34fa4..64fa2296 100644
--- a/components/signin/public/base/oauth_consumer_registry.h
+++ b/components/signin/public/base/oauth_consumer_registry.h
@@ -30,9 +30,7 @@
   OAuthConsumer GetOAuthConsumerFromId(OAuthConsumerId oauth_consumer_id) const;
 
  protected:
-  // TODO(crbug.com/425896213): Add method per feature instead of a single one.
-  virtual OAuthConsumer GetOAuthConsumerFromIdInternal(
-      OAuthConsumerId oauth_consumer_id) const = 0;
+  virtual OAuthConsumer GetOAuthConsumerForEnterprisePlusAddress() const = 0;
 };
 
 }  // namespace signin
diff --git a/components/signin/public/base/signin_feature_map.cc b/components/signin/public/base/signin_feature_map.cc
index 4f1f49dd..d6dd7a1 100644
--- a/components/signin/public/base/signin_feature_map.cc
+++ b/components/signin/public/base/signin_feature_map.cc
@@ -20,7 +20,6 @@
 // Array of features exposed through the Java SigninFeatures API.
 const base::Feature* const kFeaturesExposedToJava[] = {
     &switches::kCctSignInPrompt,
-    &switches::kEnableAddSessionRedirect,
     &switches::kEnableSeamlessSignin,
     &switches::kForceStartupSigninPromo,
     &switches::kForceHistoryOptInScreen,
diff --git a/components/signin/public/base/signin_switches.cc b/components/signin/public/base/signin_switches.cc
index a3e1164d..27f49871 100644
--- a/components/signin/public/base/signin_switches.cc
+++ b/components/signin/public/base/signin_switches.cc
@@ -145,10 +145,6 @@
                    base::Milliseconds(3000));
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 
-#if BUILDFLAG(IS_ANDROID)
-BASE_FEATURE(kEnableAddSessionRedirect, base::FEATURE_ENABLED_BY_DEFAULT);
-#endif
-
 #if BUILDFLAG(IS_IOS)
 BASE_FEATURE(kEnableASWebAuthenticationSession,
              base::FEATURE_ENABLED_BY_DEFAULT);
diff --git a/components/signin/public/base/signin_switches.h b/components/signin/public/base/signin_switches.h
index 9147544..251991e 100644
--- a/components/signin/public/base/signin_switches.h
+++ b/components/signin/public/base/signin_switches.h
@@ -139,13 +139,6 @@
                            kChromeIdentitySurveyLaunchWithDelayDuration);
 #endif  // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX)
 
-#if BUILDFLAG(IS_ANDROID)
-// After an account is added via the ADD_SESSION header it will be redirected to
-// the specified URL.
-COMPONENT_EXPORT(SIGNIN_SWITCHES)
-BASE_DECLARE_FEATURE(kEnableAddSessionRedirect);
-#endif
-
 #if BUILDFLAG(IS_IOS)
 // Features to enable using the ASWebAuthenticationSession to add accounts to
 // device.
diff --git a/components/signin/public/base/test_signin_client.cc b/components/signin/public/base/test_signin_client.cc
index 5f95d15e..142ca96c 100644
--- a/components/signin/public/base/test_signin_client.cc
+++ b/components/signin/public/base/test_signin_client.cc
@@ -9,6 +9,7 @@
 
 #include "base/check.h"
 #include "base/functional/callback.h"
+#include "components/plus_addresses/core/common/features.h"
 #include "components/signin/public/identity_manager/primary_account_change_event.h"
 #include "components/version_info/channel.h"
 #include "google_apis/gaia/gaia_auth_fetcher.h"
@@ -21,9 +22,13 @@
 
 class TestOAuthConsumerRegistry : public signin::OAuthConsumerRegistry {
  protected:
-  signin::OAuthConsumer GetOAuthConsumerFromIdInternal(
-      signin::OAuthConsumerId oauth_consumer_id) const override {
-    NOTREACHED();
+  signin::OAuthConsumer GetOAuthConsumerForEnterprisePlusAddress()
+      const override {
+    CHECK(base::FeatureList::IsEnabled(
+        plus_addresses::features::kPlusAddressesEnabled));
+    return signin::OAuthConsumer(
+        signin::oauth_consumer_name::kEnterprisePlusAddressName,
+        {plus_addresses::features::kEnterprisePlusAddressOAuthScope.Get()});
   }
 };
 
diff --git a/components/signin/public/browser/web_signin_tracker.cc b/components/signin/public/browser/web_signin_tracker.cc
index 207e2d7..f35739d 100644
--- a/components/signin/public/browser/web_signin_tracker.cc
+++ b/components/signin/public/browser/web_signin_tracker.cc
@@ -11,23 +11,22 @@
 #include "components/signin/public/base/signin_switches.h"
 #include "components/signin/public/identity_manager/account_info.h"
 #include "components/signin/public/identity_manager/accounts_in_cookie_jar_info.h"
-#include "third_party/abseil-cpp/absl/functional/overload.h"
+
 namespace signin {
 
 WebSigninTracker::WebSigninTracker(
     IdentityManager* identity_manager,
     AccountReconcilor* account_reconcilor,
-    std::variant<CoreAccountId, std::string> signin_account,
+    CoreAccountId signin_account,
     base::OnceCallback<void(WebSigninTracker::Result)> callback,
     std::optional<base::TimeDelta> timeout)
     : identity_manager_(identity_manager),
-      account_reconcilor_(account_reconcilor),
       signin_account_(signin_account),
       callback_(std::move(callback)) {
   CHECK(callback_);
 
   identity_manager_observation_.Observe(identity_manager_);
-  account_reconcilor_observation_.Observe(account_reconcilor_);
+  account_reconcilor_observation_.Observe(account_reconcilor);
 
   if (timeout) {
     timeout_timer_.Start(FROM_HERE, *timeout, this,
@@ -50,9 +49,10 @@
     const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
     const GoogleServiceAuthError& error) {
   for (const auto& account :
-       accounts_in_cookie_jar_info.GetValidSignedInAccounts()) {
-    if (MatchesRequestedAccount(account.id, account.email)) {
+       accounts_in_cookie_jar_info.GetPotentiallyInvalidSignedInAccounts()) {
+    if (account.valid && account.id == signin_account_) {
       FinishWithResult(Result::kSuccess);
+      return;
     }
   }
 }
@@ -69,24 +69,10 @@
     return;
   }
 
-  // If account is not on the device ignore errors from the account reconciler.
-  for (const CoreAccountInfo& account :
-       identity_manager_->GetAccountsWithRefreshTokens()) {
-    if (MatchesRequestedAccount(account.account_id, account.email)) {
-      bool is_auth_error = false;
-      if (std::holds_alternative<CoreAccountId>(signin_account_)) {
-        is_auth_error =
-            identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
-                std::get<CoreAccountId>(signin_account_));
-      } else {
-        // The account is not on the device and so this will be an auth error.
-        is_auth_error = true;
-      }
-
-      FinishWithResult(is_auth_error ? Result::kAuthError
-                                     : Result::kOtherError);
-    }
-  }
+  bool is_auth_error =
+      identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState(
+          signin_account_);
+  FinishWithResult(is_auth_error ? Result::kAuthError : Result::kOtherError);
 }
 
 void WebSigninTracker::OnTimeoutReached() {
@@ -100,18 +86,4 @@
   std::move(callback_).Run(result);
 }
 
-bool WebSigninTracker::MatchesRequestedAccount(
-    const CoreAccountId& account_id,
-    const std::string& account_email) {
-  return std::visit(absl::Overload(
-                        [&account_id](const CoreAccountId& requested_id) {
-                          return account_id == requested_id;
-                        },
-                        [&account_email](const std::string& requested_email) {
-                          return gaia::AreEmailsSame(account_email,
-                                                     requested_email);
-                        }),
-                    signin_account_);
-}
-
 }  // namespace signin
diff --git a/components/signin/public/browser/web_signin_tracker.h b/components/signin/public/browser/web_signin_tracker.h
index 38a7350..725eba17 100644
--- a/components/signin/public/browser/web_signin_tracker.h
+++ b/components/signin/public/browser/web_signin_tracker.h
@@ -6,7 +6,6 @@
 #define COMPONENTS_SIGNIN_PUBLIC_BROWSER_WEB_SIGNIN_TRACKER_H_
 
 #include <optional>
-#include <string>
 
 #include "base/functional/callback_forward.h"
 #include "base/memory/raw_ptr.h"
@@ -41,7 +40,7 @@
 
   WebSigninTracker(IdentityManager* identity_manager,
                    AccountReconcilor* account_reconcilor,
-                   std::variant<CoreAccountId, std::string> signin_account,
+                   CoreAccountId signin_account,
                    base::OnceCallback<void(Result)> callback,
                    std::optional<base::TimeDelta> timeout = std::nullopt);
 
@@ -62,14 +61,9 @@
  private:
   void OnTimeoutReached();
   void FinishWithResult(WebSigninTracker::Result result);
-  bool MatchesRequestedAccount(const CoreAccountId& account_id,
-                               const std::string& account_email);
 
   const raw_ptr<IdentityManager> identity_manager_;
-  const raw_ptr<AccountReconcilor> account_reconcilor_;
-  // Holds either the CoreAccountId of the signed-in account, or the email
-  // address of the account has not been made available in IdentityManager yet.
-  std::variant<CoreAccountId, std::string> signin_account_;
+  CoreAccountId signin_account_;
   base::OnceCallback<void(Result)> callback_;
   base::ScopedObservation<IdentityManager, IdentityManager::Observer>
       identity_manager_observation_{this};
diff --git a/components/signin/public/identity_manager/BUILD.gn b/components/signin/public/identity_manager/BUILD.gn
index 9ffb19b..8ab621d 100644
--- a/components/signin/public/identity_manager/BUILD.gn
+++ b/components/signin/public/identity_manager/BUILD.gn
@@ -6,6 +6,10 @@
   import("//build/config/android/rules.gni")
 }
 
+if (!is_fuchsia) {
+  import("//pdf/features.gni")
+}
+
 source_set("identity_manager") {
   sources = [
     "access_token_fetcher.cc",
@@ -69,6 +73,10 @@
     "//services/network/public/cpp",
   ]
 
+  if (!is_fuchsia) {
+    deps += [ "//pdf:buildflags" ]
+  }
+
   if (is_chromeos) {
     deps += [ "//components/user_manager" ]
   }
@@ -162,6 +170,10 @@
     ]
   }
 
+  if (!is_fuchsia) {
+    deps += [ "//pdf:buildflags" ]
+  }
+
   # TODO(crbug.com/40031409): Fix code that adds exit-time destructors and
   # enable the diagnostic by removing this line.
   configs += [ "//build/config/compiler:no_exit_time_destructors" ]
diff --git a/components/signin/public/identity_manager/DEPS b/components/signin/public/identity_manager/DEPS
index e340bfa7..ffe42a75 100644
--- a/components/signin/public/identity_manager/DEPS
+++ b/components/signin/public/identity_manager/DEPS
@@ -1,4 +1,5 @@
 include_rules = [
   "+components/signin/internal",
   "+components/signin/public",
+  "+pdf/buildflags.h",
 ]
diff --git a/components/signin/public/identity_manager/access_token_restriction.cc b/components/signin/public/identity_manager/access_token_restriction.cc
index 8d52a40..c4e9d4e 100644
--- a/components/signin/public/identity_manager/access_token_restriction.cc
+++ b/components/signin/public/identity_manager/access_token_restriction.cc
@@ -11,6 +11,10 @@
 #include "components/plus_addresses/core/common/features.h"
 #include "google_apis/gaia/gaia_constants.h"
 
+#if !BUILDFLAG(IS_FUCHSIA)
+#include "pdf/buildflags.h"  // nogncheck
+#endif                       // !BUILDFLAG(IS_FUCHSIA)
+
 namespace signin {
 
 namespace {
@@ -33,10 +37,11 @@
       // sign in.
       GaiaConstants::kSecureConnectOAuth2Scope,
 
-      // TODO(crbug.com/446152335): Consider wrapping this in
-      // `ENABLE_PDF_SAVE_TO_DRIVE` build flag.
-      // Required for save to Drive.
+#if !BUILDFLAG(IS_FUCHSIA)
+#if BUILDFLAG(ENABLE_PDF_SAVE_TO_DRIVE)
       GaiaConstants::kDriveOAuth2Scope,
+#endif  // BUILDFLAG(ENABLE_PDF_SAVE_TO_DRIVE)
+#endif  // !BUILDFLAG(IS_FUCHSIA)
 
       // TODO(b/321900823): Fix tests and move below scopes to require the
       // browser to be signed in.
diff --git a/components/signin/public/identity_manager/access_token_restriction_unittest.cc b/components/signin/public/identity_manager/access_token_restriction_unittest.cc
index df5c676a..056e01d 100644
--- a/components/signin/public/identity_manager/access_token_restriction_unittest.cc
+++ b/components/signin/public/identity_manager/access_token_restriction_unittest.cc
@@ -4,9 +4,14 @@
 
 #include "components/signin/public/identity_manager/access_token_restriction.h"
 
+#include "build/build_config.h"
 #include "google_apis/gaia/gaia_constants.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#if !BUILDFLAG(IS_FUCHSIA)
+#include "pdf/buildflags.h"  // nogncheck
+#endif                       // !BUILDFLAG(IS_FUCHSIA)
+
 namespace {
 struct AccessTokenRestrictionTestParam {
   std::string scope;
@@ -52,6 +57,7 @@
  {GaiaConstants::kAuditRecordingOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kCastBackdropOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kClearCutOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
+ {GaiaConstants::kDriveOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kExperimentsAndConfigsOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kGCMGroupServerOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kNearbyDevicesOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
@@ -62,9 +68,13 @@
  {GaiaConstants::kPhotosOAuth2Scope, OAuth2ScopeRestriction::kSignedIn},
  {GaiaConstants::kTachyonOAuthScope, OAuth2ScopeRestriction::kSignedIn},
  #endif  // BUILDFLAG(IS_CHROMEOS)
+#if !BUILDFLAG(IS_FUCHSIA)
+#if BUILDFLAG(ENABLE_PDF_SAVE_TO_DRIVE)
+ {GaiaConstants::kDriveOAuth2Scope, OAuth2ScopeRestriction::kNoRestriction},
+#endif  // BUILDFLAG(ENABLE_PDF_SAVE_TO_DRIVE)
+#endif  // !BUILDFLAG(IS_FUCHSIA)
  {GaiaConstants::kAnyApiOAuth2Scope, OAuth2ScopeRestriction::kPrivilegedOAuth2Consumer},
  {GaiaConstants::kChromeSyncSupervisedOAuth2Scope, OAuth2ScopeRestriction::kExplicitConsent},
- {GaiaConstants::kDriveOAuth2Scope, OAuth2ScopeRestriction::kNoRestriction},
  {GaiaConstants::kKidManagementPrivilegedOAuth2Scope, OAuth2ScopeRestriction::kExplicitConsent},
  {GaiaConstants::kKidsSupervisionSetupChildOAuth2Scope, OAuth2ScopeRestriction::kExplicitConsent},
  {GaiaConstants::kGoogleTalkOAuth2Scope, OAuth2ScopeRestriction::kExplicitConsent},
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc
index 8ca16b7..fdf9e91 100644
--- a/components/sync/base/features.cc
+++ b/components/sync/base/features.cc
@@ -37,6 +37,9 @@
 
 BASE_FEATURE(kSyncContextualTask, base::FEATURE_DISABLED_BY_DEFAULT);
 
+// Enabled by default, intended as a kill switch.
+BASE_FEATURE(kSyncLinkTabsAndTabGroupsPolicy, base::FEATURE_ENABLED_BY_DEFAULT);
+
 #if !BUILDFLAG(IS_CHROMEOS)
 BASE_FEATURE(kUnoPhase2FollowUp,
 #if BUILDFLAG(IS_ANDROID)
diff --git a/components/sync/base/features.h b/components/sync/base/features.h
index 93b22fa..a2fdafb 100644
--- a/components/sync/base/features.h
+++ b/components/sync/base/features.h
@@ -48,6 +48,10 @@
 // Enables syncing of contextual tasks.
 BASE_DECLARE_FEATURE(kSyncContextualTask);
 
+// If enabled, SyncTypesListDisabled policy for tabs and saved tab groups is
+// linked.
+BASE_DECLARE_FEATURE(kSyncLinkTabsAndTabGroupsPolicy);
+
 #if !BUILDFLAG(IS_CHROMEOS)
 // Flag that controls Uno fast-follow features which are:
 // On Android:
diff --git a/components/sync/service/sync_policy_handler.cc b/components/sync/service/sync_policy_handler.cc
index ea188ca6..23659e3e 100644
--- a/components/sync/service/sync_policy_handler.cc
+++ b/components/sync/service/sync_policy_handler.cc
@@ -13,6 +13,7 @@
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
 #include "components/strings/grit/components_strings.h"
+#include "components/sync/base/features.h"
 #include "components/sync/base/pref_names.h"
 #include "components/sync/base/user_selectable_type.h"
 #include "components/sync/service/sync_prefs.h"
@@ -31,6 +32,18 @@
       syncer::SyncPrefs::SetTypeDisabledByPolicy(prefs,
                                                  UserSelectableType::kPayments);
     }
+
+    // If tabs are disabled, also disable saved tab groups, and vice-versa.
+    if (base::FeatureList::IsEnabled(kSyncLinkTabsAndTabGroupsPolicy)) {
+      if (*type == UserSelectableType::kTabs) {
+        syncer::SyncPrefs::SetTypeDisabledByPolicy(
+            prefs, UserSelectableType::kSavedTabGroups);
+      }
+      if (*type == UserSelectableType::kSavedTabGroups) {
+        syncer::SyncPrefs::SetTypeDisabledByPolicy(prefs,
+                                                   UserSelectableType::kTabs);
+      }
+    }
   }
 
 #if BUILDFLAG(IS_CHROMEOS)
diff --git a/components/sync/service/sync_policy_handler_unittest.cc b/components/sync/service/sync_policy_handler_unittest.cc
index 8435cfe..a28917c 100644
--- a/components/sync/service/sync_policy_handler_unittest.cc
+++ b/components/sync/service/sync_policy_handler_unittest.cc
@@ -9,12 +9,14 @@
 #include <utility>
 #include <vector>
 
+#include "base/test/scoped_feature_list.h"
 #include "base/values.h"
 #include "components/policy/core/browser/policy_error_map.h"
 #include "components/policy/core/common/policy_map.h"
 #include "components/policy/core/common/policy_types.h"
 #include "components/policy/policy_constants.h"
 #include "components/prefs/pref_value_map.h"
+#include "components/sync/base/features.h"
 #include "components/sync/base/pref_names.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
@@ -138,6 +140,59 @@
   EXPECT_TRUE(enabled);
 }
 
+TEST(SyncPolicyHandlerTest, SyncTypesListDisabled_TabsAndSavedTabGroups) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(kSyncLinkTabsAndTabGroupsPolicy);
+  // Start with prefs enabled so we can sense that they have changed.
+  PrefValueMap prefs;
+  prefs.SetBoolean(prefs::internal::kSyncTabs, true);
+  prefs.SetBoolean(prefs::internal::kSyncSavedTabGroups, true);
+
+  // Create a policy that disables tabs.
+  policy::PolicyMap policy;
+  auto disabled_types = base::Value::List().Append("tabs");
+  policy.Set(policy::key::kSyncTypesListDisabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD,
+             base::Value(std::move(disabled_types)), nullptr);
+  SyncPolicyHandler handler;
+  handler.ApplyPolicySettings(policy, &prefs);
+
+  // Both tabs and saved tab groups should be disabled.
+  bool enabled;
+  ASSERT_TRUE(prefs.GetBoolean(prefs::internal::kSyncTabs, &enabled));
+  EXPECT_FALSE(enabled);
+  ASSERT_TRUE(prefs.GetBoolean(prefs::internal::kSyncSavedTabGroups, &enabled));
+  EXPECT_FALSE(enabled);
+}
+
+TEST(SyncPolicyHandlerTest,
+     SyncTypesListDisabled_TabsAndSavedTabGroupsFeatureDisabled) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(kSyncLinkTabsAndTabGroupsPolicy);
+  // Start with prefs enabled so we can sense that they have changed.
+  PrefValueMap prefs;
+  prefs.SetBoolean(prefs::internal::kSyncTabs, true);
+  prefs.SetBoolean(prefs::internal::kSyncSavedTabGroups, true);
+
+  // Create a policy that disables tabs.
+  policy::PolicyMap policy;
+  auto disabled_types = base::Value::List().Append("tabs");
+  policy.Set(policy::key::kSyncTypesListDisabled,
+             policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER,
+             policy::POLICY_SOURCE_CLOUD,
+             base::Value(std::move(disabled_types)), nullptr);
+  SyncPolicyHandler handler;
+  handler.ApplyPolicySettings(policy, &prefs);
+
+  // Only tabs should be disabled.
+  bool enabled;
+  ASSERT_TRUE(prefs.GetBoolean(prefs::internal::kSyncTabs, &enabled));
+  EXPECT_FALSE(enabled);
+  ASSERT_TRUE(prefs.GetBoolean(prefs::internal::kSyncSavedTabGroups, &enabled));
+  EXPECT_TRUE(enabled);
+}
+
 TEST(SyncPolicyHandlerTest, SyncTypesListDisabledInvalidEntry) {
   // Start with prefs enabled so we can sense that they have changed.
   PrefValueMap prefs;
diff --git a/components/sync_preferences/synced_set_up/BUILD.gn b/components/sync_preferences/synced_set_up/BUILD.gn
new file mode 100644
index 0000000..63918ce2
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/BUILD.gn
@@ -0,0 +1,40 @@
+# 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.
+
+source_set("utils") {
+  sources = [
+    "utils.cc",
+    "utils.h",
+  ]
+  public_deps = [
+    "//base",
+    "//components/commerce/core:pref_names",
+    "//components/ntp_tiles:pref_names",
+    "//components/omnibox/browser:pref_names",
+    "//components/safety_check:pref_names",
+    "//components/sync_preferences/cross_device_pref_tracker/prefs",
+  ]
+  deps = [
+    "//components/prefs",
+    "//components/sync_device_info",
+    "//components/sync_preferences/cross_device_pref_tracker",
+    "//components/sync_preferences/cross_device_pref_tracker:timestamped_pref_value",
+  ]
+}
+
+source_set("unit_tests") {
+  testonly = true
+  sources = [ "utils_unittest.cc" ]
+  deps = [
+    ":utils",
+    "//base",
+    "//base/test:test_support",
+    "//components/sync/protocol",
+    "//components/sync_device_info",
+    "//components/sync_device_info:test_support",
+    "//components/sync_preferences/cross_device_pref_tracker",
+    "//components/sync_preferences/cross_device_pref_tracker:timestamped_pref_value",
+    "//testing/gtest",
+  ]
+}
diff --git a/components/sync_preferences/synced_set_up/DEPS b/components/sync_preferences/synced_set_up/DEPS
new file mode 100644
index 0000000..6ee2a9a0
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/DEPS
@@ -0,0 +1,9 @@
+include_rules = [
+# keep-sorted start
+  "+components/commerce/core/pref_names.h",
+  "+components/ntp_tiles/pref_names.h",
+  "+components/omnibox/browser/omnibox_pref_names.h",
+  "+components/safety_check/safety_check_pref_names.h",
+  "+components/sync_preferences/cross_device_pref_tracker/prefs/cross_device_pref_names.h",
+# keep-sorted end
+]
diff --git a/components/sync_preferences/synced_set_up/OWNERS b/components/sync_preferences/synced_set_up/OWNERS
new file mode 100644
index 0000000..4c158f6e
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/OWNERS
@@ -0,0 +1,2 @@
+bwwilliams@google.com
+jhimawan@google.com
diff --git a/components/sync_preferences/synced_set_up/utils.cc b/components/sync_preferences/synced_set_up/utils.cc
new file mode 100644
index 0000000..271951c
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/utils.cc
@@ -0,0 +1,189 @@
+// 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/sync_preferences/synced_set_up/utils.h"
+
+#include <optional>
+#include <string>
+#include <tuple>
+
+#include "base/values.h"
+#include "components/prefs/pref_service.h"
+#include "components/sync_device_info/device_info_tracker.h"
+#include "components/sync_preferences/cross_device_pref_tracker/cross_device_pref_tracker.h"
+#include "components/sync_preferences/cross_device_pref_tracker/timestamped_pref_value.h"
+
+namespace {
+
+// Struct representing a unique device, containing a map of cross-device pref
+// names and values, and the total number of changes observed by the
+// `CrossDevicePrefTracker` for the device.
+struct DeviceData {
+  // Map of all cross-device prefs and their values associated with this
+  // device.
+  std::map<std::string_view, sync_preferences::TimestampedPrefValue> pref_map;
+  // Total number of observed pref changes on this device.
+  size_t observed_change_count = 0;
+};
+
+// A map of device GUID's to device data containing the devices' respective sets
+// of synced prefs and number of observed remote pref changes.
+using DeviceDataMap = std::map<std::string, DeviceData>;
+
+// Helper for adding `DeviceData` entries related to a `DeviceDataMap`, using
+// prefs contained in `pref_map`.
+template <size_t N>
+void BuildDeviceDataMapFromPrefMap(
+    DeviceDataMap& device_data_map,
+    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
+    const base::fixed_flat_map<std::string_view, std::string_view, N>&
+        pref_map) {
+  sync_preferences::CrossDevicePrefTracker::DeviceFilter filter;
+
+  // Query the tracker for tracked prefs and construct a `DeviceDataMap`
+  // associating device GUID's with sets of prefs.
+  for (const auto& tracked_pref : pref_map) {
+    std::vector<sync_preferences::TimestampedPrefValue> pref_values =
+        pref_tracker->GetValues(tracked_pref.first, filter);
+
+    // Populate the device data map with device GUID's mapped to their set of
+    // synced prefs and number of recent observed changes.
+    for (const sync_preferences::TimestampedPrefValue& pref_value :
+         pref_values) {
+      DeviceData& device_data_entry =
+          device_data_map[pref_value.device_sync_cache_guid];
+
+      // Ensure that only the most recent observed pref change is preserved in
+      // the DeviceData pref map.
+      auto it = device_data_entry.pref_map.find(tracked_pref.first);
+      if (it == device_data_entry.pref_map.end() ||
+          pref_value.last_observed_change_time >=
+              it->second.last_observed_change_time) {
+        device_data_entry.pref_map.insert_or_assign(tracked_pref.first,
+                                                    pref_value.Clone());
+      }
+
+      // Count total observed pref changes.
+      if (!pref_value.last_observed_change_time.is_null()) {
+        device_data_entry.observed_change_count++;
+      }
+    }
+  }
+}
+
+// Returns a map of synced device GUID's to the devices' associated synced pref
+// data.
+DeviceDataMap MapPrefsToDevices(
+    const sync_preferences::CrossDevicePrefTracker* pref_tracker) {
+  DeviceDataMap device_data_map;
+  BuildDeviceDataMapFromPrefMap(
+      device_data_map, pref_tracker,
+      sync_preferences::synced_set_up::kCrossDeviceToProfilePrefMap);
+  BuildDeviceDataMapFromPrefMap(
+      device_data_map, pref_tracker,
+      sync_preferences::synced_set_up::kCrossDeviceToLocalStatePrefMap);
+  return device_data_map;
+}
+
+// Returns the best fitting device in a `DeviceDataMap` of considered devices
+// and their associated prefs.
+DeviceData GetBestMatchDeviceData(
+    DeviceDataMap& synced_devices,
+    const syncer::DeviceInfoTracker* device_info_tracker,
+    const syncer::DeviceInfo* local_device) {
+  // Criteria for scoring devices against the local device as the best match for
+  // applying synced prefs.
+  using MatchesFormFactor = bool;
+  using MatchesOsType = bool;
+  using RecentPrefChangeCount = size_t;
+
+  using DeviceScore =
+      std::tuple<MatchesFormFactor, MatchesOsType, RecentPrefChangeCount>;
+
+  // Devices cannot be scored.
+  if (synced_devices.empty() || !device_info_tracker || !local_device) {
+    return {};
+  }
+
+  // Use a std::set to automatically order the scores.
+  // We store {score, guid} pairs. The set orders primarily by score.
+  using ScoredDevice = std::pair<DeviceScore, std::string_view>;
+  std::set<ScoredDevice> scored_remote_devices;
+
+  const std::string& local_device_guid = local_device->guid();
+
+  for (const auto& [guid, data] : synced_devices) {
+    // 1. Skip local device and devices with no prefs.
+    if (guid == local_device_guid || data.pref_map.empty()) {
+      continue;
+    }
+
+    // 2. Ensure the device info exists.
+    const syncer::DeviceInfo* device_info =
+        device_info_tracker->GetDeviceInfo(guid);
+    if (!device_info) {
+      continue;
+    }
+
+    // 3. Calculate and insert the score.
+    DeviceScore score = {
+        device_info->form_factor() == local_device->form_factor(),
+        device_info->os_type() == local_device->os_type(),
+        data.observed_change_count};
+    scored_remote_devices.insert({score, guid});
+  }
+
+  if (scored_remote_devices.empty()) {
+    return {};
+  }
+
+  // The best device is the last element in the ordered set.
+  const auto& best_match = *scored_remote_devices.rbegin();
+  const std::string best_guid = std::string(best_match.second);
+
+  // Final check: Compare activity level with the local device, if present.
+  auto local_it = synced_devices.find(local_device_guid);
+  if (local_it != synced_devices.end()) {
+    if (local_it->second.observed_change_count >
+        synced_devices.at(best_guid).observed_change_count) {
+      // Local device has more activity; prefer to keep local settings.
+      return {};
+    }
+  }
+  return std::move(synced_devices.at(best_guid));
+}
+
+// Returns a map of tracked pref names and their values extracted from a set of
+// `DeviceData`.
+std::map<std::string_view, base::Value> GetCrossDevicePrefValuesForDevice(
+    DeviceData& device) {
+  std::map<std::string_view, base::Value> prefs;
+  for (const auto& [cross_device_pref_name, timestamped_pref_value] :
+       device.pref_map) {
+    prefs.insert(std::make_pair(cross_device_pref_name,
+                                timestamped_pref_value.value.Clone()));
+  }
+  return prefs;
+}
+
+}  // namespace
+
+namespace sync_preferences::synced_set_up {
+
+std::map<std::string_view, base::Value> GetCrossDevicePrefsFromRemoteDevice(
+    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
+    const syncer::DeviceInfoTracker* device_info_tracker,
+    const syncer::DeviceInfo* local_device) {
+  if (!pref_tracker || !device_info_tracker || !local_device) {
+    return {};
+  }
+  DeviceDataMap device_data_map = MapPrefsToDevices(pref_tracker);
+  DeviceData best_match_device_data = GetBestMatchDeviceData(
+      device_data_map, device_info_tracker, local_device);
+  std::map<std::string_view, base::Value> cross_device_pref_values =
+      GetCrossDevicePrefValuesForDevice(best_match_device_data);
+  return cross_device_pref_values;
+}
+
+}  // namespace sync_preferences::synced_set_up
diff --git a/components/sync_preferences/synced_set_up/utils.h b/components/sync_preferences/synced_set_up/utils.h
new file mode 100644
index 0000000..9f24e877
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/utils.h
@@ -0,0 +1,74 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_SYNC_PREFERENCES_SYNCED_SET_UP_UTILS_H_
+#define COMPONENTS_SYNC_PREFERENCES_SYNCED_SET_UP_UTILS_H_
+
+#include <map>
+#include <string_view>
+
+#include "base/containers/fixed_flat_map.h"
+#include "components/commerce/core/pref_names.h"
+#include "components/ntp_tiles/pref_names.h"
+#include "components/omnibox/browser/omnibox_pref_names.h"
+#include "components/safety_check/safety_check_pref_names.h"
+#include "components/sync_preferences/cross_device_pref_tracker/prefs/cross_device_pref_names.h"
+
+namespace base {
+class Value;
+}  // namespace base
+
+namespace syncer {
+class DeviceInfo;
+class DeviceInfoTracker;
+}  // namespace syncer
+
+namespace sync_preferences {
+
+class CrossDevicePrefTracker;
+
+namespace synced_set_up {
+
+// Map of cross-device synced prefs considered by Synced Set Up mapped to their
+// corresponding tracked local-state pref.
+inline constexpr auto kCrossDeviceToLocalStatePrefMap =
+    base::MakeFixedFlatMap<std::string_view, std::string_view>({
+        // keep-sorted start
+        {prefs::kCrossDeviceOmniboxIsInBottomPosition,
+         omnibox::kIsOmniboxInBottomPosition},
+        // keep-sorted end
+    });
+
+// Map of cross-device synced prefs considered by Synced Set Up mapped to their
+// corresponding tracked profile pref.
+inline constexpr auto kCrossDeviceToProfilePrefMap =
+    base::MakeFixedFlatMap<std::string_view, std::string_view>({
+        // keep-sorted start
+        {prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+         ntp_tiles::prefs::kMagicStackHomeModuleEnabled},
+        {prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+         ntp_tiles::prefs::kMostVisitedHomeModuleEnabled},
+        {prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
+         commerce::kPriceTrackingHomeModuleEnabled},
+        {prefs::kCrossDeviceSafetyCheckHomeModuleEnabled,
+         safety_check::prefs::kSafetyCheckHomeModuleEnabled},
+        {prefs::kCrossDeviceTabResumptionHomeModuleEnabled,
+         ntp_tiles::prefs::kTabResumptionHomeModuleEnabled},
+        {prefs::kCrossDeviceTipsHomeModuleEnabled,
+         ntp_tiles::prefs::kTipsHomeModuleEnabled},
+        // keep-sorted end
+    });
+
+// Returns a map of tracked pref names and values corresponding to the "best
+// match" prefs for the Synced Set Up flow to apply.
+std::map<std::string_view, base::Value> GetCrossDevicePrefsFromRemoteDevice(
+    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
+    const syncer::DeviceInfoTracker* device_info_tracker,
+    const syncer::DeviceInfo* local_device);
+
+}  // namespace synced_set_up
+
+}  // namespace sync_preferences
+
+#endif  // COMPONENTS_SYNC_PREFERENCES_SYNCED_SET_UP_UTILS_H_
diff --git a/components/sync_preferences/synced_set_up/utils_unittest.cc b/components/sync_preferences/synced_set_up/utils_unittest.cc
new file mode 100644
index 0000000..5fec722
--- /dev/null
+++ b/components/sync_preferences/synced_set_up/utils_unittest.cc
@@ -0,0 +1,636 @@
+// 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/sync_preferences/synced_set_up/utils.h"
+
+#include <optional>
+#include <string>
+
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "base/values.h"
+#include "components/sync/protocol/sync_enums.pb.h"
+#include "components/sync_device_info/device_info.h"
+#include "components/sync_device_info/device_info_util.h"
+#include "components/sync_device_info/fake_device_info_tracker.h"
+#include "components/sync_preferences/cross_device_pref_tracker/cross_device_pref_tracker.h"
+#include "components/sync_preferences/cross_device_pref_tracker/timestamped_pref_value.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/platform_test.h"
+
+#if BUILDFLAG(IS_ANDROID)
+#include "base/android/scoped_java_ref.h"
+#endif  // BUILDFLAG(IS_ANDROID)
+
+namespace {
+
+// Test implementation of `CrossDevicePrefTracker`.
+class TestCrossDevicePrefTracker
+    : public sync_preferences::CrossDevicePrefTracker {
+ public:
+  TestCrossDevicePrefTracker() = default;
+  ~TestCrossDevicePrefTracker() override = default;
+
+  // `KeyedService` overrides.
+  void Shutdown() override {}
+
+  // `CrossDevicePrefTracker` overrides.
+  void AddObserver(Observer* observer) override {}
+  void RemoveObserver(Observer* observer) override {}
+
+  std::vector<sync_preferences::TimestampedPrefValue> GetValues(
+      std::string_view pref_name,
+      const DeviceFilter& filter) const override {
+    auto it = pref_values_.find(pref_name);
+    if (it == pref_values_.end()) {
+      return {};
+    }
+
+    std::vector<sync_preferences::TimestampedPrefValue> result;
+    for (const auto& timestamped_value : it->second) {
+      sync_preferences::TimestampedPrefValue copied_value =
+          timestamped_value.Clone();
+      result.push_back(std::move(copied_value));
+    }
+    return result;
+  }
+
+  std::optional<sync_preferences::TimestampedPrefValue> GetMostRecentValue(
+      std::string_view pref_name,
+      const DeviceFilter& filter) const override {
+    return std::nullopt;
+  }
+
+  // Testing Method for injecting pref values into the tracker.
+  void AddSyncedPrefValue(std::string_view pref_name,
+                          sync_preferences::TimestampedPrefValue& value) {
+    pref_values_[pref_name].push_back(std::move(value));
+  }
+
+#if BUILDFLAG(IS_ANDROID)
+  base::android::ScopedJavaLocalRef<jobject> GetJavaObject() override {
+    return base::android::ScopedJavaLocalRef<jobject>();
+  }
+
+  base::android::ScopedJavaLocalRef<jobjectArray> GetValues(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jstring>& pref_name,
+      std::optional<int> os_type,
+      std::optional<int> form_factor,
+      std::optional<jlong> max_sync_recency_microseconds) const override {
+    return base::android::ScopedJavaLocalRef<jobjectArray>();
+  }
+
+  base::android::ScopedJavaLocalRef<jobject> GetMostRecentValue(
+      JNIEnv* env,
+      const base::android::JavaParamRef<jstring>& pref_name,
+      std::optional<int> os_type,
+      std::optional<int> form_factor,
+      std::optional<jlong> max_sync_recency_microseconds) const override {
+    return base::android::ScopedJavaLocalRef<jobject>();
+  }
+#endif  // BUILDFLAG(IS_ANDROID)
+
+ private:
+  // Testing member. Map containing TimestampedPrefValues mapped to their
+  // associated pref's name.
+  std::map<std::string_view,
+           std::vector<sync_preferences::TimestampedPrefValue>>
+      pref_values_;
+};
+
+}  // namespace
+
+// Test suite for Synced Set Up utility functions.
+class SyncedSetUpUtilsTest : public PlatformTest {
+ public:
+  // Creates a DeviceInfo object.
+  std::unique_ptr<syncer::DeviceInfo> CreateDeviceInfoForTesting(
+      std::string guid,
+      syncer::DeviceInfo::FormFactor form_factor,
+      syncer::DeviceInfo::OsType os_type,
+      base::Time last_updated_timestamp = base::Time::Now()) {
+    return CreateFakeDeviceInfo(guid, "Device Name", std::nullopt,
+                                sync_pb::SyncEnums::TYPE_UNSET, os_type,
+                                form_factor, "manufacturer", "model",
+                                std::string(), last_updated_timestamp);
+  }
+
+  // Helper for creating a DeviceInfo object.
+  std::unique_ptr<syncer::DeviceInfo> CreateFakeDeviceInfo(
+      const std::string& guid,
+      const std::string& name = "name",
+      const std::optional<syncer::DeviceInfo::SharingInfo>& sharing_info =
+          std::nullopt,
+      sync_pb::SyncEnums_DeviceType device_type =
+          sync_pb::SyncEnums_DeviceType_TYPE_UNSET,
+      syncer::DeviceInfo::OsType os_type = syncer::DeviceInfo::OsType::kUnknown,
+      syncer::DeviceInfo::FormFactor form_factor =
+          syncer::DeviceInfo::FormFactor::kUnknown,
+      const std::string& manufacturer_name = "manufacturer",
+      const std::string& model_name = "model",
+      const std::string& full_hardware_class = std::string(),
+      base::Time last_updated_timestamp = base::Time::Now()) {
+    return std::make_unique<syncer::DeviceInfo>(
+        guid, name, "chrome_version", "user_agent", device_type, os_type,
+        form_factor, "device_id", manufacturer_name, model_name,
+        full_hardware_class, last_updated_timestamp,
+        syncer::DeviceInfoUtil::GetPulseInterval(),
+        /*send_tab_to_self_receiving_enabled=*/
+        false,
+        sync_pb::
+            SyncEnums_SendTabReceivingType_SEND_TAB_RECEIVING_TYPE_CHROME_OR_UNSPECIFIED,
+        sharing_info,
+        /*paask_info=*/std::nullopt,
+        /*fcm_registration_token=*/std::string(),
+        /*interested_data_types=*/syncer::DataTypeSet(),
+        /*auto_sign_out_last_signin_timestamp=*/std::nullopt);
+  }
+
+  // Helper for configuring a TimestampedPrefValue.
+  void ConfigureTimestampedPrefValue(
+      sync_preferences::TimestampedPrefValue& timestamped_value,
+      base::Value value,
+      std::string device_sync_cache_guid,
+      base::Time last_observed_change_time = base::Time::Now()) {
+    timestamped_value.value = value.Clone();
+    timestamped_value.last_observed_change_time = last_observed_change_time;
+    timestamped_value.device_sync_cache_guid = device_sync_cache_guid;
+  }
+
+ protected:
+  base::test::TaskEnvironment task_environment_;
+  TestCrossDevicePrefTracker pref_tracker_;
+  syncer::FakeDeviceInfoTracker device_info_tracker_;
+};
+
+namespace sync_preferences {
+
+// Test that a device with a matching form factor is chosen as the best fit
+// device.
+TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByFormFactor) {
+  // Local device (iOS phone).
+  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
+      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // Android tablet.
+  std::unique_ptr<syncer::DeviceInfo> android_tablet =
+      CreateDeviceInfoForTesting("android_tablet",
+                                 syncer::DeviceInfo::FormFactor::kTablet,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  // Android phone (match).
+  std::unique_ptr<syncer::DeviceInfo> android_phone =
+      CreateDeviceInfoForTesting("android_phone",
+                                 syncer::DeviceInfo::FormFactor::kPhone,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  // iOS tablet.
+  std::unique_ptr<syncer::DeviceInfo> ios_tablet = CreateDeviceInfoForTesting(
+      "ios_tablet", syncer::DeviceInfo::FormFactor::kTablet,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  device_info_tracker_.Add(local_device.get());
+  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
+  device_info_tracker_.Add(android_tablet.get());
+  device_info_tracker_.Add(android_phone.get());
+  device_info_tracker_.Add(ios_tablet.get());
+
+  // Configure some `TimestampedPrefValue` objects associated with the tracked
+  // device GUID's and add them to the pref tracker.
+  TimestampedPrefValue local_device_magic_stack_enabled;
+  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
+                                base::Value(true), local_device.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      local_device_magic_stack_enabled);
+
+  TimestampedPrefValue android_tablet_magic_stack_enabled;
+  TimestampedPrefValue android_tablet_most_visited_enabled;
+  ConfigureTimestampedPrefValue(android_tablet_magic_stack_enabled,
+                                base::Value(true),
+                                android_tablet.get()->guid());
+  ConfigureTimestampedPrefValue(android_tablet_most_visited_enabled,
+                                base::Value(false),
+                                android_tablet.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      android_tablet_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      android_tablet_most_visited_enabled);
+
+  TimestampedPrefValue android_phone_magic_stack_enabled;
+  TimestampedPrefValue android_phone_most_visited_enabled;
+  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
+                                base::Value(false),
+                                android_phone.get()->guid());
+  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
+                                base::Value(true), android_phone.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      android_phone_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      android_phone_most_visited_enabled);
+
+  TimestampedPrefValue ios_tablet_magic_stack_enabled;
+  TimestampedPrefValue ios_tablet_most_visited_enabled;
+  ConfigureTimestampedPrefValue(ios_tablet_magic_stack_enabled,
+                                base::Value(false), ios_tablet.get()->guid());
+  ConfigureTimestampedPrefValue(ios_tablet_most_visited_enabled,
+                                base::Value(false), ios_tablet.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_tablet_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_tablet_most_visited_enabled);
+
+  // Expect that the prefs from the Android phone are returned.
+  std::map<std::string_view, base::Value> expected_result;
+  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+                          android_phone_magic_stack_enabled.value.Clone()});
+  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+                          android_phone_most_visited_enabled.value.Clone()});
+
+  std::map<std::string_view, base::Value> result =
+      synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
+          &pref_tracker_, &device_info_tracker_, local_device.get());
+  ASSERT_TRUE(!result.empty());
+  ASSERT_EQ(result.size(), expected_result.size());
+
+  // Compare the resultant map to the expected map.
+  for (const auto& [pref_name, pref_value] : expected_result) {
+    auto it = result.find(pref_name);
+    ASSERT_NE(it, result.end());
+    EXPECT_EQ(it->second, pref_value);
+  }
+}
+
+// Test that a device with a matching OS is chosen as the best fit device if
+// there is no device with a matching form factor.
+TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByOsType) {
+  // Local device (iOS phone).
+  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
+      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // Android tablet.
+  std::unique_ptr<syncer::DeviceInfo> android_tablet =
+      CreateDeviceInfoForTesting("android_tablet",
+                                 syncer::DeviceInfo::FormFactor::kTablet,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  // iOS tablet (match).
+  std::unique_ptr<syncer::DeviceInfo> ios_tablet = CreateDeviceInfoForTesting(
+      "ios_tablet", syncer::DeviceInfo::FormFactor::kTablet,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  device_info_tracker_.Add(local_device.get());
+  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
+  device_info_tracker_.Add(android_tablet.get());
+  device_info_tracker_.Add(ios_tablet.get());
+
+  // Configure some `TimestampedPrefValue` objects associated with the tracked
+  // device GUID's and add them to the pref tracker.
+  TimestampedPrefValue local_device_magic_stack_enabled;
+  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
+                                base::Value(true), local_device.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      local_device_magic_stack_enabled);
+
+  TimestampedPrefValue android_tablet_magic_stack_enabled;
+  TimestampedPrefValue android_tablet_most_visited_enabled;
+  ConfigureTimestampedPrefValue(android_tablet_magic_stack_enabled,
+                                base::Value(true),
+                                android_tablet.get()->guid());
+  ConfigureTimestampedPrefValue(android_tablet_most_visited_enabled,
+                                base::Value(false),
+                                android_tablet.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      android_tablet_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      android_tablet_most_visited_enabled);
+
+  TimestampedPrefValue ios_tablet_magic_stack_enabled;
+  TimestampedPrefValue ios_tablet_most_visited_enabled;
+  ConfigureTimestampedPrefValue(ios_tablet_magic_stack_enabled,
+                                base::Value(false), ios_tablet.get()->guid());
+  ConfigureTimestampedPrefValue(ios_tablet_most_visited_enabled,
+                                base::Value(false), ios_tablet.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_tablet_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_tablet_most_visited_enabled);
+
+  // Expect that the prefs from the iOS tablet are returned.
+  std::map<std::string_view, base::Value> expected_result;
+  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+                          ios_tablet_magic_stack_enabled.value.Clone()});
+  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+                          ios_tablet_most_visited_enabled.value.Clone()});
+
+  std::map<std::string_view, base::Value> result =
+      synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
+          &pref_tracker_, &device_info_tracker_, local_device.get());
+  ASSERT_TRUE(!result.empty());
+  ASSERT_EQ(result.size(), expected_result.size());
+
+  // compare the returned map to the expected map
+  for (const auto& [pref_name, pref_value] : expected_result) {
+    auto it = result.find(pref_name);
+    ASSERT_NE(it, result.end());
+    EXPECT_EQ(it->second, pref_value);
+  }
+}
+
+// Test that a device with the highest volume of observed pref changes is chosen
+// as the best fit device if the synced devices score the same against the
+// current device on form factor and OS.
+TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByObservedChangeCount) {
+  // Local device (iOS phone).
+  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
+      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // Android phone.
+  std::unique_ptr<syncer::DeviceInfo> android_phone =
+      CreateDeviceInfoForTesting("android_phone",
+                                 syncer::DeviceInfo::FormFactor::kPhone,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  // iOS phone.
+  std::unique_ptr<syncer::DeviceInfo> ios_phone = CreateDeviceInfoForTesting(
+      "ios_phone", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // iOS phone (match).
+  std::unique_ptr<syncer::DeviceInfo> ios_phone_2 = CreateDeviceInfoForTesting(
+      "ios_phone_2", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  device_info_tracker_.Add(local_device.get());
+  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
+  device_info_tracker_.Add(android_phone.get());
+  device_info_tracker_.Add(ios_phone.get());
+  device_info_tracker_.Add(ios_phone_2.get());
+
+  // Configure some `TimestampedPrefValue` objects associated with the tracked
+  // device GUID's and add them to the pref tracker.
+  TimestampedPrefValue local_device_magic_stack_enabled;
+  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
+                                base::Value(true), local_device.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      local_device_magic_stack_enabled);
+
+  TimestampedPrefValue android_phone_magic_stack_enabled;
+  TimestampedPrefValue android_phone_most_visited_enabled;
+  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
+                                base::Value(true), android_phone.get()->guid());
+  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
+                                base::Value(false),
+                                android_phone.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      android_phone_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      android_phone_most_visited_enabled);
+
+  TimestampedPrefValue ios_phone_1_magic_stack_enabled;
+  TimestampedPrefValue ios_phone_1_most_visited_enabled;
+  ConfigureTimestampedPrefValue(ios_phone_1_magic_stack_enabled,
+                                base::Value(false), ios_phone.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_1_most_visited_enabled,
+                                base::Value(false), ios_phone.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_phone_1_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_phone_1_most_visited_enabled);
+
+  TimestampedPrefValue ios_phone_2_magic_stack_enabled;
+  TimestampedPrefValue ios_phone_2_most_visited_enabled;
+  TimestampedPrefValue ios_phone_2_price_tracking_enabled;
+  ConfigureTimestampedPrefValue(ios_phone_2_magic_stack_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_2_most_visited_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_2_price_tracking_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_phone_2_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_phone_2_most_visited_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
+      ios_phone_2_price_tracking_enabled);
+
+  // Expect that the prefs from the second iOS phone with more changes are
+  // returned.
+  std::map<std::string_view, base::Value> expected_result;
+  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+                          ios_phone_2_magic_stack_enabled.value.Clone()});
+  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+                          ios_phone_2_most_visited_enabled.value.Clone()});
+  expected_result.insert({prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
+                          ios_phone_2_price_tracking_enabled.value.Clone()});
+
+  std::map<std::string_view, base::Value> result =
+      synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
+          &pref_tracker_, &device_info_tracker_, local_device.get());
+  ASSERT_TRUE(!result.empty());
+  ASSERT_EQ(result.size(), expected_result.size());
+
+  // Compare the resultant map to the expected map.
+  for (const auto& [pref_name, pref_value] : expected_result) {
+    auto it = result.find(pref_name);
+    ASSERT_NE(it, result.end());
+    EXPECT_EQ(it->second, pref_value);
+  }
+}
+
+// Tests that no new prefs to apply are returned if the local device has a
+// higher volume of observed pref changes than the otherwise best fitting
+// device.
+TEST_F(SyncedSetUpUtilsTest, TestKeepLocalPrefsByChangeActivity) {
+  // Local device (iOS phone).
+  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
+      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // Android phone.
+  std::unique_ptr<syncer::DeviceInfo> android_phone =
+      CreateDeviceInfoForTesting("android_phone",
+                                 syncer::DeviceInfo::FormFactor::kPhone,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  // iOS phone.
+  std::unique_ptr<syncer::DeviceInfo> ios_phone = CreateDeviceInfoForTesting(
+      "ios_phone", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // iOS phone (match).
+  std::unique_ptr<syncer::DeviceInfo> ios_phone_2 = CreateDeviceInfoForTesting(
+      "ios_phone_2", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  device_info_tracker_.Add(local_device.get());
+  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
+  device_info_tracker_.Add(android_phone.get());
+  device_info_tracker_.Add(ios_phone.get());
+  device_info_tracker_.Add(ios_phone_2.get());
+
+  // Configure some `TimestampedPrefValue` objects associated with the tracked
+  // device GUID's and add them to the pref tracker.
+  TimestampedPrefValue local_device_magic_stack_enabled;
+  TimestampedPrefValue local_device_most_visited_enabled;
+  TimestampedPrefValue local_device_price_tracking_enabled;
+  TimestampedPrefValue local_device_safety_check_enabled;
+  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
+                                base::Value(true), local_device.get()->guid());
+  ConfigureTimestampedPrefValue(local_device_most_visited_enabled,
+                                base::Value(true), local_device.get()->guid());
+  ConfigureTimestampedPrefValue(local_device_price_tracking_enabled,
+                                base::Value(true), local_device.get()->guid());
+  ConfigureTimestampedPrefValue(local_device_safety_check_enabled,
+                                base::Value(true), local_device.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      local_device_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      local_device_most_visited_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
+      local_device_price_tracking_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceSafetyCheckHomeModuleEnabled,
+      local_device_safety_check_enabled);
+
+  TimestampedPrefValue android_phone_magic_stack_enabled;
+  TimestampedPrefValue android_phone_most_visited_enabled;
+  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
+                                base::Value(true), android_phone.get()->guid());
+  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
+                                base::Value(false),
+                                android_phone.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      android_phone_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      android_phone_most_visited_enabled);
+
+  TimestampedPrefValue ios_phone_1_magic_stack_enabled;
+  TimestampedPrefValue ios_phone_1_most_visited_enabled;
+  ConfigureTimestampedPrefValue(ios_phone_1_magic_stack_enabled,
+                                base::Value(false), ios_phone.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_1_most_visited_enabled,
+                                base::Value(false), ios_phone.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_phone_1_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_phone_1_most_visited_enabled);
+
+  TimestampedPrefValue ios_phone_2_magic_stack_enabled;
+  TimestampedPrefValue ios_phone_2_most_visited_enabled;
+  TimestampedPrefValue ios_phone_2_price_tracking_enabled;
+  ConfigureTimestampedPrefValue(ios_phone_2_magic_stack_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_2_most_visited_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  ConfigureTimestampedPrefValue(ios_phone_2_price_tracking_enabled,
+                                base::Value(true), ios_phone_2.get()->guid());
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+      ios_phone_2_magic_stack_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
+      ios_phone_2_most_visited_enabled);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
+      ios_phone_2_price_tracking_enabled);
+
+  // Expect that no new prefs are returned.
+  std::map<std::string_view, base::Value> result =
+      synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
+          &pref_tracker_, &device_info_tracker_, local_device.get());
+  EXPECT_TRUE(result.empty());
+}
+
+// Tests that if a pref has multiple observed changes only the most recently
+// observed pref change is retrieved.
+TEST_F(SyncedSetUpUtilsTest, TestReturnsMostRecentObservedPrefChanges) {
+  const base::Time kNow = base::Time::Now();
+
+  // Local device (iOS phone).
+  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
+      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
+      syncer::DeviceInfo::OsType::kIOS);
+
+  // Android phone (match).
+  std::unique_ptr<syncer::DeviceInfo> android_phone =
+      CreateDeviceInfoForTesting("android_phone",
+                                 syncer::DeviceInfo::FormFactor::kPhone,
+                                 syncer::DeviceInfo::OsType::kAndroid);
+
+  device_info_tracker_.Add(local_device.get());
+  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
+  device_info_tracker_.Add(android_phone.get());
+
+  // Configure some `TimestampedPrefValue` objects for the same pref associated
+  // with the Android phone GUID's and add them to the pref tracker. These
+  // represent the same pref being changed several times over a period of time.
+  TimestampedPrefValue magic_stack_enabled_day;
+  TimestampedPrefValue magic_stack_enabled_now;
+  TimestampedPrefValue magic_stack_enabled_week;
+  ConfigureTimestampedPrefValue(magic_stack_enabled_day, base::Value(true),
+                                android_phone.get()->guid(),
+                                kNow - base::Days(1));
+  ConfigureTimestampedPrefValue(magic_stack_enabled_now, base::Value(false),
+                                android_phone.get()->guid(), kNow);
+  ConfigureTimestampedPrefValue(magic_stack_enabled_week, base::Value(true),
+                                android_phone.get()->guid(),
+                                kNow - base::Days(7));
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_day);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_now);
+  pref_tracker_.AddSyncedPrefValue(
+      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_week);
+
+  // Expect that the pref is returned with its most recently set value.
+  std::map<std::string_view, base::Value> expected_result;
+  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
+                          magic_stack_enabled_now.value.Clone()});
+
+  std::map<std::string_view, base::Value> result =
+      synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
+          &pref_tracker_, &device_info_tracker_, local_device.get());
+  ASSERT_TRUE(!result.empty());
+  ASSERT_EQ(result.size(), expected_result.size());
+
+  // Compare the resultant map to the expected map.
+  for (const auto& [pref_name, pref_value] : expected_result) {
+    auto it = result.find(pref_name);
+    ASSERT_NE(it, result.end());
+    EXPECT_EQ(it->second, pref_value);
+  }
+}
+
+}  // namespace sync_preferences
diff --git a/components/test/data/viz/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json b/components/test/data/viz/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
index b7a90dc..352b720 100644
--- a/components/test/data/viz/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
+++ b/components/test/data/viz/render_pass_data/multi_surface_test/youtube_tab_focused/1641.json
@@ -1719,6 +1719,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": true,
@@ -1753,6 +1754,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": false,
@@ -2209,6 +2211,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": true,
@@ -2243,6 +2246,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": false,
@@ -2277,6 +2281,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": true,
@@ -2311,6 +2316,7 @@
                   "green": 0.0,
                   "red": 0.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": false,
@@ -4272,6 +4278,7 @@
                   "green": 1.0,
                   "red": 1.0
                },
+               "is_normalized_coords": true,
                "material": "kTextureContent",
                "nearest_neighbor": false,
                "needs_blending": false,
diff --git a/components/test/data/viz/render_pass_data/top_real_world_desktop/espn_2018/0463.json b/components/test/data/viz/render_pass_data/top_real_world_desktop/espn_2018/0463.json
index a3b5a87a..be692a89 100644
--- a/components/test/data/viz/render_pass_data/top_real_world_desktop/espn_2018/0463.json
+++ b/components/test/data/viz/render_pass_data/top_real_world_desktop/espn_2018/0463.json
@@ -1348,6 +1348,7 @@
             "green": 0.0,
             "red": 0.0
          },
+         "is_normalized_coords": true,
          "material": "kTextureContent",
          "nearest_neighbor": false,
          "needs_blending": true,
@@ -1382,6 +1383,7 @@
             "green": 0.0,
             "red": 0.0
          },
+         "is_normalized_coords": true,
          "material": "kTextureContent",
          "nearest_neighbor": false,
          "needs_blending": false,
diff --git a/components/variations/service/variations_field_trial_creator.cc b/components/variations/service/variations_field_trial_creator.cc
index a82cc344..b7c4f61 100644
--- a/components/variations/service/variations_field_trial_creator.cc
+++ b/components/variations/service/variations_field_trial_creator.cc
@@ -377,9 +377,7 @@
 
   base::FeatureList::SetInstance(std::move(feature_list));
 
-  if (base::FeatureList::IsEnabled(internal::kPurgeVariationsSeedFromMemory)) {
-    GetSeedStore()->AllowToPurgeSeedsDataFromMemory();
-  }
+  GetSeedStore()->AllowToPurgeSeedsDataFromMemory();
 
   // For testing Variations Safe Mode, maybe crash here.
   if (base::FeatureList::IsEnabled(kForceFieldTrialSetupCrashForTesting)) {
diff --git a/components/variations/variations_features.cc b/components/variations/variations_features.cc
index 7dd5b855..ae37c8f 100644
--- a/components/variations/variations_features.cc
+++ b/components/variations/variations_features.cc
@@ -6,6 +6,4 @@
 
 namespace variations::internal {
 
-BASE_FEATURE(kPurgeVariationsSeedFromMemory, base::FEATURE_DISABLED_BY_DEFAULT);
-
 }  // namespace variations::internal
diff --git a/components/variations/variations_features.h b/components/variations/variations_features.h
index 32ff578..c5ef1eb 100644
--- a/components/variations/variations_features.h
+++ b/components/variations/variations_features.h
@@ -11,10 +11,7 @@
 
 namespace variations::internal {
 
-// A feature to allow removing the finch seed data from memory when it is no
-// longer needed.
-COMPONENT_EXPORT(VARIATIONS_FEATURES)
-BASE_DECLARE_FEATURE(kPurgeVariationsSeedFromMemory);
+// Add Variations Features here...
 
 }  // namespace variations::internal
 
diff --git a/components/viz/common/features.h b/components/viz/common/features.h
index 3ddad53..88ea110f 100644
--- a/components/viz/common/features.h
+++ b/components/viz/common/features.h
@@ -115,8 +115,6 @@
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kEnableADPFScrollBoost);
 VIZ_COMMON_EXPORT extern const base::FeatureParam<base::TimeDelta>
     kADPFBoostTimeout;
-VIZ_COMMON_EXPORT extern const base::FeatureParam<double>
-    kADPFMidFrameBoostDurationMultiplier;
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kEnableADPFSeparateRendererMainSession);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kEnableADPFSetThreads);
 VIZ_COMMON_EXPORT BASE_DECLARE_FEATURE(kEnableADPFWorkloadIncreaseOnPageLoad);
diff --git a/components/viz/common/quads/draw_quad_unittest.cc b/components/viz/common/quads/draw_quad_unittest.cc
index ec2dc06..eb3d315 100644
--- a/components/viz/common/quads/draw_quad_unittest.cc
+++ b/components/viz/common/quads/draw_quad_unittest.cc
@@ -35,6 +35,7 @@
 #include "ui/gfx/geometry/rect.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/test/geometry_util.h"
 #include "ui/gfx/geometry/transform.h"
 #include "ui/gfx/hdr_metadata.h"
 #include "ui/gfx/video_types.h"
@@ -327,6 +328,42 @@
   EXPECT_EQ(protected_video_type, copy_quad->protected_video_type);
 }
 
+TEST(DrawQuadTest, TextureDrawQuadNormalization) {
+  gfx::Rect rect(100, 100);
+  bool needs_blending = true;
+  const gfx::RectF uv_rect(0.0f, 0.0f, 1.0f, 1.0f);
+  const gfx::RectF unnormalized_uv_rect(0.0f, 0.0f, 50.0f, 50.0f);
+  const gfx::Size resource_size(100, 50);
+  ResourceId resource_id(1);
+  constexpr float kEpsilon = 1e-5f;
+  SharedQuadState shared_state;
+
+  TextureDrawQuad quad;
+  // Test default (normalized = true)
+  quad.SetNew(&shared_state, rect, rect, needs_blending, resource_id,
+              uv_rect.origin(), uv_rect.bottom_right(), SkColors::kTransparent,
+              false, false, gfx::ProtectedVideoType::kClear,
+              /*is_tex_coords_normalized=*/true);
+
+  EXPECT_RECTF_NEAR(uv_rect, quad.GetNormalizedTexCoords(resource_size),
+                    kEpsilon);
+  EXPECT_RECTF_NEAR(gfx::ScaleRect(uv_rect, 100.f, 50.f),
+                    quad.GetUnnormalizedTexCoords(resource_size), kEpsilon);
+
+  // Test unnormalized (normalized = false)
+  quad.SetNew(&shared_state, rect, rect, needs_blending, resource_id,
+              unnormalized_uv_rect.origin(),
+              unnormalized_uv_rect.bottom_right(), SkColors::kTransparent,
+              false, false, gfx::ProtectedVideoType::kClear,
+              /*is_tex_coords_normalized=*/false);
+
+  EXPECT_RECTF_NEAR(
+      gfx::ScaleRect(unnormalized_uv_rect, 1.f / 100.f, 1.f / 50.f),
+      quad.GetNormalizedTexCoords(resource_size), kEpsilon);
+  EXPECT_RECTF_NEAR(unnormalized_uv_rect,
+                    quad.GetUnnormalizedTexCoords(resource_size), kEpsilon);
+}
+
 TEST(DrawQuadTest, CopyTileDrawQuad) {
   gfx::Rect visible_rect(40, 50, 30, 20);
   bool blending = true;
diff --git a/components/viz/common/quads/render_pass_io.cc b/components/viz/common/quads/render_pass_io.cc
index f1a3e272..e3663f6 100644
--- a/components/viz/common/quads/render_pass_io.cc
+++ b/components/viz/common/quads/render_pass_io.cc
@@ -1255,6 +1255,7 @@
   // data.
   dict->Set("premultiplied_alpha", true);
   dict->Set("tex_coord_rect", RectFToDict(draw_quad->tex_coord_rect_));
+  dict->Set("is_normalized_coords", draw_quad->is_normalized_coords);
   dict->Set("background_color", SkColor4fToDict(draw_quad->background_color));
   // TODO(crbug.com/40942150): Update
   // "components/test/data/viz/render_pass_data/" to reflect the deprecation of
@@ -1448,6 +1449,8 @@
   const base::Value::Dict* damage_rect = dict.FindDict("damage_rect");
   std::optional<bool> nearest_neighbor = dict.FindBool("nearest_neighbor");
   std::optional<bool> secure_output_only = dict.FindBool("secure_output_only");
+  std::optional<bool> is_normalized_coords =
+      dict.FindBool("is_normalized_coords");
   const std::string* protected_video_type =
       dict.FindString("protected_video_type");
 
@@ -1472,7 +1475,8 @@
       common.needs_blending, resource_id, t_tex_coord_rect.origin(),
       t_tex_coord_rect.bottom_right(), t_background_color,
       nearest_neighbor.value(), secure_output_only.value(),
-      static_cast<gfx::ProtectedVideoType>(protected_video_type_index));
+      static_cast<gfx::ProtectedVideoType>(protected_video_type_index),
+      is_normalized_coords.value_or(true));
 
   gfx::Rect t_damage_rect;
   if (damage_rect && RectFromDict(*damage_rect, &t_damage_rect)) {
diff --git a/components/viz/common/quads/texture_draw_quad.cc b/components/viz/common/quads/texture_draw_quad.cc
index 9a16f504..8f224fc 100644
--- a/components/viz/common/quads/texture_draw_quad.cc
+++ b/components/viz/common/quads/texture_draw_quad.cc
@@ -41,7 +41,8 @@
                              SkColor4f background,
                              bool nearest,
                              bool secure_output,
-                             gfx::ProtectedVideoType video_type) {
+                             gfx::ProtectedVideoType video_type,
+                             bool is_tex_coords_normalized) {
   CHECK_NE(resource, kInvalidResourceId);
   this->needs_blending = needs_blending;
   DrawQuad::SetAll(shared_quad_state, DrawQuad::Material::kTextureContent, rect,
@@ -52,6 +53,7 @@
   nearest_neighbor = nearest;
   secure_output_only = secure_output;
   protected_video_type = video_type;
+  is_normalized_coords = is_tex_coords_normalized;
 }
 
 void TextureDrawQuad::SetAll(const SharedQuadState* shared_quad_state,
@@ -64,7 +66,8 @@
                              SkColor4f background,
                              bool nearest,
                              bool secure_output,
-                             gfx::ProtectedVideoType video_type) {
+                             gfx::ProtectedVideoType video_type,
+                             bool is_tex_coords_normalized) {
   CHECK_NE(resource, kInvalidResourceId);
   DrawQuad::SetAll(shared_quad_state, DrawQuad::Material::kTextureContent, rect,
                    visible_rect, needs_blending);
@@ -74,6 +77,7 @@
   nearest_neighbor = nearest;
   secure_output_only = secure_output;
   protected_video_type = video_type;
+  is_normalized_coords = is_tex_coords_normalized;
 }
 
 const TextureDrawQuad* TextureDrawQuad::MaterialCast(const DrawQuad* quad) {
@@ -90,6 +94,7 @@
   value->SetBoolean("secure_output_only", secure_output_only);
   value->SetBoolean("is_video_frame", is_video_frame);
   value->SetBoolean("force_rgbx", force_rgbx);
+  value->SetBoolean("is_normalized_coords", is_normalized_coords);
   value->SetInteger("protected_video_type",
                     static_cast<int>(protected_video_type));
   value->SetInteger("overlay_priority_hint",
diff --git a/components/viz/common/quads/texture_draw_quad.h b/components/viz/common/quads/texture_draw_quad.h
index aa538d86..af90c792 100644
--- a/components/viz/common/quads/texture_draw_quad.h
+++ b/components/viz/common/quads/texture_draw_quad.h
@@ -49,7 +49,8 @@
               SkColor4f background,
               bool nearest,
               bool secure_output,
-              gfx::ProtectedVideoType video_type);
+              gfx::ProtectedVideoType video_type,
+              bool is_tex_coords_normalized = true);
 
   void SetAll(const SharedQuadState* shared_quad_state,
               const gfx::Rect& rect,
@@ -61,25 +62,31 @@
               SkColor4f background,
               bool nearest,
               bool secure_output,
-              gfx::ProtectedVideoType video_type);
+              gfx::ProtectedVideoType video_type,
+              bool is_tex_coords_normalized = true);
 
   // Returns the texture coordinates in the range [0, 1].
   gfx::RectF GetNormalizedTexCoords(const gfx::Size& resource_size) const {
-    // TODO(crbug.com/451876192): This parameter is currently unused because
-    // tex_coord_rect_ is always normalized. It is included here to prepare for
-    // the next CL where tex_coord_rect_ may be unnormalized, requiring
-    // resource_size to perform the normalization.
-    return tex_coord_rect_;
+    if (is_normalized_coords) {
+      return tex_coord_rect_;
+    }
+
+    if (resource_size.IsEmpty()) {
+      return gfx::RectF();
+    }
+
+    return gfx::ScaleRect(tex_coord_rect_, 1.0f / resource_size.width(),
+                          1.0f / resource_size.height());
   }
 
   // Returns the texture coordinates in the range [0, resource_size].
   gfx::RectF GetUnnormalizedTexCoords(const gfx::Size& resource_size) const {
-    // tex_coord_rect_ is currently always normalized, so we must scale it.
-    // In the future, if the internal storage becomes unnormalized, this will
-    // simply return tex_coord_rect_ directly.
-    return gfx::ScaleRect(tex_coord_rect_,
-                          static_cast<float>(resource_size.width()),
-                          static_cast<float>(resource_size.height()));
+    if (is_normalized_coords) {
+      return gfx::ScaleRect(tex_coord_rect_,
+                            static_cast<float>(resource_size.width()),
+                            static_cast<float>(resource_size.height()));
+    }
+    return tex_coord_rect_;
   }
 
   // Sets the texture coordinates in the range [0, 1].
@@ -90,6 +97,7 @@
     // for the future CL where we will need to scale the input `normalized_rect`
     // by `resource_size` to store it as unnormalized coordinates.
     tex_coord_rect_ = normalized_rect;
+    is_normalized_coords = true;
   }
 
   SkColor4f background_color = SkColors::kTransparent;
@@ -173,6 +181,10 @@
 
   gfx::RectF tex_coord_rect_;
 
+  // Indicates whether the texture coordinates are normalized (in [0, 1] range)
+  // or unnormalized (in [0, resource_size] range).
+  bool is_normalized_coords = true;
+
   void ExtendValue(base::trace_event::TracedValue* value) const override;
 };
 
diff --git a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc
index 16bdc669..47f3117 100644
--- a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc
+++ b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.cc
@@ -129,6 +129,12 @@
              : nullptr;
 }
 
+bool IwaKeyDistributionInfoProvider::IsBundleBlocklisted(
+    std::string_view web_bundle_id) const {
+  return component_ &&
+         base::Contains(component_->data.blocklist, web_bundle_id);
+}
+
 bool IwaKeyDistributionInfoProvider::IsManagedInstallPermitted(
     std::string_view web_bundle_id) const {
   if (skip_managed_checks_for_testing_) {
@@ -307,14 +313,18 @@
   }
 
   IwaKeyDistributionInfoProvider::ManagedAllowlist managed_allowlist;
+  IwaKeyDistributionInfoProvider::Blocklist blocklist;
   if (key_distribution.has_iwa_access_control()) {
     managed_allowlist = base::MakeFlatSet<std::string>(
         key_distribution.iwa_access_control().managed_allowlist(), /*comp=*/{},
         /*proj=*/[](const auto& pair) { return pair.first; });
+    blocklist = base::MakeFlatSet<std::string>(
+        key_distribution.iwa_access_control().blocklist(), /*comp=*/{},
+        /*proj=*/[](const auto& pair) { return pair.first; });
   }
 
   return Data(std::move(key_rotations), std::move(special_app_permissions),
-              std::move(managed_allowlist));
+              std::move(managed_allowlist), std::move(blocklist));
 }
 
 void IwaKeyDistributionInfoProvider::AddObserver(Observer* observer) {
@@ -386,9 +396,16 @@
     }
   }
   if (component_) {
+    // Component meta data
     debug_data.Set("component_version", component_->version.GetString());
+    if (component_->is_preloaded) {
+      debug_data.Set("is_preloaded", true);
+    }
+    // Per bundle_id permissions/prohibitions
     debug_data.Set("managed_allowlist",
                    base::ToValueList(component_->data.managed_allowlist));
+    debug_data.Set("blocklist", base::ToValueList(component_->data.blocklist));
+
     auto* key_rotations = debug_data.EnsureDict("key_rotations");
     for (const auto& [web_bundle_id, kr_info] :
          component_->data.key_rotations) {
@@ -400,10 +417,6 @@
          component_->data.special_app_permissions) {
       app_permissions->Set(web_bundle_id, app_permissions_info.AsDebugValue());
     }
-
-    if (component_->is_preloaded) {
-      debug_data.Set("is_preloaded", true);
-    }
   } else {
     debug_data.Set("component_version", "null");
   }
@@ -493,10 +506,12 @@
 IwaKeyDistributionInfoProvider::Data::Data(
     KeyRotations key_rotations,
     SpecialAppPermissions special_app_permissions,
-    ManagedAllowlist managed_allowlist)
+    ManagedAllowlist managed_allowlist,
+    Blocklist blocklist)
     : key_rotations(std::move(key_rotations)),
       special_app_permissions(std::move(special_app_permissions)),
-      managed_allowlist(std::move(managed_allowlist)) {}
+      managed_allowlist(std::move(managed_allowlist)),
+      blocklist(std::move(blocklist)) {}
 IwaKeyDistributionInfoProvider::Data::~Data() = default;
 IwaKeyDistributionInfoProvider::Data::Data(const Data&) = default;
 
diff --git a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h
index 489928c..d550776d 100644
--- a/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h
+++ b/components/webapps/isolated_web_apps/iwa_key_distribution_info_provider.h
@@ -49,6 +49,7 @@
   using KeyRotations =
       base::flat_map<std::string, IwaRuntimeDataProvider::KeyRotationInfo>;
   using ManagedAllowlist = base::flat_set<std::string>;
+  using Blocklist = base::flat_set<std::string>;
   using SpecialAppPermissions =
       base::flat_map<std::string, SpecialAppPermissionsInfo>;
 
@@ -92,6 +93,10 @@
   std::vector<std::string> GetSkipMultiCaptureNotificationBundleIds() const;
   std::optional<base::Version> GetVersion() const;
 
+  // All installations of blocklisted bundles are removed from the device.
+  // Installation is prevented.
+  bool IsBundleBlocklisted(std::string_view web_bundle_id) const;
+
   // Only bundles present in the managed allowlist can be installed and updated.
   bool IsManagedInstallPermitted(std::string_view web_bundle_id) const;
   bool IsManagedUpdatePermitted(std::string_view web_bundle_id) const;
@@ -138,14 +143,15 @@
   struct Data {
     Data(KeyRotations key_rotations,
          SpecialAppPermissions special_app_permissions,
-         ManagedAllowlist managed_allowlist);
+         ManagedAllowlist managed_allowlist,
+         Blocklist blocklist);
     ~Data();
     Data(const Data&);
 
     KeyRotations key_rotations;
     SpecialAppPermissions special_app_permissions;
     ManagedAllowlist managed_allowlist;
-    // TODO(crbug.com/432446316): Implement the blocklist
+    Blocklist blocklist;
   };
 
   struct Component {
diff --git a/content/browser/android/content_feature_map.cc b/content/browser/android/content_feature_map.cc
index 293f967d..392295af2 100644
--- a/content/browser/android/content_feature_map.cc
+++ b/content/browser/android/content_feature_map.cc
@@ -31,6 +31,7 @@
     &features::kAndroidCaptureKeyEvents,
     &features::kAndroidCaretBrowsing,
     &features::kAndroidDevToolsFrontend,
+    &features::kAccessibilityCheckJavaNodeCacheFreshness,
     &features::kAccessibilityDeprecateJavaNodeCache,
     &features::kAccessibilityDeprecateTypeAnnounce,
     &features::kAccessibilityImproveLiveRegionAnnounce,
diff --git a/content/browser/attribution_reporting/attribution_report_network_sender.cc b/content/browser/attribution_reporting/attribution_report_network_sender.cc
index 1036c96..b3f05e9 100644
--- a/content/browser/attribution_reporting/attribution_report_network_sender.cc
+++ b/content/browser/attribution_reporting/attribution_report_network_sender.cc
@@ -78,20 +78,6 @@
   GURL url = report.ReportURL(is_debug_report);
   std::string body = SerializeAttributionJson(report.ReportBody());
 
-  if (!is_debug_report) {
-    switch (report.GetReportType()) {
-      case AttributionReport::Type::kEventLevel:
-        base::UmaHistogramCounts1000(
-            "Conversions.EventLevelReport.ReportBodySize", body.size());
-        break;
-      case AttributionReport::Type::kAggregatableAttribution:
-      case AttributionReport::Type::kNullAggregatable:
-        base::UmaHistogramCounts10000(
-            "Conversions.AggregatableReport.ReportBodySize", body.size());
-        break;
-    }
-  }
-
   url::Origin origin(report.reporting_origin());
   SendReport(std::move(url), std::move(origin), std::move(body),
              base::BindOnce(&AttributionReportNetworkSender::OnReportSent,
diff --git a/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc b/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc
index 4b2c1d7..ad61e1f5 100644
--- a/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc
+++ b/content/browser/attribution_reporting/attribution_report_network_sender_unittest.cc
@@ -514,8 +514,6 @@
        EventLevelReportSent_MetricsRecorded) {
   static constexpr char kErrorCodeMetric[] =
       "Conversions.HttpResponseOrNetErrorCodeEventLevel";
-  static constexpr char kReportSizeMetric[] =
-      "Conversions.EventLevelReport.ReportBodySize";
 
   // All OK
   {
@@ -526,7 +524,6 @@
     EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
         kEventLevelReportUrl, ""));
     histograms.ExpectUniqueSample(kErrorCodeMetric, net::HTTP_OK, 1);
-    histograms.ExpectTotalCount(kReportSizeMetric, 1);
   }
 
   // Internal error
@@ -540,7 +537,6 @@
         GURL(kEventLevelReportUrl), completion_status,
         network::mojom::URLResponseHead::New(), ""));
     histograms.ExpectUniqueSample(kErrorCodeMetric, net::ERR_FAILED, 1);
-    histograms.ExpectTotalCount(kReportSizeMetric, 1);
   }
   // External error
   {
@@ -551,7 +547,6 @@
     EXPECT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
         kEventLevelReportUrl, "", net::HTTP_UNAUTHORIZED));
     histograms.ExpectUniqueSample(kErrorCodeMetric, net::HTTP_UNAUTHORIZED, 1);
-    histograms.ExpectTotalCount(kReportSizeMetric, 1);
   }
   // Retried network change error
   {
@@ -567,8 +562,6 @@
 
     ASSERT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
         kEventLevelReportUrl, ""));
-
-    histograms.ExpectTotalCount(kReportSizeMetric, 1);
   }
 }
 
@@ -649,8 +642,6 @@
 
   static constexpr char kErrorCodeMetric[] =
       "HttpResponseOrNetErrorCodeAggregatable2";
-  static constexpr char kReportSizeMetric[] =
-      "Conversions.AggregatableReport.ReportBodySize";
 
   for (const bool has_trigger_context_id : {false, true}) {
     SCOPED_TRACE(has_trigger_context_id);
@@ -670,7 +661,6 @@
           kAggregatableReportUrl, ""));
       verify_histogram(histograms, kErrorCodeMetric, has_trigger_context_id,
                        net::HTTP_OK, 1);
-      histograms.ExpectTotalCount(kReportSizeMetric, 1);
     }
 
     // Internal error
@@ -685,7 +675,6 @@
           network::mojom::URLResponseHead::New(), ""));
       verify_histogram(histograms, kErrorCodeMetric, has_trigger_context_id,
                        net::ERR_FAILED, 1);
-      histograms.ExpectTotalCount(kReportSizeMetric, 1);
     }
     // External error
     {
@@ -697,7 +686,6 @@
           kAggregatableReportUrl, "", net::HTTP_UNAUTHORIZED));
       verify_histogram(histograms, kErrorCodeMetric, has_trigger_context_id,
                        net::HTTP_UNAUTHORIZED, 1);
-      histograms.ExpectTotalCount(kReportSizeMetric, 1);
     }
     // Retried network change error
     {
@@ -713,8 +701,6 @@
 
       ASSERT_TRUE(test_url_loader_factory_.SimulateResponseForPendingRequest(
           kAggregatableReportUrl, ""));
-
-      histograms.ExpectTotalCount(kReportSizeMetric, 1);
     }
   }
 }
@@ -958,8 +944,6 @@
         kAggregatableReportUrl, ""));
     verify_histogram(histograms, "HttpResponseOrNetErrorCodeAggregatable2",
                      has_trigger_context_id, net::HTTP_OK, 1);
-    histograms.ExpectTotalCount("Conversions.AggregatableReport.ReportBodySize",
-                                1);
   }
 }
 
diff --git a/content/browser/code_cache/generated_code_cache_context.cc b/content/browser/code_cache/generated_code_cache_context.cc
index b137331..113e7cb 100644
--- a/content/browser/code_cache/generated_code_cache_context.cc
+++ b/content/browser/code_cache/generated_code_cache_context.cc
@@ -151,10 +151,13 @@
   } else {
 #if !BUILDFLAG(IS_FUCHSIA)
     // Target the same amount of disk space used for persistent_cache as is used
-    // for disk_cache.
-    int64_t disk_cache_max_size = disk_cache::PreferredCacheSize(
-        base::SysInfo::AmountOfFreeDiskSpace(path).value_or(-1),
-        net::GENERATED_BYTE_CODE_CACHE);
+    // for disk_cache or use `max_bytes` if provided.
+    int64_t disk_cache_max_size =
+        max_bytes > 0
+            ? max_bytes
+            : disk_cache::PreferredCacheSize(
+                  base::SysInfo::AmountOfFreeDiskSpace(path).value_or(-1),
+                  net::GENERATED_BYTE_CODE_CACHE);
 
     persistent_cache_collection_ = {
         new persistent_cache::PersistentCacheCollection(
diff --git a/content/browser/devtools/protocol/target_handler.cc b/content/browser/devtools/protocol/target_handler.cc
index 0f9fe4e..86ec64f7 100644
--- a/content/browser/devtools/protocol/target_handler.cc
+++ b/content/browser/devtools/protocol/target_handler.cc
@@ -229,6 +229,8 @@
 
     base::Value::Dict add_binding_params;
     add_binding_params.Set("name", binding_name);
+    // Expose to the default execution context only.
+    add_binding_params.Set("executionContextName", "");
     SendProtocolMessageToPage("Runtime.addBinding",
                               base::Value(std::move(add_binding_params)));
 
@@ -236,14 +238,13 @@
         base::StringPrintf(kInitializerScript, binding_name.c_str());
 
     base::Value::Dict params;
-    params.Set("scriptSource", initializer_script);
-    SendProtocolMessageToPage("Page.addScriptToEvaluateOnLoad",
+    params.Set("source", initializer_script);
+    params.Set("worldName", "");
+    // Run the initializer script immediately on the current page. This is
+    // needed to expose the binding to the current page.
+    params.Set("runImmediately", true);
+    pending_request_id_ = SendProtocolMessageToPage("Page.addScriptToEvaluateOnNewDocument",
                               base::Value(std::move(params)));
-
-    base::Value::Dict evaluate_params;
-    evaluate_params.Set("expression", initializer_script);
-    pending_request_id_ = SendProtocolMessageToPage(
-        "Runtime.evaluate", base::Value(std::move(evaluate_params)));
     GetInstanceMap()[page_host_.get()].reset(this);
   }
 
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java
index bc9c791e..f6f9d971 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityHistogramRecorder.java
@@ -13,6 +13,7 @@
 import org.chromium.base.TraceEvent;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.build.annotations.NullMarked;
+import org.chromium.content_public.browser.ContentFeatureList;
 import org.chromium.ui.accessibility.AccessibilityState;
 
 /** Helper class for recording UMA histograms of accessibility events */
@@ -139,6 +140,9 @@
     public static final String CACHE_PERCENTAGE_RETRIEVED_FROM_CACHE_HISTOGRAM =
             "Accessibility.Android.Cache.PercentageRetrievedFromCache";
 
+    private static final String CACHE_PERCENTAGE_FRESH_HISTOGRAM =
+            "Accessibility.Android.Cache.PercentageFreshInCache";
+
     private static final int CACHE_MAX_NODES_MIN_BUCKET = 1;
     private static final int CACHE_MAX_NODES_MAX_BUCKET = 3000;
     private static final int CACHE_MAX_NODES_BUCKET_COUNT = 100;
@@ -153,6 +157,7 @@
     private int mMaxNodesInCache;
     private int mNodeWasReturnedFromCache;
     private int mNodeWasCreatedFromScratch;
+    private int mNodeWasFreshInCache;
 
     // These track the usage in time when a web contents is in the foreground.
     private long mTimeOfFirstShown = -1;
@@ -271,6 +276,11 @@
         mNodeWasCreatedFromScratch++;
     }
 
+    /** Increment the count of instances when a node was fresh in cache. */
+    public void incrementNodeWasFreshInCache() {
+        mNodeWasFreshInCache++;
+    }
+
     /** Set the time this instance was shown to the current time in ms. */
     public void updateTimeOfFirstShown() {
         mTimeOfFirstShown = SystemClock.elapsedRealtime();
@@ -315,6 +325,15 @@
         recordTotalTimeCreateAccessibilityNodeInfoHistogram();
     }
 
+    /**
+     * Calculates what percentage of {@code total} {@code count} is, expressed as an integer
+     * percentage truncated down. {@code total} must not be zero.
+     */
+    private static int computeIntegerPercent(int count, int total) {
+        // Cast to long to account for overflow
+        return (int) ((count * 100L) / total);
+    }
+
     /** Record UMA histograms for the event counts for the OnDemand feature. */
     public void recordEventsHistograms() {
         // There are only 2 AXModes, kAXModeComplete is used when a complex service is active.
@@ -324,7 +343,7 @@
         // If we did not enqueue any events, we can ignore the data as a trivial case.
         if (mTotalEnqueuedEvents > 0) {
             // Log the percentage dropped (dispatching 0 events should be 100% dropped).
-            int percentSent = (int) (mTotalDispatchedEvents * 1.0 / mTotalEnqueuedEvents * 100.0);
+            int percentSent = computeIntegerPercent(mTotalDispatchedEvents, mTotalEnqueuedEvents);
             RecordHistogram.recordPercentageHistogram(
                     PERCENTAGE_DROPPED_HISTOGRAM, 100 - percentSent);
             RecordHistogram.recordPercentageHistogram(
@@ -381,15 +400,24 @@
                 CACHE_MAX_NODES_BUCKET_COUNT);
 
         int totalNodeRequests = mNodeWasReturnedFromCache + mNodeWasCreatedFromScratch;
-        int percentFromCache = (int) (mNodeWasReturnedFromCache * 1.0 / totalNodeRequests * 100.0);
+        if (totalNodeRequests > 0) {
+            RecordHistogram.recordPercentageHistogram(
+                    CACHE_PERCENTAGE_RETRIEVED_FROM_CACHE_HISTOGRAM,
+                    computeIntegerPercent(mNodeWasReturnedFromCache, totalNodeRequests));
 
-        RecordHistogram.recordPercentageHistogram(
-                CACHE_PERCENTAGE_RETRIEVED_FROM_CACHE_HISTOGRAM, percentFromCache);
+            if (mNodeWasReturnedFromCache > 0
+                    && ContentFeatureList.enabledAccessibilityCheckJavaNodeCacheFreshness()) {
+                RecordHistogram.recordPercentageHistogram(
+                        CACHE_PERCENTAGE_FRESH_HISTOGRAM,
+                        computeIntegerPercent(mNodeWasFreshInCache, mNodeWasReturnedFromCache));
+            }
+        }
 
         // Reset counters.
         mMaxNodesInCache = 0;
         mNodeWasReturnedFromCache = 0;
         mNodeWasCreatedFromScratch = 0;
+        mNodeWasFreshInCache = 0;
     }
 
     /** Record UMA histograms for the usage timers of the native accessibility engine. */
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
index 64967e1..66678454 100644
--- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
+++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -66,7 +66,9 @@
 import android.content.ReceiverCallNotAllowedException;
 import android.graphics.Rect;
 import android.graphics.RectF;
+import android.os.Build;
 import android.os.Bundle;
+import android.os.Parcel;
 import android.util.SparseArray;
 import android.view.MotionEvent;
 import android.view.View;
@@ -80,6 +82,7 @@
 import android.view.autofill.AutofillManager;
 import android.view.inputmethod.EditorInfo;
 
+import androidx.annotation.RequiresApi;
 import androidx.annotation.VisibleForTesting;
 import androidx.core.view.accessibility.AccessibilityNodeInfoCompat;
 import androidx.core.view.accessibility.AccessibilityNodeProviderCompat;
@@ -121,6 +124,7 @@
 import org.chromium.ui.base.WindowAndroid;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -989,6 +993,43 @@
         mImageDataRequestedNodes.remove(virtualViewId);
     }
 
+    /**
+     * Deep equality check of two {@link AccessibilityNodeInfoCompat} nodes.
+     *
+     * <p>Requires API level 33 (Tiramisu) for deprecation of {@link
+     * AccessibilityNodeInfo.recycle()}, prior to which the serialization used by this check was
+     * destructive.
+     *
+     * @return true if both are null or both are non-null and have all fields equal.
+     */
+    @RequiresApi(Build.VERSION_CODES.TIRAMISU)
+    private boolean nodesAreEqual(
+            @Nullable AccessibilityNodeInfoCompat a, @Nullable AccessibilityNodeInfoCompat b) {
+        if (a == null && b == null) return true;
+        if (a == null || b == null) return false;
+
+        // Checks only ANICompat fields not stored in ANI or Extras bundle
+        if (!a.equals(b)) return false;
+
+        // Parcel serialization gets all fields, including IDs for parent, child, labeled-by, and
+        // traversal before & after nodes which would otherwise only be accessible on sealed nodes
+        // and which create unnecessary AccessibilityNodeInfoCompat objects in their public
+        // accessors. In particular, the Extras bundle where ANICompat stores fields not in the base
+        // ANI object is also serialized by ANI.writeToParcel(), and the relevant fields of the
+        // wrapper types AccessibilityActionCompat, CollectionInfoCompat, CollectionItemInfoCompat,
+        // RangeInfoCompat, and TouchDelegateInfoCompat are also serialized.
+        //
+        // Though the AccessibilityNodeInfo parcel format is not guaranteed to be stable, it should
+        // be consistently-ordered within a single run of the same build of Chrome (some fields are
+        // ArrayMaps of objects, but ArrayMap is sorted by hash code, and hash codes of equal
+        // objects should be equal in the same program run).
+        Parcel aParcel = Parcel.obtain();
+        a.unwrap().writeToParcel(aParcel, 0);
+        Parcel bParcel = Parcel.obtain();
+        b.unwrap().writeToParcel(bParcel, 0);
+        return Arrays.equals(aParcel.marshall(), bParcel.marshall());
+    }
+
     @Override
     public @Nullable AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) {
         if (!isAccessibilityEnabled()) {
@@ -1039,6 +1080,26 @@
 
                 mHistogramRecorder.incrementNodeWasReturnedFromCache();
                 mHistogramRecorder.endAccessibilityNodeInfoConstruction();
+
+                // Check cache freshness by drawing from C++ (Finch experiment).
+                if (ContentFeatureList.enabledAccessibilityCheckJavaNodeCacheFreshness()) {
+                    final AccessibilityNodeInfoCompat freshNode =
+                            AccessibilityNodeInfoCompat.obtain(mView);
+                    freshNode.setPackageName(mContext.getPackageName());
+                    freshNode.setSource(mView, virtualViewId);
+
+                    if (virtualViewId == mCurrentRootId) {
+                        freshNode.setParent(mView);
+                    }
+
+                    if (WebContentsAccessibilityImplJni.get()
+                            .populateAccessibilityNodeInfo(mNativeObj, freshNode, virtualViewId)) {
+                        if (nodesAreEqual(cachedNode, freshNode)) {
+                            mHistogramRecorder.incrementNodeWasFreshInCache();
+                        }
+                    } // If node is still in the cache when it's not in C++, treat as stale
+                }
+
                 return cachedNode;
             } else {
                 // If the node is no longer valid, wipe it from the cache and return null
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
index 2352206..df1eb32a 100644
--- a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
+++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
@@ -4,6 +4,8 @@
 
 package org.chromium.content_public.browser;
 
+import android.os.Build;
+
 import org.chromium.base.MutableBooleanParamWithSafeDefault;
 import org.chromium.base.MutableFlagWithSafeDefault;
 import org.chromium.base.MutableIntParamWithSafeDefault;
@@ -75,6 +77,21 @@
 
     public static final String DIPS_TTL = "DIPSTtl";
 
+    private static final MutableFlagWithSafeDefault sAccessibilityCheckJavaNodeCacheFreshness =
+            new MutableFlagWithSafeDefault(
+                    ContentFeatureMap.getInstance(),
+                    ContentFeatures.ACCESSIBILITY_CHECK_JAVA_NODE_CACHE_FRESHNESS,
+                    false);
+
+    /**
+     * Checks "AccessibilityCheckJavaNodeCacheFreshness" feature flag, including that current
+     * environment is at least required Android SDK 33 (Tiramisu).
+     */
+    public static boolean enabledAccessibilityCheckJavaNodeCacheFreshness() {
+        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
+                && sAccessibilityCheckJavaNodeCacheFreshness.isEnabled();
+    }
+
     public static final MutableFlagWithSafeDefault sAccessibilityDeprecateJavaNodeCache =
             new MutableFlagWithSafeDefault(
                     ContentFeatureMap.getInstance(),
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
index d174ee7c..5bc5068 100644
--- a/content/public/common/content_features.cc
+++ b/content/public/common/content_features.cc
@@ -1215,6 +1215,11 @@
 BASE_FEATURE(kWebPermissionsApi, base::FEATURE_ENABLED_BY_DEFAULT);
 
 #if BUILDFLAG(IS_ANDROID)
+// When enabled, will unconditionally poll the C++ cache to check Java node
+// cache freshness to test correctness of Java node cache.
+BASE_FEATURE(kAccessibilityCheckJavaNodeCacheFreshness,
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 BASE_FEATURE(kAccessibilityDeprecateJavaNodeCache,
              base::FEATURE_DISABLED_BY_DEFAULT);
 
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h
index ec92700..11ec5cd5 100644
--- a/content/public/common/content_features.h
+++ b/content/public/common/content_features.h
@@ -328,6 +328,7 @@
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebPermissionsApi);
 
 #if BUILDFLAG(IS_ANDROID)
+CONTENT_EXPORT BASE_DECLARE_FEATURE(kAccessibilityCheckJavaNodeCacheFreshness);
 CONTENT_EXPORT BASE_DECLARE_FEATURE(kAccessibilityDeprecateJavaNodeCache);
 CONTENT_EXPORT extern const base::FeatureParam<bool>
     kAccessibilityDeprecateJavaNodeCacheOptimizeScroll;
diff --git a/content/public/test/OWNERS b/content/public/test/OWNERS
index fee98041..8e284ea 100644
--- a/content/public/test/OWNERS
+++ b/content/public/test/OWNERS
@@ -53,6 +53,7 @@
 
 # For browsing data changes.
 per-file browsing_data_remover_test_util.*=file://content/browser/browsing_data/OWNERS
+per-file mock_browsing_data_remover_delegate.*=file://content/browser/browsing_data/OWNERS
 
 # For Captured Surface Control.
 per-file *captured_surface_controller*=eladalon@chromium.org
diff --git a/content/renderer/gpu_benchmarking_extension.cc b/content/renderer/gpu_benchmarking_extension.cc
index 1165857..a1d6a34 100644
--- a/content/renderer/gpu_benchmarking_extension.cc
+++ b/content/renderer/gpu_benchmarking_extension.cc
@@ -190,7 +190,7 @@
       DCHECK(file.isValid());
 
       SkSerialProcs procs{
-          .fImageProc = [](SkImage* img, void*) -> sk_sp<SkData> {
+          .fImageProc = [](SkImage* img, void*) -> SkSerialReturnType {
             // Note: if the picture contains texture-backed (gpu) images, they
             // will fail to be read-back and therefore fail to be encoded unless
             // we can thread the correct GrDirectContext through to here.
diff --git a/docs/privacy_budget/DIR_METADATA b/docs/privacy_budget/DIR_METADATA
deleted file mode 100644
index b3eca914..0000000
--- a/docs/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1,9 +0,0 @@
-# Metadata information for this directory.
-#
-# For more information on DIR_METADATA files, see:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/README.md
-#
-# For the schema of this file, see Metadata message:
-#   https://source.chromium.org/chromium/infra/infra/+/main:go/src/infra/tools/dirmd/proto/dir_metadata.proto
-
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
diff --git a/docs/privacy_budget/OWNERS b/docs/privacy_budget/OWNERS
deleted file mode 100644
index dc54869..0000000
--- a/docs/privacy_budget/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/blink/public/common/privacy_budget/OWNERS
diff --git a/docs/privacy_budget/good_identifiable_surface.md b/docs/privacy_budget/good_identifiable_surface.md
deleted file mode 100644
index 56cf16d1..0000000
--- a/docs/privacy_budget/good_identifiable_surface.md
+++ /dev/null
@@ -1,286 +0,0 @@
-# What's a Good Candidate For an IdentifiableSurface? {#good-surface}
-
-Once you have a source of potentially identifying information picked out, you
-need to determine how to represent the surface using
-[`blink::IdentifiableSurface`].
-
-The first step would be to determine what the surface *is* in the first place.
-
-_If the surface were to be presented as a question that the document asks
-a user-agent, what details should the question include in order for the answer
-to be identifiable across a wide range of user-agents?_
-
-Sometimes the question is straightforward. E.g. [`window.screenTop`] pretty much
-captures the entire question. But it can get tricky as we'll see in the
-examples below.
-
-All the pieces of information that the document needs to present to the
-user-agent in order to ask the identifiable question should be represented in
-the [`blink::IdentifiableSurface`].
-
-There are two broad categories of identifiable surfaces:
-
-*  **Direct Surfaces**: Surfaces accessible via looking up an attribute or
-   invoking a parameter-less operation of a global singleton object.
-
-   *Global singleton objects* refer to an object which is effectively the only
-   instance of its interface in a single execution context. If one were to
-   start from the global object and follow a chain of attributes or
-   parameter-less methods, all objects encountered along the way are global
-   singleton objects. One could pluck the attribute or operation out of the
-   last interface and stick it in the global object and there would be no
-   semantic difference.
-
-   In our `window.screenTop` example the global object exposes the `Window`
-   interface. `Window.window` or just `window` is a reference back to this
-   global object. The `Window` interface exposes the `screenTop` attribute. So
-   `window.screenTop` is an expression that looks up an attribute of the global
-   object.
-
-   By convention direct surfaces are represented using their corresponding
-   [`blink::WebFeature`]. All APIs that are direct identifiable surfaces should
-   have corresponding [Use Counters] and hence corresponding `WebFeature`
-   values.
-
-   For `window.screenTop`, the resulting `IdentifiableSurface` constructor
-   would look like this:
-
-   ```cpp
-   IdentifiableSurface::FromTypeAndToken(
-       Type::kWebFeature,                  // All direct surfaces use this type.
-       WebFeature::WindowScreenTop)
-   ```
-
-   See [Instrumenting Direct Surfaces] for details on how to instrument
-   these surfaces.
-
-2. **Indirect Surfaces**. A.k.a. everything else.
-
-   [`HTMLMediaElement.canPlayType()`] takes a string indicating a MIME type and
-   returns a vague indication of whether that media type is supported (its
-   return values are one of `"probably"`, `"maybe"`, or `""`). So the question
-   necessarily must include the MIME type.
-
-   Hence the `IdentifiableSurface` constructor could look like this:
-
-   ```cpp
-   IdentifiableSurface::FromTypeAndToken(
-       Type::kHTMLMediaElement_CanPlayType,
-       IdentifiabilityBenignStringToken(mime_type))
-   ```
-
-   The [`blink::IdentifiableSurface`] includes:
-   * That it represents an `HTMLMediaElement.canPlayType()` invocation.
-     `Type::kHTMLMediaElement_CanPlayType` is a bespoke enum value that was
-     introduced for this specific surface. See [Adding a Surface Type]
-     for details on how to add a surface type.
-   * The parameter that was passed to the operation.
-
-   `IdentifiabilityBenignStringToken` is a helper function that calculates
-   a digest of a "benign" string. See [Instrumentation] for more details on how
-   to represent operation arguments.
-
-The distinction between a direct surface and an indirect surface can sometimes
-be fuzzy. But it's always based on what's known _a priori_ and what's practical
-to measure. A `canPlayType("audio/ogg; codecs=vorbis")` query could just as
-easily be represented as a `WebFeature` like
-`MediaElementCanPlayType_Audio_Ogg_Codecs_Vorbis`. But
-
-* [This doesn't scale].
-* The set of MIME types can be pretty large and changing.
-* It's not possible to hardcode all possible values at coding time.
-* Most of the values will be irrelevant to identifiability, but we don't know which ones.
-
-All things considered, deriving a digest for the argument is much more
-practical than alternatives.
-
-### Example: NetworkInformation.saveData {#eg-net-effective-type}
-
-The following expression yields whether the user-agent is operating under
-a reduce data usage constraint (See [`NetworkInformation.saveData`]):
-
-```js
-navigator.connection.saveData
-```
-
-This is a [direct surface]. As such constructing a `IdentifableSurface` only
-requires knowing the interface and name of the final attribute or operation in
-the expression.
-
-Hence the `IdentifiableSurface` is of type `kWebFeature` with a web feature
-named `NetInfoEffectiveType` (which was a pre-existing [Use Counter][Use
-counters]). I.e.:
-
-```cpp
-IdentifiableSurface::FromTypeAndToken(
-    Type::kWebFeature,
-    WebFeature::NetInfoEffectiveType)
-```
-
-### Example: Media Capabilities {#eg-media-capabilities}
-
-The [Media Capabilities API] helps determine whether some media type is
-supported. E.g.:
-
-```js
-await navigator.mediaCapabilities.decodingInfo({
-  type: "file",
-  audio: { contentType: "audio/mp3" }
-});
-```
-
-In this case the script is specifying a [`MediaDecodingConfiguration`]
-dictionary. The [`MediaCapabilitiesInfo`] object returned by [`decodingInfo()`]
-depends on the input. Hence we have to capture the input in the
-`IdentifiableSurface` as follows:
-
-```cpp
-IdentifiableSurface::FromTypeAndToken(
-    Type::kHTMLMediaElement_CanPlayType,
-    IdentifiabilityBenignStringToken(mime_type))
-```
-
-See [Instrumentation] for more details on how to represent operation arguments
-and caveats around encoding strings.
-
-### Example: Media Streams API {#eg-media-streams}
-
-Another more complicated example is this use of the [Media Streams API].
-
-```js
-var mediaStream = await navigator.mediaDevices.getUserMedia({video: {
-  height: 240,
-  width: 320
-}});
-
-var firstAudioTrack = mediaStream.getAudioTracks()[0];
-
-var capabilities = firstAudioTrack.getCapabilities();
-```
-
-The target identifiable surface is the value of `capabilities`.
-
-An important consideration here is that [`MediaDevices.getUserMedia`] operation
-involves user interaction.
-
-In theory, if the `getUserMedia` operation is successful, the
-`IdentifiableSurface` for `capabilities` should represent the artifacts
-(starting with the last global singleton object):
-
-1. The operation [`MediaDevices.getUserMedia`].
-
-1. A [`MediaStreamConstraints`] dictionary with value
-   `{video: {height: 240, width: 320}}`.
-
-1. The user action.
-
-1. The operation [`MediaStream.getAudioTracks`] -- which is invoked on the
-   result of the prior step assuming the operation succeeded.
-
-1. `[0]`^th^ index -- applied to the list of [`MediaStreamTrack`]s resulting from
-   the previous step
-
-   > The Media Streams API does not specify the order of tracks. In general
-   > where a spec doesn't state the ordering of a sequence, the ordering itself
-   > can be a tracking concern. However in this case the implementation yields
-   > at most one audio track after a successful `getUserMedia` invocation.
-   > Hence there's no ordering concern here at least in Chromium.
-
-1. The operation [`MediaStreamTrack.getCapabilities`] -- which is invoked on
-   the result of the prior step.
-
-However,
-
-* The user action is not observable by the document. The only outcome exposed
-  to the document is whether `getUserMedia()` returned a `MediaStream` or if
-  the request was rejected due to some reason.
-
-  It's not necessary to go beyond what the document can observe.
-
-* If the call is successful the initial state of the resulting `MediaStream`
-  determines the stable properties that a document can observe.
-
-  The remaining accessors (e.g. `getAudioTracks()`, `getVideoTracks()` etc...)
-  deterministically depend on the returned `MediaStream` with the exception of
-  the indexing in step 5 which can be non-deterministic if there is more than
-  one audio track.
-
-  The diversity of document exposed state past step 3 is a subset of the
-  diversity of the initial `MediaStream` object.
-
-* If the call is rejected due to the request being over-constrained, then the
-  exception could indicate limitations of the underlying devices.
-
-Considering the above, we can tease apart multiple identifiable surfaces:
-
-1. **VALID** The mapping from &lt;`"MediaDevices.getUserMedia"` operation,
-   `MediaStreamConstraints` instance&gt; to &lt;`Exception` instance&gt; when
-   the call rejects prior to any user interaction.
-
-1. **OUT OF SCOPE** The mapping from &lt;`"MediaDevices.getUserMedia"`
-   operation, `MediaStreamConstraints` instance&gt; to &lt;time elapsed&gt; when
-   the call resolves.
-
-   Timing vectors like this are outside the scope of the initial study.
-
-1. **INFEASIBLE** The mapping from &lt;`"MediaDevices.getUserMedia"` operation,
-   &lt;`MediaStreamConstraints` instance, (user action)&gt; to
-   &lt;`MediaStream` instance&gt;.
-
-   As mentioned earlier the user action is not exposed to the document. Hence
-   we end up with an incomplete metric where the key doesn't have sufficient
-   diversity to account for the outcomes.
-
-1. **INFEASIBLE** The mapping from &lt;`"MediaDevices.getUserMedia"` operation,
-   `MediaStreamConstraints` instance, (user action)&gt; to &lt;`Exception`
-   instance&gt;.
-
-   Same problem as above.
-
-1. **VALID** The mapping from &lt;`MediaStreamTrack` instance&gt; to
-   &lt;`MediaTrackCapabilities` instance&gt;.
-
-   We can reason that this mapping is going to be surjective. The diversity of
-   &lt;`MediaTrackCapabilities` instance&gt; is not going to add information.
-
-   For simplicity surjective mappings can be collapsed into a single point
-   without losing information. Thus the mapping here is just &lt;`MediaStream`
-   instance&gt; to &lt;`1`&gt; where the value is arbitrary and doesn't matter.
-
-1. **VALID** The mapping from &lt;`MediaStreamTrack.label` string&gt; to
-   &lt;`MediaTrackCapabilities` instance&gt;.
-
-   The label is a string like "Internal microphone" which can be presented to
-   the user and assumed to be discerning enough that the user will find the
-   string sufficient to identify the correct device.
-
-The metrics we can derive from this surface are marked as **VALID**.
-
-Constructing a digest out of any of the dictionary instances also requires some
-care. Only include properties of each object that are expected to persist
-across browsing contexts. For example, any identifier that is origin-local,
-document-local, or depends on input from the document is not a good candidate.
-
-<!-- sort, case insensitive -->
-[`blink::IdentifiableSurface`]: ../../third_party/blink/public/common/privacy_budget/identifiable_surface.h
-[`blink::WebFeature`]: ../../third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
-[`decodingInfo()`]: https://www.w3.org/TR/media-capabilities/#dom-mediacapabilities-decodinginfo
-[`HTMLMediaElement.canPlayType()`]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/canPlayType
-[`MediaCapabilitiesInfo`]: https://www.w3.org/TR/media-capabilities/#dictdef-mediacapabilitiesinfo
-[`MediaDecodingConfiguration`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaDecodingConfiguration
-[`MediaDevices.getUserMedia`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia
-[`MediaStream.getAudioTracks`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStream/getAudioTracks
-[`MediaStream`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStream
-[`MediaStreamConstraints`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaTrackConstraints
-[`MediaStreamTrack.getCapabilities`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/getCapabilities
-[`MediaStreamTrack`]: https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack
-[`NetworkInformation.saveData`]: https://developer.mozilla.org/en-US/docs/Web/API/NetworkInformation/saveData
-[`window.screenTop`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/screenTop
-[Adding a Surface Type]: privacy_budget_instrumentation.md#adding-a-surface-type
-[direct surface]: privacy_budget_glossary.md#directsurface
-[Instrumentation]: privacy_budget_instrumentation.md
-[Instrumenting Direct Surfaces]: privacy_budget_instrumentation.md#annotating-direct-surfaces
-[Media Capabilities API]: https://developer.mozilla.org/en-US/docs/Web/API/Media_Capabilities_API
-[Media Streams API]: https://developer.mozilla.org/en-US/docs/Web/API/Media_Streams_API
-[this doesn't scale]: https://thecooperreview.com/10-tricks-appear-smart-meetings/
-[Use Counters]: ../use_counter_wiki.md
diff --git a/docs/privacy_budget/privacy_budget_code_locations.md b/docs/privacy_budget/privacy_budget_code_locations.md
deleted file mode 100644
index 5f60d68f..0000000
--- a/docs/privacy_budget/privacy_budget_code_locations.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Privacy Budget: Code Locations
-
-Following on from the high level [Privacy
-Budget](https://github.com/bslassey/privacy-budget) explainer, the current
-implementation focuses on measuring the identifiability of various web exposed
-features. Hence the word `Identifiability` occurs often in the code and
-documentation.
-
-This document focuses on code layout for Privacy Budget. Concepts and background
-for the identifiability study are out of scope.
-
-TODO(asanka): Link to study documents once they are checked in.
-
-## Core Metrics and Aggregation
-
-Locations:
-
-* [`third_party/blink/public/common/privacy_budget`](../../third_party/blink/public/common/privacy_budget)
-* [`third_party/blink/common/privacy_budget`](../../third_party/blink/common/privacy_budget)
-
-Includes:
-
-* Core logic and primitives for constructing identifiability metrics.
-
-  This is what one would use when reporting identifiability study samples.
-  Centralized logic makes it easier to construct consistent and stable samples.
-  All logic for supporting the construction of [`blink::IdentifiableToken`]
-  values from `std::` types and `base::` types should go here.
-
-* Per-process aggregation of metrics.
-
-  Aggregation minimizes the amount of information being communicated across
-  process boundaries.
-
-The code in this directory is shared across `//content`, `//chrome`, and
-`//third_party/blink`. Hence its placement in `blink/public/common`.
-
-In addition, this directory also contains logic for per-process aggregation of
-metrics so that they can be efficiently communicated across process boundaries.
-
-## Metrics Calculation for types visible to blink/renderer/platform
-
-Locations:
-
-* [`third_party/blink/renderer/platform/privacy_budget`](../../third_party/blink/renderer/platform/privacy_budget)
-
-Functions for constructing [`blink::IdentifiableToken`] values from
-`platform/wtf` types. E.g. `blink::String`.
-
-See the [`DEPS`][platform/pb/deps] in that directory for the paths that this
-component can depend on. In particular:
-
-* `blink/renderer/platform` can't depend on `modules/` or `core/` which means
-  that types from those source locations will need to be supported elsewhere.
-* `blink/renderer/platform/foo` can depend on other features under `platform/`.
-  So it would be possible to add support for types in `platform/` in this
-  directory.
-
-[`blink::IdentifiableToken`]: ../../third_party/blink/public/common/privacy_budget/identifiable_token.h
-[platform/pb/deps]: ../../third_party/blink/renderer/platform/privacy_budget/DEPS
-
-## Metrics calculation for types used in bindings based instrumentation
-
-Bindings based instrumentation is discussed in [Annotating Direct Surfaces vis
-WebIDL Bindings](privacy_budget_instrumentation.md#annotating-direct-surfaces).
-
-The generated bindings invoke `Dactyloscoper::RecordDirectSurface()` overrides
-for sampling and reporting. Hence support for types visible to
-`renderer/core/frame` lives in
-[`dactyloscoper.cc`/`.h`](../../third_party/blink/renderer/core/frame/dactyloscoper.h)
-
-## Static study settings
-
-Locations:
-
-* [`chrome/common/privacy_budget`](../../chrome/common/privacy_budget)
-
-Logic for accessing per-session settings based on externally supplied field
-trial configurations. The full set of externally controlled settings are
-in
-[`privacy_budget_features.h`](../../chrome/common/privacy_budget/privacy_budget_features.h).
-
-At a high level, these settings control such things as:
-
-* Whether the study is active.
-* Which identifiable surfaces should *not* be sampled.
-* Parameters for how surfaces are selected for sampling.
-
-Both the browser and the renderer need to access these settings. The browser
-needs them for filtering and reporting. The renderer needs them to avoid
-sampling surfaces where sampling itself is harmful for performance or stability
-reasons.
-
-## Persistent study state and reporting
-
-Locations:
-* [`chrome/browser/privacy_budget`](../../chrome/browser/privacy_budget)
-* [`chrome/test/data/privacy_budget`](../../chrome/test/data/privacy_budget): Test data
-
-Per-client state is primarily used and exposed by `IdentifiabilityStudyState`
-([Source](../../chrome/browser/privacy_budget/identifiability_study_state.h)).
diff --git a/docs/privacy_budget/privacy_budget_glossary.md b/docs/privacy_budget/privacy_budget_glossary.md
deleted file mode 100644
index 58b8f27e..0000000
--- a/docs/privacy_budget/privacy_budget_glossary.md
+++ /dev/null
@@ -1,51 +0,0 @@
-# Privacy Budget: Glossary
-
-<!-- Keep definitions sorted topologically, but also:
-
-* Add a named anchor. See
-  https://gerrit.googlesource.com/gitiles/+/HEAD/Documentation/markdown.md#Named-anchors
-
-* Use [this kind of reference], which you can define at the bottom of this
-  document.
-
--->
-
-## Identifiable Surface {#identifiablesurface}
-
-Concretely, defined in [`identifiable_surface.h`]. Represents a single source of
-partially identifying information.
-
-### Direct Identifiable Surface {#direct} {#directsurface}
-
-An [identifiable surface](#identifiablesurface) where the value returned by an
-operation or an attribute defined in an IDL file independently reports the
-partial fingerprint. No additional contextual information is necessary to
-interpret the meaning of the returned value.
-
-E.g.: `Screen.width` which is exposed as `window.screen.width`.
-
-Direct identifiable surfaces are a special case of [Keyed Identifiable
-Surface](#keyedsurface)s where the key is implicit and global.
-
-### Keyed Identifiable Surface {#keyedsurface}
-
-An [identifiable surface](#identifiablesurface) where the partial fingerprint is
-only meaningful if its context is fully qualified.
-
-E.g.: `HTMLElement.scrollWidth` depends on the contents and styling of the
-element. Hence for the return value to qualify as a partial fingerprint it needs
-to be interpreted in the context of the content and styling.
-
-### Identifiable Surface Type {#surfacetype}
-
-See [Surface Types].
-
-### Volatile Identifiable Surface {#volatilesurface}
-
-An [identifiable surface](#identifiablesurface) which changes semi-frequently
-but whose change events can be correlated to join identities across browsing
-contexts.
-
-<!-- References go here. Keep them sorted. -->
-[`identifiable_surface.h`]: ../../third_party/blink/public/common/privacy_budget/identifiable_surface.h
-[Surface Types]: privacy_budget_instrumentation.md#surface-types
diff --git a/docs/privacy_budget/privacy_budget_instrumentation.md b/docs/privacy_budget/privacy_budget_instrumentation.md
deleted file mode 100644
index 21563ee..0000000
--- a/docs/privacy_budget/privacy_budget_instrumentation.md
+++ /dev/null
@@ -1,349 +0,0 @@
-# Privacy Budget: Instrumentation
-
-Refer to [Privacy Budget: Code Locations](privacy_budget_code_locations.md) for
-details on where the code is located.
-
-All instrumentation for the identifiability study is done via the API exposed in
-[`third_party/blink/public/common/privacy_budget`](../../third_party/blink/public/common/privacy_budget).
-
-Follow the instructions below for adding instrumentation for an API.
-
-1. Are you annotating a [direct surface]? Jump to [Annotating Direct
-   Surfaces](#annotating-direct-surfaces) below.
-
-1. Are you annotating a [volatile surface]? For now we aren't annotating those.
-   So let's go ahead and pick a different API to work on.
-
-1. Determine the `UkmSourceId` and `UkmRecorder` to use for reporting, which
-   depends on what you have. See the table below:
-
-   | You have this              | Use this                                                                |
-   |----------------------------|-------------------------------------------------------------------------|
-   |[`blink::Document`]         |`Document::UkmRecorder()` and `Document::UkmSourceID()`                  |
-   |[`blink::ExecutionContext`] |`ExecutionContext::UkmRecorder()` and `ExecutionContext::UkmSourceID()`  |
-
-   Several classes inherit `blink::ExecutionContext` and therefore implement
-   `UkmRecorder()` and `UkmSourceID()` methods. E.g.:
-
-   * `blink::LocalDOMWindow`
-   * `blink::WorkerGlobalScope`
-     * `ServiceWorkerGlobalScope`
-     * `SharedWorkerGlobalScope`
-     * `DedicatedWorker`
-
-   If you can get your hand on any of these, you are all set. Otherwise you may
-   need to plumb a `UkmSourceID` down the stack.
-
-   The only requirement as far as Privacy Budget is concerned is that the given
-   source ID can be mapped to a top level navigation.
-
-1. Decide on the [`blink::IdentifiableSurface`] to use, and the method for
-   constructing it. If there's no corresponding surface type, see the
-   [Surface Types](#surface-types) section for instructions on adding a new type.
-
-   *** note
-   What's a good candidate for [`blink::IdentifiableSurface`]?
-   See [What's a good candidate for IdentifiableSurface?] below.
-   ***
-
-1. Condition all additional work on whether the study is active and whether the
-   type and surface should be sampled. {#gating}
-
-   On both the browser process and the renderer process the global
-   [`blink::IdentifiabilityStudySettings`] singleton knows whether the study is
-   active or not and whether a given [`blink::IdentifiableSurface`] or
-   [`blink::IdentifiableSurface::Type`] should be sampled.
-
-   If you know the final `blink::IdentifiableSurface` that you are going to use,
-   then:
-
-   ``` cpp
-   #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-
-   /* ... */
-
-   if (IdentifiabilityStudySettings::Get()->ShouldSampleSurface(my_surface)) {
-     // Only do work here.
-   }
-   ```
-
-   Otherwise, if you know the surface type, then:
-
-   ``` cpp
-   #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-
-   /* ... */
-
-   if (IdentifiabilityStudySettings::Get()->ShouldSampleType(my_surface_type)) {
-     // Only do work here.
-   }
-   ```
-
-   If you neither know the surface nor the type (this happens if the code you
-   are working on is common to a number of different surfaces or types) then:
-
-   ``` cpp
-   #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-
-   /* ... */
-
-   if (IdentifiabilityStudySettings::Get()->IsActive()) {
-     // Only do work here.
-   }
-   ```
-
-   *** note
-   **Important**: There should be zero additional work done if the study is not
-   active. If the surface or the type is disabled, then corresponding sampling
-   code should do no work.
-
-   This includes calculating the `IdentifiableSurface` and any related digests.
-   If calculating the `IdentifiableSurface` is expensive, then the code should
-   check `ShouldSampleType()` before progressing.
-
-   The primary mechanism for recovering from an unforeseen adverse effect of
-   sampling a surface is to stop the collection of that specific sample by way
-   of the global [`blink::IdentifiabilityStudySettings`]. The success of this
-   depends entirely on whether turning off the surface or type results in the
-   sampling code not doing any work when the surface or type is disabled.
-
-   If not, we'd need to shut down progressively larger scopes (i.e. the type or
-   the entire experiment). Granular checks are important to minimize the fallout
-   of such an event.
-   ***
-
-   *** promo
-   Avoid using `IdentifiabilityStudySettings::Get()->IsActive()` except as a
-   last resort. Use one of the more granular conditions instead.
-
-   The decision on whether to activate the study is made on a per client (i.e.
-   a browser instance) basis. It's not based on user profile nor any property
-   associated with the user.
-   ***
-
-1. Calculate the sample value based on the documentation in
-   [`identifiable_surface.h`] or whatever criteria you came up with.
-
-   More specific guidelines and low level details about deriving
-   an `IdentifiableToken` can be found in [`identifiable_token.h`]. However, the
-   gist of it is:
-
-   *** note
-   **WAIT**: Is the value being derived from a string that could potentially
-   contain sensitive information? (E.g. all strings originating from the
-   document that is not defined as a constant somewhere in the browser is likely
-   going to be sensitive). Then only extract a maximum of 16 bits from the
-   string.
-
-   For `blink::String` type, this is implemented as
-   `IdentifiabilitySensitiveStringToken()` and
-   `IdentifiabilitySensitiveCaseFoldingStringToken()` in
-   [`identifiability_digest_helpers.h`].
-   ***
-
-   * If you are about to construct a token out of a `blink::String` type use
-     one of the helpers in [`identifiability_digest_helpers.h`]. As mentioned
-     above, you'll need to decide:
-
-     * Whether this is a hardcoded string or not.
-     * Whether the case of the string is relevant or not.
-
-     It should be obvious which of the variants to use based on that. E.g.:
-
-     ``` cpp
-     namespace blink {
-
-     void Foo(const String& input) {
-       auto sample_value =
-           IdentifiabilitySensitiveCaseFoldingStringToken(input);
-       // ... other stuff
-     }
-
-     }  // namespace blink
-     ```
-
-   * For scalar types, the implicit conversions of
-     [`IdentifiableToken`][`identifiable_token.h`] should be enough. I.e.:
-
-     ``` cpp
-     // `scalar_value` is an intrinsic integral or floating point type. So
-     // implicit conversion kicks in.
-     blink::IdentifiableToken sample_value = scalar_value;
-     ```
-
-     Or
-
-     ``` cpp
-     int scalar_input = GetInput();
-     float scalar_value = GetValue();
-
-     IdentifiabiltyMetricsBuilder(source_id)
-       .Set(IdentifiableSurface::Type::kFoo,
-            scalar_input,
-            scalar_value)
-       .Record(/* elided */);
-     ```
-
-1. Report the value.
-
-## Surface Types {#surface-types}
-
-Every identifiable surface value should be _aggregateable_ across clients.
-
-*** promo
-What does _aggregateable_ mean? Let's say we observe two samples for the same
-[`blink::IdentifiableSurface`] 𝑣₁ and 𝑣₂. We should be able to claim that 𝑣₁
-= 𝑣₂ implies that the underlying sources of entropy are in identical states.
-Essentially this means that observations of a single identifiable surface value
-are measuring the **same thing**.
-***
-
-For example: The [`Screen`]`.width` attribute corresponds to the identifiable
-surface constructed as:
-
-```cpp
-// Good
-auto surface = blink::IdentifiableSurface::FromTypeAndToken(
-    Type::kWebFeature,
-    WebFeature::kV8Screen_Width_AttributeGetter);
-```
-
-All values for this surface are measuring the pixel width of **the same
-display**. All browser contexts active on the same browser window will report
-the same value.
-
-Another example: The [`Plugin`]`.filename` attribute may be considered to
-correspond to the identifiable surface constructed as:
-
-```cpp
-// Bad
-auto surface = blink::IdentifiableSurface::FromTypeAndToken(
-    Type::kWebFeature,
-    WebFeature::kPluginFilename);
-```
-
-However two observed values for this surface can't be meaningfully compared.
-Their equivalence likely indicates that they are for the same plugin. However
-if they are different, that could be because the two values correspond to
-different plugins, or different versions of the same plugin. In the former
-case, the same browser context can produce both values, which is misleading.
-In the case of this specific attribute, the surface must be further keyed
-based on some stable identifier for the plugin. For example, the key could be
-derived from [`Plugin`]`.name`.
-
-Whenever we are looking at two distinct sources of keys, the surfaces should
-belong to two different types. I.e. two different
-[`blink::IdentifiableSurface::Type`]`s`. If a matching type doesn't exist,
-you'll need to add one. See the next section for how to do that.
-
-### Adding a Surface Type {#adding-a-surface-type}
-
-All surface types and their parameters must be documented in
-[`identifiable_surface.h`]. When adding a new type, you should document:
-
-1. The source of the key with enough detail for someone to independently
-   construct the correct surface key.
-
-2. How to compute the value with enough detail for someone to independently
-   construct the correct value. Different code locations where the same surface
-   type is sampled **must** produce the same `IdentifiableSurface` value given
-   the same inputs.
-
-For an example, see the comments above the definition of `kWebFeature` in
-[`identifiable_surface.h`].
-
-## Annotating Direct Surfaces via WebIDL Bindings {#annotating-direct-surfaces}
-
-Since [direct surface]s are quite common, instrumentation for those APIs are done
-via the Blink bindings generation process.
-
-Operations and attributes (but not interfaces) that have been identified as
-being useful for client fingerprinting receive the [`HighEntropy`] extended
-attribute as follows:
-
-``` idl
-[Exposed=Window]
-interface MyInterface : EventTarget {
-    // This method does not expose any information.
-    void uninterestingMethod();
-
-    // This method, on the other hand, can be informative. It is marked as
-    // HighEntropy. This annotation alone doesn't provide any automated
-    // instrumentation since the bindings doesn't know what to look for or the
-    // relevance of the input parameters.
-    [HighEntropy, Measure] unsigned long? userHeightInInches(boolean tippyToes);
-
-    // All the returned contents of this attribute including their ordering is
-    // relevant for identification. It has the additional `Direct` token which
-    // signals to the bindings generator to emit sampling instrumentation.
-    [HighEntropy=Direct, Measure] readonly attribute DOMStringList allergies;
-};
-```
-
-All [`HighEntropy`] attributes must be accompanied by a corresponding
-[`Measure`] or `MeasureAs` attribute.
-
-If there was no [`Measure`] or `MeasureAs` attribute then adding it also
-involves updating `enums.xml` and `web_feature.mojom` as described in
-[`Measure`]. Perhaps it's easier to follow an example like the one below.
-
-Here's a sample CL that shows what needs to be done:
-  * http://crrev.com/c/2351957: Adds IDL based instrumentation for
-    `Screen.internal` and `Screen.primary`.
-
-Don't add custom `UseCounter` enums and instead rely on the generated
-`UseCounter` name whenever possible.
-
-E.g.: This is preferred.
-
-``` idl
-[Exposed=Window]
-interface MyInterface : EventTarget {
-    [HighEntropy=Direct, Measure] readonly attribute unsigned short angle;
-    [HighEntropy=Direct, Measure] readonly attribute DOMString type;
-};
-```
-
-Over this...
-
-``` idl
-[Exposed=Window]
-interface MyInterface : EventTarget {
-    [HighEntropy=Direct, MeasureAs=MyCustomUseCounterName1] readonly attribute unsigned short angle;
-    [HighEntropy=Direct, MeasureAs=MyCustomUseCounterName2] readonly attribute DOMString type;
-
-    //                             ^^^^^^^^^^^^^^^^^^^^^^^
-    //    You can optionally explicitly specify the UseCounter name like so.
-    //    It's more meant for cases where two or more methods or attributes are
-    //    effectively aliases of each other or the UseCounter only intends to
-    //    measure usage of either.
-};
-```
-
-There's no hard rule about this, but the `UseCounter` name is an implementation
-detail that doesn't belong in the IDL. It also adds unnecessary noise.
-
-*** note
-**IMPORTANT** Make sure that each API has its own `UseCounter` name. Otherwise
-multiple APIs will have their samples aggregated within the same bucket. This
-alters the observed characteristics of the API from what it really is.
-***
-
-<!-- Sort (case insensitive), but don't line-wrap -->
-[`blink::Document`]: ../../third_party/blink/renderer/core/dom/document.h
-[`blink::ExecutionContext`]: ../../third_party/blink/renderer/core/execution_context/execution_context.h
-[`blink::IdentifiabilityStudySettings`]: ../../third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
-[`blink::IdentifiableSurface::Type`]: ../../third_party/blink/public/common/privacy_budget/identifiable_surface.h
-[`blink::IdentifiableSurface`]: ../../third_party/blink/public/common/privacy_budget/identifiable_surface.h
-[`blink::WebFeature`]: ../../third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
-[`HighEntropy`]: ../../third_party/blink/renderer/bindings/IDLExtendedAttributes.md#HighEntropy_m_a_c
-[`identifiability_digest_helpers.h`]: ../../third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h
-[`identifiable_surface.h`]: ../../third_party/blink/public/common/privacy_budget/identifiable_surface.h
-[`identifiable_token.h`]: ../../third_party/blink/public/common/privacy_budget/identifiable_token.h
-[`Measure`]: ../../third_party/blink/renderer/bindings/IDLExtendedAttributes.md#Measure_i_m_a_c
-[`Plugin`]: ../../third_party/blink/renderer/modules/plugins/plugin.idl
-[`Screen`]: ../../third_party/blink/renderer/core/frame/screen.idl
-[direct surface]: privacy_budget_glossary.md#directsurface
-[Use Counter]: ../use_counter_wiki.md
-[volatile surface]: privacy_budget_glossary.md#volatilesurface
-[What's a good candidate for IdentifiableSurface?]: good_identifiable_surface.md
diff --git a/infra/config/generated/builders/ci/ToTLinuxMSan/gn-args.json b/infra/config/generated/builders/ci/ToTLinuxMSan/gn-args.json
index ac70fa3..52ffca62 100644
--- a/infra/config/generated/builders/ci/ToTLinuxMSan/gn-args.json
+++ b/infra/config/generated/builders/ci/ToTLinuxMSan/gn-args.json
@@ -10,6 +10,7 @@
     "target_os": "linux",
     "treat_warnings_as_errors": false,
     "use_reclient": false,
+    "use_remoteexec": true,
     "use_siso": true
   }
 }
\ No newline at end of file
diff --git a/infra/config/generated/luci/commit-queue.cfg b/infra/config/generated/luci/commit-queue.cfg
index 18cb8938..18df1078 100644
--- a/infra/config/generated/luci/commit-queue.cfg
+++ b/infra/config/generated/luci/commit-queue.cfg
@@ -8395,6 +8395,7 @@
       ref_regexp_exclude: "refs/branch-heads/7204"
       ref_regexp_exclude: "refs/branch-heads/7444"
       ref_regexp_exclude: "refs/branch-heads/7499"
+      ref_regexp_exclude: "refs/branch-heads/7559"
     }
   }
   verifiers {
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 5e51496..371587d0 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -355,6 +355,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -1298,6 +1302,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -2029,6 +2037,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -2600,6 +2612,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -2974,6 +2990,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -3877,6 +3897,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -4381,6 +4405,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -4810,6 +4838,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -5176,6 +5208,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -5545,6 +5581,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -5909,6 +5949,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -6353,6 +6397,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -7352,6 +7400,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -8111,6 +8163,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -8475,6 +8531,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -9119,6 +9179,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -9518,6 +9582,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -9877,6 +9945,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -10325,6 +10397,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -10754,6 +10830,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -11112,6 +11192,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -11624,6 +11708,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -12048,6 +12136,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -12662,6 +12754,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -13246,6 +13342,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -13865,6 +13965,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -14329,6 +14433,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -14715,6 +14823,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -15309,6 +15421,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -15892,6 +16008,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -16307,6 +16427,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -17065,6 +17189,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -17452,6 +17580,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -18226,6 +18358,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -18624,6 +18760,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -19072,6 +19212,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -19531,6 +19675,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -19995,6 +20143,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -20359,6 +20511,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -20717,6 +20873,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -21111,6 +21271,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -21510,6 +21674,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -22054,6 +22222,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -22448,6 +22620,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -22873,6 +23049,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -23302,6 +23482,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -23671,6 +23855,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -24040,6 +24228,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -24509,6 +24701,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -24867,6 +25063,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -25225,6 +25425,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -25824,6 +26028,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -26214,6 +26422,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -26615,6 +26827,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
@@ -26994,6 +27210,10 @@
         url: "/p/chromium-m143/g/main/console"
       }
       links {
+        text: "m144"
+        url: "/p/chromium-m144/g/main/console"
+      }
+      links {
         text: "trunk"
         url: "/p/chromium/g/main/console"
         alt: "Trunk (ToT) console"
diff --git a/infra/config/generated/luci/realms.cfg b/infra/config/generated/luci/realms.cfg
index 79f34b57..3fa2f8c0 100644
--- a/infra/config/generated/luci/realms.cfg
+++ b/infra/config/generated/luci/realms.cfg
@@ -570,6 +570,7 @@
     principals: "project:chromium-m138"
     principals: "project:chromium-m142"
     principals: "project:chromium-m143"
+    principals: "project:chromium-m144"
     principals: "project:dawn"
     principals: "user:chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:findit-for-me@appspot.gserviceaccount.com"
@@ -624,6 +625,7 @@
     principals: "project:chromium-m138"
     principals: "project:chromium-m142"
     principals: "project:chromium-m143"
+    principals: "project:chromium-m144"
     principals: "project:dawn"
     principals: "user:chromium-orchestrator@chops-service-accounts.iam.gserviceaccount.com"
     principals: "user:infra-try-recipes-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/milestones.json b/infra/config/milestones.json
index 56a32e3..27bd9e2 100644
--- a/infra/config/milestones.json
+++ b/infra/config/milestones.json
@@ -13,5 +13,10 @@
         "name": "m143",
         "project": "chromium-m143",
         "ref": "refs/branch-heads/7499"
+    },
+    "144": {
+        "name": "m144",
+        "project": "chromium-m144",
+        "ref": "refs/branch-heads/7559"
     }
 }
diff --git a/infra/config/subprojects/chromium/ci/chromium.clang.star b/infra/config/subprojects/chromium/ci/chromium.clang.star
index 7034e8a..7fbdcbf 100644
--- a/infra/config/subprojects/chromium/ci/chromium.clang.star
+++ b/infra/config/subprojects/chromium/ci/chromium.clang.star
@@ -1118,7 +1118,7 @@
             "msan",
             "release",
             "x64",
-            # TODO(crbug.com/450862240) enable "remoteexec" here
+            "remoteexec",
         ],
     ),
     targets = targets.bundle(
diff --git a/internal b/internal
index 2098733..631be08 160000
--- a/internal
+++ b/internal
@@ -1 +1 @@
-Subproject commit 20987331c080610f354e4a0a7fbd4a5b71fd6624
+Subproject commit 631be088f7fe566bcac84cc5b619c5784cdb6195
diff --git a/ios/chrome/browser/ai_prototyping/coordinator/BUILD.gn b/ios/chrome/browser/ai_prototyping/coordinator/BUILD.gn
index 3dfa300..5c2052f 100644
--- a/ios/chrome/browser/ai_prototyping/coordinator/BUILD.gn
+++ b/ios/chrome/browser/ai_prototyping/coordinator/BUILD.gn
@@ -22,6 +22,7 @@
     "//ios/chrome/browser/intelligence/proto_wrappers",
     "//ios/chrome/browser/intelligence/proto_wrappers:ios_smart_tab_grouping_proto_wrapper",
     "//ios/chrome/browser/intelligence/smart_tab_grouping/model",
+    "//ios/chrome/browser/intelligence/smart_tab_grouping/utils",
     "//ios/chrome/browser/optimization_guide/model",
     "//ios/chrome/browser/optimization_guide/mojom",
     "//ios/chrome/browser/shared/coordinator/chrome_coordinator",
diff --git a/ios/chrome/browser/ai_prototyping/coordinator/DEPS b/ios/chrome/browser/ai_prototyping/coordinator/DEPS
index 720a1e6..1edb9cb 100644
--- a/ios/chrome/browser/ai_prototyping/coordinator/DEPS
+++ b/ios/chrome/browser/ai_prototyping/coordinator/DEPS
@@ -6,4 +6,5 @@
   "+ios/chrome/browser/intelligence/enhanced_calendar/model",
   "+ios/chrome/browser/intelligence/persist_tab_context/model",
   "+ios/chrome/browser/intelligence/smart_tab_grouping/model",
+  "+ios/chrome/browser/intelligence/smart_tab_grouping/utils",
 ]
diff --git a/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm b/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
index 6aaaa55..b8d2b6f06 100644
--- a/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
+++ b/ios/chrome/browser/ai_prototyping/coordinator/ai_prototyping_mediator.mm
@@ -28,6 +28,7 @@
 #import "ios/chrome/browser/intelligence/proto_wrappers/page_context_wrapper.h"
 #import "ios/chrome/browser/intelligence/proto_wrappers/tab_organization_request_wrapper.h"
 #import "ios/chrome/browser/intelligence/smart_tab_grouping/model/smart_tab_grouping_service_impl.h"
+#import "ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.h"
 #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service.h"
 #import "ios/chrome/browser/optimization_guide/model/optimization_guide_service_factory.h"
 #import "ios/chrome/browser/optimization_guide/mojom/enhanced_calendar_service.mojom-forward.h"
@@ -417,7 +418,7 @@
   return result;
 }
 
-// Handles the SmartTabGroupingResponse by outputting the response proto or
+// Handles the IosSmartTabGroupingResponse by outputting the response proto or
 // an error message into the result text field.
 - (void)handleSmartTabGroupingResponseResult:
     (ai::mojom::SmartTabGroupingResponseResultPtr)response_result {
@@ -428,13 +429,23 @@
     return;
   }
 
-  std::string result = [self
-      serializeSmartTabGroupingResponseToString:
-          response_result->get_response()
-              .As<optimization_guide::proto::IosSmartTabGroupingResponse>()
-              .value()];
+  auto response_proto =
+      response_result->get_response()
+          .As<optimization_guide::proto::IosSmartTabGroupingResponse>();
 
-  [self.consumer updateQueryResult:base::SysUTF8ToNSString(result)
+  if (!response_proto.has_value()) {
+    [self.consumer
+        updateQueryResult:@"Error parsing IosSmartTabGroupingResponse"
+               forFeature:AIPrototypingFeature::kSmartTabGrouping];
+    return;
+  }
+
+  ApplySmartTabGroupResponse(response_proto.value(), _webStateList);
+
+  std::string result_string =
+      [self serializeSmartTabGroupingResponseToString:response_proto.value()];
+
+  [self.consumer updateQueryResult:base::SysUTF8ToNSString(result_string)
                         forFeature:AIPrototypingFeature::kSmartTabGrouping];
 }
 
diff --git a/ios/chrome/browser/composebox/coordinator/BUILD.gn b/ios/chrome/browser/composebox/coordinator/BUILD.gn
index bd1fef93..5e5985b5 100644
--- a/ios/chrome/browser/composebox/coordinator/BUILD.gn
+++ b/ios/chrome/browser/composebox/coordinator/BUILD.gn
@@ -43,6 +43,7 @@
     "//components/search",
     "//components/search_engines",
     "//ios/chrome/app/strings",
+    "//ios/chrome/browser/aim/model:aim_availability",
     "//ios/chrome/browser/autocomplete/model",
     "//ios/chrome/browser/bookmarks/model",
     "//ios/chrome/browser/bookmarks/model:model_utils",
@@ -128,6 +129,8 @@
     "//base/test:test_support",
     "//components/contextual_search:public",
     "//components/contextual_search/internal:test_support",
+    "//components/omnibox/browser",
+    "//components/omnibox/browser:test_support",
     "//components/omnibox/composebox/ios",
     "//components/search_engines",
     "//components/search_engines:test_support",
diff --git a/ios/chrome/browser/composebox/coordinator/DEPS b/ios/chrome/browser/composebox/coordinator/DEPS
index fdd01305..b193b25 100644
--- a/ios/chrome/browser/composebox/coordinator/DEPS
+++ b/ios/chrome/browser/composebox/coordinator/DEPS
@@ -1,6 +1,7 @@
 include_rules = [
   "+components/contextual_search",
   "+components/omnibox/composebox",
+  "+ios/chrome/browser/aim/model",
   "+ios/chrome/browser/autocomplete/model",
   "+ios/chrome/browser/bookmarks/model",
   "+ios/chrome/browser/context_menu/ui_bundled",
diff --git a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_coordinator.mm b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_coordinator.mm
index aea49d6..ef3ead1 100644
--- a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_coordinator.mm
+++ b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_coordinator.mm
@@ -15,6 +15,7 @@
 #import "components/omnibox/composebox/ios/composebox_query_controller_ios.h"
 #import "components/search_engines/template_url_service.h"
 #import "components/signin/public/identity_manager/identity_manager.h"
+#import "ios/chrome/browser/aim/model/ios_chrome_aim_eligibility_service_factory.h"
 #import "ios/chrome/browser/composebox/coordinator/composebox_entrypoint.h"
 #import "ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h"
 #import "ios/chrome/browser/composebox/coordinator/composebox_mode_holder.h"
@@ -163,7 +164,9 @@
                                           FromBrowser(self.browser)
                           isIncognito:self.isOffTheRecord
                            modeHolder:_modeHolder
-                   templateURLService:templateURLService];
+                   templateURLService:templateURLService
+                aimEligibilityService:IOSChromeAimEligibilityServiceFactory::
+                                          GetForProfile(self.profile)];
   _mediator.URLLoader = _URLLoader;
   _mediator.consumer = _viewController;
   _mediator.delegate = self;
@@ -279,12 +282,9 @@
     [self showMaxAttachmentSnackbarError];
     return;
   }
-  if (!_picker) {
     [self
         composeboxViewControllerMayShowGalleryPicker:composeboxViewController];
-  }
   [_viewController presentViewController:_picker animated:YES completion:nil];
-  _picker = nil;
 }
 
 - (void)composeboxViewControllerDidTapCameraButton:
@@ -309,12 +309,9 @@
 
 - (void)composeboxViewControllerMayShowGalleryPicker:
     (ComposeboxInputPlateViewController*)composeboxViewController {
-  if (_picker) {
-    return;
-  }
   PHPickerConfiguration* config = [[PHPickerConfiguration alloc]
       initWithPhotoLibrary:PHPhotoLibrary.sharedPhotoLibrary];
-  config.selectionLimit = 1;
+  config.selectionLimit = [_mediator maxNumberOfGalleryItemsAllowed];
   config.filter = [PHPickerFilter imagesFilter];
   _picker = [[PHPickerViewController alloc] initWithConfiguration:config];
   _picker.delegate = self;
@@ -377,14 +374,15 @@
 - (void)picker:(PHPickerViewController*)picker
     didFinishPicking:(NSArray<PHPickerResult*>*)results {
   [picker dismissViewControllerAnimated:YES completion:nil];
-
+  _picker = nil;
   if (results.count == 0) {
     return;
   }
 
-  PHPickerResult* result = results.firstObject;
-  [_mediator processImageItemProvider:result.itemProvider
-                              assetID:result.assetIdentifier];
+  for (PHPickerResult* result in results) {
+    [_mediator processImageItemProvider:result.itemProvider
+                                assetID:result.assetIdentifier];
+  }
 }
 
 #pragma mark - UIDocumentPickerDelegate
diff --git a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h
index 7e6060f..748da44 100644
--- a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h
+++ b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h
@@ -20,6 +20,7 @@
 
 @class ComposeboxMetricsRecorder;
 @protocol ComposeboxURLLoader;
+class AimEligibilityService;
 class FaviconLoader;
 class GURL;
 class PersistTabContextBrowserAgent;
@@ -67,7 +68,9 @@
                  (PersistTabContextBrowserAgent*)persistTabContextAgent
                         isIncognito:(BOOL)isIncognito
                          modeHolder:(ComposeboxModeHolder*)modeHolder
-                 templateURLService:(TemplateURLService*)templateURLService;
+                 templateURLService:(TemplateURLService*)templateURLService
+              aimEligibilityService:
+                  (AimEligibilityService*)aimEligibilityService;
 
 - (void)disconnect;
 
@@ -81,6 +84,10 @@
 // Returns whether more attachments can be added.
 - (BOOL)canAddMoreAttachments;
 
+// Returns the maximum number of gallery items allowed based on the current
+// composebox mode.
+- (NSUInteger)maxNumberOfGalleryItemsAllowed;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_COMPOSEBOX_COORDINATOR_COMPOSEBOX_INPUT_PLATE_MEDIATOR_H_
diff --git a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm
index 9b26a2a3..c130188 100644
--- a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm
+++ b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.mm
@@ -31,6 +31,7 @@
 #import "components/contextual_search/contextual_search_session_handle.h"
 #import "components/lens/contextual_input.h"
 #import "components/lens/lens_bitmap_processing.h"
+#import "components/omnibox/browser/aim_eligibility_service.h"
 #import "components/omnibox/browser/lens_suggest_inputs_utils.h"
 #import "components/omnibox/common/omnibox_features.h"
 #import "components/omnibox/composebox/ios/composebox_file_upload_observer_bridge.h"
@@ -160,6 +161,10 @@
   raw_ptr<TemplateURLService> _templateURLService;
   // Observer for the TemplateURLService.
   std::unique_ptr<SearchEngineObserverBridge> _searchEngineObserver;
+  // Service to check for AI mode eligibility.
+  raw_ptr<AimEligibilityService> _aimEligibilityService;
+  // Subscription for AIM eligibility changes.
+  base::CallbackListSubscription _aimEligibilitySubscription;
 
   // Stores the page context wrappers for the duration of the APC retrieval.
   std::unordered_map<web::WebStateID, PageContextWrapper*> _pageContextWrappers;
@@ -193,7 +198,9 @@
                  (PersistTabContextBrowserAgent*)persistTabContextAgent
                         isIncognito:(BOOL)isIncognito
                          modeHolder:(ComposeboxModeHolder*)modeHolder
-                 templateURLService:(TemplateURLService*)templateURLService {
+                 templateURLService:(TemplateURLService*)templateURLService
+              aimEligibilityService:
+                  (AimEligibilityService*)aimEligibilityService {
   self = [super init];
   if (self) {
     _items = [NSMutableArray array];
@@ -213,6 +220,15 @@
     _templateURLService = templateURLService;
     _searchEngineObserver =
         std::make_unique<SearchEngineObserverBridge>(self, _templateURLService);
+    _aimEligibilityService = aimEligibilityService;
+    if (_aimEligibilityService) {
+      __weak __typeof(self) weakSelf = self;
+      _aimEligibilitySubscription =
+          _aimEligibilityService->RegisterEligibilityChangedCallback(
+              base::BindRepeating(^{
+                [weakSelf updateEligibleToAIMode];
+              }));
+    }
   }
   return self;
 }
@@ -226,6 +242,8 @@
   _persistTabContextAgent = nullptr;
   _searchEngineObserver.reset();
   _templateURLService = nullptr;
+  _aimEligibilitySubscription = {};
+  _aimEligibilityService = nullptr;
   _composeboxObserverBridge.reset();
   if (_contextualSearchSession) {
     _contextualSearchSession->NotifySessionAbandoned();
@@ -297,6 +315,7 @@
     [self attachCurrentTabContent];
   }
 
+  [self updateEligibleToAIMode];
   [self updateCompactModeIfNeeded];
   [self updateShowsExtendedControls];
 }
@@ -345,6 +364,32 @@
   return _items.count < kAttachmentLimit;
 }
 
+- (NSUInteger)maxNumberOfGalleryItemsAllowed {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(_sequenceChecker);
+
+  NSUInteger availableSlots = kAttachmentLimit - _items.count;
+  switch (_modeHolder.mode) {
+    case ComposeboxMode::kRegularSearch:
+    case ComposeboxMode::kAIM: {
+      // For RegularSearch and AIM, allow up to kAttachmentLimit items.
+      return availableSlots;
+    }
+    case ComposeboxMode::kImageGeneration: {
+      // For ImageGeneration, allow 1 image if no images are present, otherwise
+      // 0.
+      BOOL hasImage = NO;
+      for (ComposeboxInputItem* item in _items) {
+        if (item.type ==
+            ComposeboxInputItemType::kComposeboxInputItemTypeImage) {
+          hasImage = YES;
+          break;
+        }
+      }
+      return hasImage ? 0 : MIN(availableSlots, 1);
+    }
+  }
+}
+
 #pragma mark - ComposeboxInputPlateMutator
 
 - (void)removeItem:(ComposeboxInputItem*)item {
@@ -418,10 +463,14 @@
       [self.consumer setItems:_items];
       break;
     case ComposeboxMode::kAIM:
+      break;
     case ComposeboxMode::kImageGeneration:
+      [self cleanAttachmentsForImageGeneration];
       break;
   }
+
   [self updateCompactModeIfNeeded];
+  [self updateConsumerActionsState];
 }
 
 #pragma mark - ComposeboxTabPickerSelectionDelegate
@@ -776,6 +825,42 @@
 
 #pragma mark - Private
 
+// Cleans attachments when switching to image generation mode.
+// This method ensures that only one image attachment is kept, and all other
+// attachments (including other images, tabs, and files) are removed.
+- (void)cleanAttachmentsForImageGeneration {
+  NSMutableArray<ComposeboxInputItem*>* itemsToKeep = [NSMutableArray array];
+  ComposeboxInputItem* imageToKeep = nil;
+
+  // Find one image to keep.
+  for (ComposeboxInputItem* item in _items) {
+    if (item.type == ComposeboxInputItemType::kComposeboxInputItemTypeImage &&
+        !imageToKeep) {
+      imageToKeep = item;
+      [itemsToKeep addObject:item];
+      break;
+    }
+  }
+
+  if (itemsToKeep.count == _items.count) {
+    // No items were removed.
+    return;
+  }
+
+  // Find items to remove from the backend.
+  for (ComposeboxInputItem* item in _items) {
+    if (![itemsToKeep containsObject:item]) {
+      if (_contextualSearchSession) {
+        _contextualSearchSession->DeleteFile(item.serverToken);
+      }
+    }
+  }
+
+  _items = itemsToKeep;
+
+  [self updateConsumerItems];
+}
+
 // Handles the loaded preview `image` for the item with the given `identifier`.
 - (void)didLoadPreviewImage:(UIImage*)previewImage
       forItemWithIdentifier:(base::UnguessableToken)identifier {
@@ -999,6 +1084,14 @@
   return NO;
 }
 
+// Updates the consumer about whether the user is eligible to use AI Mode.
+- (void)updateEligibleToAIMode {
+  if (!_aimEligibilityService) {
+    return;
+  }
+  [self.consumer setEligibleToAIMode:_aimEligibilityService->IsAimEligible()];
+}
+
 // Updates the consumer about whether the extended controls should be shown.
 - (void)updateShowsExtendedControls {
   if (!_templateURLService) {
@@ -1087,11 +1180,13 @@
   }
   [self.consumer disableCreateImageActions:hasTabOrFile];
 
-  // TODO(crbug.com/454832175): Disable tabs and files actions in image creation
-  // mode.
-  BOOL isImageCreation = NO;
+  BOOL isImageCreation = _modeHolder.mode == ComposeboxMode::kImageGeneration;
   [self.consumer disableAttachTabActions:isImageCreation];
   [self.consumer disableAttachFileActions:isImageCreation];
+
+  BOOL canAddMoreImages = [self maxNumberOfGalleryItemsAllowed] > 0;
+  [self.consumer disableGalleryActions:!canAddMoreImages];
+  [self.consumer disableCameraActions:!canAddMoreImages];
 }
 /// Updates the consumer items and maybe trigger AIM.
 - (void)updateConsumerItems {
@@ -1100,12 +1195,10 @@
   [self updateOptionToAttachCurrentTab];
   [self updateConsumerActionsState];
 
-  if (_items.count > 0) {
-    if ([_modeHolder isRegularSearch]) {
-      // AI mode is implicitly enabled by items attachment.
-      [self.metricsRecorder
-          recordAiModeActivationSource:AiModeActivationSource::kImplicit];
-    }
+  if (_items.count > 0 && [_modeHolder isRegularSearch]) {
+    // AI mode is implicitly enabled by items attachment.
+    [self.metricsRecorder
+        recordAiModeActivationSource:AiModeActivationSource::kImplicit];
     _modeHolder.mode = ComposeboxMode::kAIM;
   }
 }
diff --git a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator_unittest.mm b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator_unittest.mm
index a4b2095..48ca04b 100644
--- a/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator_unittest.mm
+++ b/ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator_unittest.mm
@@ -4,21 +4,27 @@
 
 #import "ios/chrome/browser/composebox/coordinator/composebox_input_plate_mediator.h"
 
+#import "base/no_destructor.h"
 #import "base/run_loop.h"
 #import "base/test/task_environment.h"
 #import "components/contextual_search/contextual_search_context_controller.h"
 #import "components/contextual_search/contextual_search_service.h"
 #import "components/contextual_search/internal/test_composebox_query_controller.h"
+#import "components/omnibox/browser/mock_aim_eligibility_service.h"
+#import "components/omnibox/browser/omnibox_prefs.h"
 #import "components/omnibox/composebox/ios/composebox_query_controller_ios.h"
+#import "components/prefs/testing_pref_service.h"
 #import "components/search_engines/search_engines_test_environment.h"
 #import "components/search_engines/template_url_service.h"
 #import "components/search_engines/template_url_service_test_util.h"
 #import "components/signin/public/identity_manager/identity_manager.h"
+#import "components/signin/public/identity_manager/identity_test_environment.h"
 #import "components/variations/variations_client.h"
 #import "components/version_info/channel.h"
 #import "ios/chrome/browser/composebox/coordinator/composebox_mode_holder.h"
 #import "ios/chrome/browser/composebox/ui/composebox_input_plate_consumer.h"
 #import "ios/chrome/browser/shared/model/profile/test/test_profile_ios.h"
+#import "ios/chrome/browser/signin/model/identity_manager_factory.h"
 #import "services/network/public/cpp/shared_url_loader_factory.h"
 #import "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
 #import "services/network/test/test_url_loader_factory.h"
@@ -30,6 +36,7 @@
 @interface TestComposeboxInputPlateConsumer
     : NSObject <ComposeboxInputPlateConsumer>
 
+@property(nonatomic, assign) BOOL eligibleToAIMode;
 @property(nonatomic, assign) BOOL showsSendButton;
 @property(nonatomic, assign) BOOL showsExtendedControls;
 
@@ -43,6 +50,10 @@
     forItemWithIdentifier:(const base::UnguessableToken&)identifier {
 }
 
+- (void)setEligibleToAIMode:(BOOL)eligibleToAIMode {
+  _eligibleToAIMode = eligibleToAIMode;
+}
+
 - (void)setShowsSendButton:(BOOL)showsSendButton {
   _showsSendButton = showsSendButton;
 }
@@ -73,6 +84,10 @@
 }
 - (void)disableCreateImageActions:(BOOL)disabled {
 }
+- (void)disableCameraActions:(BOOL)disabled {
+}
+- (void)disableGalleryActions:(BOOL)disabled {
+}
 
 @end
 
@@ -82,6 +97,8 @@
  protected:
   void SetUp() override {
     PlatformTest::SetUp();
+    omnibox::RegisterProfilePrefs(pref_service_.registry());
+    AimEligibilityService::RegisterProfilePrefs(pref_service_.registry());
     profile_ = TestProfileIOS::Builder().Build();
     shared_url_loader_factory_ =
         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
@@ -92,16 +109,30 @@
         fake_variations_client_.get(), version_info::Channel::STABLE, "en-US");
     auto config_params = std::make_unique<
         contextual_search::ContextualSearchContextController::ConfigParams>();
+    static base::NoDestructor<network::TestURLLoaderFactory>
+        test_url_loader_factory;
+    aim_eligibility_service_ =
+        std::make_unique<testing::NiceMock<MockAimEligibilityService>>(
+            pref_service_, template_url_service(),
+            test_url_loader_factory->GetSafeWeakWrapper(),
+            IdentityManagerFactory::GetForProfile(profile_.get()));
+    EXPECT_CALL(*aim_eligibility_service_,
+                RegisterEligibilityChangedCallback(testing::_))
+        .WillOnce(
+            testing::DoAll(testing::SaveArg<0>(&aim_callback_),
+                           testing::Return(base::CallbackListSubscription())));
     mediator_ = [[ComposeboxInputPlateMediator alloc]
-        initWithContextualSearchSession:service_->CreateSession(
-                                            std::move(config_params),
-                                            contextual_search::ContextualSearchSource::kUnknown)
+        initWithContextualSearchSession:
+            service_->CreateSession(
+                std::move(config_params),
+                contextual_search::ContextualSearchSource::kUnknown)
                            webStateList:nullptr
                           faviconLoader:nullptr
                  persistTabContextAgent:nullptr
                             isIncognito:NO
                              modeHolder:[[ComposeboxModeHolder alloc] init]
-                     templateURLService:template_url_service()];
+                     templateURLService:template_url_service()
+                  aimEligibilityService:aim_eligibility_service_.get()];
     consumer_ = [[TestComposeboxInputPlateConsumer alloc] init];
     mediator_.consumer = consumer_;
 
@@ -114,6 +145,7 @@
     [mediator_ disconnect];
     mediator_ = nil;
     consumer_ = nil;
+    aim_eligibility_service_.reset();
     service_.reset();
     fake_variations_client_.reset();
     shared_url_loader_factory_.reset();
@@ -127,16 +159,42 @@
   }
 
   base::test::TaskEnvironment task_environment_;
+  TestingPrefServiceSimple pref_service_;
   std::unique_ptr<TestProfileIOS> profile_;
   network::TestURLLoaderFactory test_factory_;
   scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
   std::unique_ptr<FakeVariationsClient> fake_variations_client_;
   search_engines::SearchEnginesTestEnvironment search_engines_test_environment_;
   std::unique_ptr<contextual_search::ContextualSearchService> service_;
+  std::unique_ptr<testing::NiceMock<MockAimEligibilityService>>
+      aim_eligibility_service_;
+  base::RepeatingClosure aim_callback_;
   TestComposeboxInputPlateConsumer* consumer_;
   ComposeboxInputPlateMediator* mediator_;
 };
 
+// Tests that the consumer is informed when AIM is eligible.
+TEST_F(ComposeboxInputPlateMediatorTest, InformConsumerWhenAimEligible) {
+  EXPECT_CALL(*aim_eligibility_service_, IsAimEligible())
+      .WillRepeatedly(testing::Return(true));
+  ASSERT_FALSE(aim_callback_.is_null());
+
+  aim_callback_.Run();
+
+  EXPECT_TRUE(consumer_.eligibleToAIMode);
+}
+
+// Tests that the consumer is informed when AIM is not eligible.
+TEST_F(ComposeboxInputPlateMediatorTest, InformConsumerWhenAimNotEligible) {
+  EXPECT_CALL(*aim_eligibility_service_, IsAimEligible())
+      .WillRepeatedly(testing::Return(false));
+  ASSERT_FALSE(aim_callback_.is_null());
+
+  aim_callback_.Run();
+
+  EXPECT_FALSE(consumer_.eligibleToAIMode);
+}
+
 // Tests that extended controls are shown when Google is the default search
 // engine.
 TEST_F(ComposeboxInputPlateMediatorTest, ShowsExtendedControlsWithGoogleDSE) {
@@ -173,12 +231,14 @@
   [mediator_ omniboxDidChangeText:u"some text"
                     isSearchQuery:NO
               userInputInProgress:NO];
+
   EXPECT_TRUE(consumer_.showsSendButton);
 }
 
 // Tests that the send button is hidden when there is no text in the omnibox.
 TEST_F(ComposeboxInputPlateMediatorTest, HidesSendButtonWithoutText) {
   [mediator_ omniboxDidChangeText:u"" isSearchQuery:NO userInputInProgress:NO];
+
   EXPECT_FALSE(consumer_.showsSendButton);
 }
 
diff --git a/ios/chrome/browser/composebox/ui/BUILD.gn b/ios/chrome/browser/composebox/ui/BUILD.gn
index f8cea32..cb9e4314 100644
--- a/ios/chrome/browser/composebox/ui/BUILD.gn
+++ b/ios/chrome/browser/composebox/ui/BUILD.gn
@@ -32,6 +32,7 @@
     "composebox_view_controller.mm",
   ]
   deps = [
+    ":ui_constants",
     "//base",
     "//build:branding_buildflags",
     "//ios/chrome/app/strings",
@@ -55,3 +56,25 @@
     "//ui/base",
   ]
 }
+
+source_set("ui_constants") {
+  sources = [
+    "composebox_ui_constants.h",
+    "composebox_ui_constants.mm",
+  ]
+  deps = [ "//base" ]
+}
+
+source_set("eg2_tests") {
+  configs += [ "//build/config/ios:xctest_config" ]
+  testonly = true
+  sources = [ "composebox_egtest.mm" ]
+  deps = [
+    ":ui_constants",
+    "//ios/chrome/browser/omnibox/public:constants",
+    "//ios/chrome/browser/shared/public/features",
+    "//ios/chrome/test/earl_grey:eg_test_support+eg2",
+    "//ios/testing/earl_grey:eg_test_support+eg2",
+    "//net:test_support",
+  ]
+}
diff --git a/ios/chrome/browser/composebox/ui/composebox_egtest.mm b/ios/chrome/browser/composebox/ui/composebox_egtest.mm
new file mode 100644
index 0000000..1d30b04f
--- /dev/null
+++ b/ios/chrome/browser/composebox/ui/composebox_egtest.mm
@@ -0,0 +1,102 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import <XCTest/XCTest.h>
+
+#import "ios/chrome/browser/composebox/ui/composebox_ui_constants.h"
+#import "ios/chrome/browser/omnibox/public/omnibox_constants.h"
+#import "ios/chrome/browser/shared/public/features/features.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey.h"
+#import "ios/chrome/test/earl_grey/chrome_earl_grey_ui.h"
+#import "ios/chrome/test/earl_grey/chrome_matchers.h"
+#import "ios/chrome/test/earl_grey/chrome_test_case.h"
+#import "ios/testing/earl_grey/earl_grey_test.h"
+#import "net/test/embedded_test_server/embedded_test_server.h"
+
+namespace {
+
+// Matcher for the Composebox.
+id<GREYMatcher> ComposeboxMatcher() {
+  return grey_accessibilityID(kComposeboxAccessibilityIdentifier);
+}
+
+// Matcher for the clear button in the Composebox.
+id<GREYMatcher> ComposeboxClearButtonMatcher() {
+  return grey_allOf(
+      grey_accessibilityID(kOmniboxClearButtonAccessibilityIdentifier),
+      grey_sufficientlyVisible(), nil);
+}
+
+}  // namespace
+
+@interface ComposeboxTestCase : ChromeTestCase
+@end
+
+@implementation ComposeboxTestCase
+
+- (AppLaunchConfiguration)appConfigurationForTestCase {
+  AppLaunchConfiguration config = [super appConfigurationForTestCase];
+  config.features_enabled.push_back(kComposeboxIOS);
+  return config;
+}
+
+- (void)setUp {
+  [super setUp];
+  GREYAssertTrue(self.testServer->Start(), @"Test server failed to start.");
+}
+
+// Tests that the Composebox is visible when tapping the omnibox.
+- (void)testComposeboxVisibility {
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGreyUI focusOmnibox];
+
+  // Clear the omnibox.
+  [[EarlGrey selectElementWithMatcher:ComposeboxClearButtonMatcher()]
+      performAction:grey_tap()];
+
+  // Check for Composebox elements.
+  // Plus button is visible.
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_accessibilityID(kComposeboxPlusButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_sufficientlyVisible()];
+  // Mic button is visible.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityID(
+                                   kComposeboxMicButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_sufficientlyVisible()];
+  // Send button is not visible.
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_accessibilityID(kComposeboxSendButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_notVisible()];
+}
+
+// Tests that typing in the Composebox shows the Send button.
+- (void)testComposeboxSendButtonVisibility {
+  [ChromeEarlGrey loadURL:self.testServer->GetURL("/")];
+  [ChromeEarlGreyUI focusOmnibox];
+
+  // Type some text.
+  [[EarlGrey selectElementWithMatcher:ComposeboxMatcher()]
+      performAction:grey_typeText(@"test")];
+
+  // Send button is visible.
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_accessibilityID(kComposeboxSendButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_sufficientlyVisible()];
+  // Plus button is visible.
+  [[EarlGrey
+      selectElementWithMatcher:
+          grey_accessibilityID(kComposeboxPlusButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_sufficientlyVisible()];
+  // Mic button is not visible.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityID(
+                                   kComposeboxMicButtonAccessibilityIdentifier)]
+      assertWithMatcher:grey_notVisible()];
+}
+
+@end
diff --git a/ios/chrome/browser/composebox/ui/composebox_input_plate_consumer.h b/ios/chrome/browser/composebox/ui/composebox_input_plate_consumer.h
index 4082275..ca8ea45 100644
--- a/ios/chrome/browser/composebox/ui/composebox_input_plate_consumer.h
+++ b/ios/chrome/browser/composebox/ui/composebox_input_plate_consumer.h
@@ -19,10 +19,14 @@
 - (void)updateState:(ComposeboxInputItemState)state
     forItemWithIdentifier:(const base::UnguessableToken&)identifier;
 
+// Sets whether AI Mode is currently eligible.
+- (void)setEligibleToAIMode:(BOOL)eligibleToAIMode;
+
 // Sets whether to show the Send button vs the other enabled controls.
 - (void)setShowsSendButton:(BOOL)showsSendButton;
 
-// Sets whether to show the extended controls (Plus button and Lens button).
+// Sets whether to show the extended controls (Plus button and Lens button),
+// based on the current default search engine.
 - (void)setShowsExtendedControls:(BOOL)showsExtendedControls;
 
 // Sets whether AI mode is enabled.
@@ -58,6 +62,12 @@
 // Sets whether the create image actions are disabled.
 - (void)disableCreateImageActions:(BOOL)disabled;
 
+// Sets whether the camera actions are disabled.
+- (void)disableCameraActions:(BOOL)disabled;
+
+// Sets whether the gallery actions are disabled.
+- (void)disableGalleryActions:(BOOL)disabled;
+
 @end
 
 #endif  // IOS_CHROME_BROWSER_COMPOSEBOX_UI_COMPOSEBOX_INPUT_PLATE_CONSUMER_H_
diff --git a/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm b/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm
index 1de414f..5cc676b 100644
--- a/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm
+++ b/ios/chrome/browser/composebox/ui/composebox_input_plate_view_controller.mm
@@ -20,6 +20,7 @@
 #import "ios/chrome/browser/composebox/ui/composebox_input_item_view.h"
 #import "ios/chrome/browser/composebox/ui/composebox_input_plate_mutator.h"
 #import "ios/chrome/browser/composebox/ui/composebox_snackbar_presenter.h"
+#import "ios/chrome/browser/composebox/ui/composebox_ui_constants.h"
 #import "ios/chrome/browser/omnibox/ui/text_field_view_containing.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 #import "ios/chrome/browser/shared/ui/elements/extended_touch_target_button.h"
@@ -148,6 +149,8 @@
       _dataSource;
   /// The view containing the input text field and action buttons.
   UIView* _inputPlateContainerView;
+  /// Whether the user is eligible for AI mode.
+  BOOL _eligibleToAIMode;
   /// The button to toggle AI mode.
   UIButton* _aimButton;
   UIImageView* _aimButtonXIndicator;
@@ -182,6 +185,10 @@
   /// Create image action state.
   BOOL _createImageActionsHidden;
   BOOL _createImageActionsDisabled;
+  /// Camera action state.
+  BOOL _cameraActionsDisabled;
+  /// Gallery action state.
+  BOOL _galleryActionsDisabled;
   /// Container for the omnibox.
   UIView* _omniboxContainer;
 
@@ -290,6 +297,7 @@
 - (void)setEditView:(UIView<TextFieldViewContaining>*)editView {
   _editView = editView;
   _editView.translatesAutoresizingMaskIntoConstraints = NO;
+  _editView.accessibilityIdentifier = kComposeboxAccessibilityIdentifier;
   [_omniboxContainer addSubview:editView];
   AddSameConstraints(_editView, _omniboxContainer);
 }
@@ -378,6 +386,14 @@
   }
 }
 
+- (void)setEligibleToAIMode:(BOOL)eligibleToAIMode {
+  if (_eligibleToAIMode == eligibleToAIMode) {
+    return;
+  }
+  _eligibleToAIMode = eligibleToAIMode;
+  [self updateButtonsVisibility];
+}
+
 - (void)setShowsSendButton:(BOOL)showsSendButton {
   if (_showsSendButton == showsSendButton) {
     return;
@@ -491,6 +507,22 @@
   [self updatePlusButtonItems];
 }
 
+- (void)disableCameraActions:(BOOL)disabled {
+  if (_cameraActionsDisabled == disabled) {
+    return;
+  }
+  _cameraActionsDisabled = disabled;
+  [self updatePlusButtonItems];
+}
+
+- (void)disableGalleryActions:(BOOL)disabled {
+  if (_galleryActionsDisabled == disabled) {
+    return;
+  }
+  _galleryActionsDisabled = disabled;
+  [self updatePlusButtonItems];
+}
+
 #pragma mark - Actions
 
 - (void)galleryButtonTapped {
@@ -693,7 +725,7 @@
 }
 
 - (void)updateButtonsVisibility {
-  _plusButton.hidden = !_showsExtendedControls;
+  _plusButton.hidden = !_showsExtendedControls || !_eligibleToAIMode;
   _aimButton.hidden = !self.AIModeEnabled;
   _micButton.hidden = _showsSendButton;
   _lensButton.hidden = _showsSendButton || !_showsExtendedControls;
@@ -824,6 +856,8 @@
       forState:UIControlStateNormal];
   plusButton.translatesAutoresizingMaskIntoConstraints = NO;
   plusButton.tintColor = [UIColor colorNamed:kTextPrimaryColor];
+  plusButton.accessibilityIdentifier =
+      kComposeboxPlusButtonAccessibilityIdentifier;
 
   AddSizeConstraints(plusButton,
                      CGSizeMake(kAIMButtonHeight, kAIMButtonHeight));
@@ -858,6 +892,8 @@
                            CGAffineTransformMakeScale(scale, scale);
                      }];
   };
+  sendButton.accessibilityIdentifier =
+      kComposeboxSendButtonAccessibilityIdentifier;
 
   [sendButton addTarget:self
                  action:@selector(sendButtonTapped)
@@ -873,6 +909,8 @@
       [self createButtonWithImage:CustomSymbolWithPointSize(
                                       kVoiceSymbol, kSymbolActionPointSize)];
   micButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
+  micButton.accessibilityIdentifier =
+      kComposeboxMicButtonAccessibilityIdentifier;
 
   [micButton addTarget:self
                 action:@selector(micButtonTapped)
@@ -886,6 +924,9 @@
       createButtonWithImage:CustomSymbolWithPointSize(kCameraLensSymbol,
                                                       kSymbolActionPointSize)];
   lensButton.imageView.contentMode = UIViewContentModeScaleAspectFit;
+  lensButton.accessibilityIdentifier =
+      kComposeboxLensButtonAccessibilityIdentifier;
+
   [lensButton addTarget:self
                  action:@selector(lensButtonTapped)
        forControlEvents:UIControlEventTouchUpInside];
@@ -1049,6 +1090,18 @@
   }
   createImageAction.attributes = createImageAttributes;
 
+  UIMenuElementAttributes galleryAttributes = 0;
+  if (_galleryActionsDisabled) {
+    galleryAttributes |= UIMenuElementAttributesDisabled;
+  }
+  galleryAction.attributes = galleryAttributes;
+
+  UIMenuElementAttributes cameraAttributes = 0;
+  if (_cameraActionsDisabled) {
+    cameraAttributes |= UIMenuElementAttributesDisabled;
+  }
+  cameraAction.attributes = cameraAttributes;
+
   UIMenu* attachmentMenu =
       [UIMenu menuWithTitle:@""
                       image:nil
diff --git a/ios/chrome/browser/composebox/ui/composebox_ui_constants.h b/ios/chrome/browser/composebox/ui/composebox_ui_constants.h
new file mode 100644
index 0000000..d0d9e625
--- /dev/null
+++ b/ios/chrome/browser/composebox/ui/composebox_ui_constants.h
@@ -0,0 +1,22 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_COMPOSEBOX_UI_COMPOSEBOX_UI_CONSTANTS_H_
+#define IOS_CHROME_BROWSER_COMPOSEBOX_UI_COMPOSEBOX_UI_CONSTANTS_H_
+
+#import <Foundation/Foundation.h>
+
+// Accessibility identifier for the composebox.
+extern NSString* const kComposeboxAccessibilityIdentifier;
+
+// Accessibility identifier for the plus button in the composebox.
+extern NSString* const kComposeboxPlusButtonAccessibilityIdentifier;
+// Accessibility identifier for the microphone button in the composebox.
+extern NSString* const kComposeboxMicButtonAccessibilityIdentifier;
+// Accessibility identifier for the Lens button in the composebox.
+extern NSString* const kComposeboxLensButtonAccessibilityIdentifier;
+// Accessibility identifier for the send button in the composebox.
+extern NSString* const kComposeboxSendButtonAccessibilityIdentifier;
+
+#endif  // IOS_CHROME_BROWSER_COMPOSEBOX_UI_COMPOSEBOX_UI_CONSTANTS_H_
diff --git a/ios/chrome/browser/composebox/ui/composebox_ui_constants.mm b/ios/chrome/browser/composebox/ui/composebox_ui_constants.mm
new file mode 100644
index 0000000..b7f47c7
--- /dev/null
+++ b/ios/chrome/browser/composebox/ui/composebox_ui_constants.mm
@@ -0,0 +1,17 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/composebox/ui/composebox_ui_constants.h"
+
+NSString* const kComposeboxAccessibilityIdentifier =
+    @"kComposeboxAccessibilityIdentifier";
+
+NSString* const kComposeboxPlusButtonAccessibilityIdentifier =
+    @"kComposeboxPlusButtonAccessibilityIdentifier";
+NSString* const kComposeboxMicButtonAccessibilityIdentifier =
+    @"kComposeboxMicButtonAccessibilityIdentifier";
+NSString* const kComposeboxLensButtonAccessibilityIdentifier =
+    @"kComposeboxLensButtonAccessibilityIdentifier";
+NSString* const kComposeboxSendButtonAccessibilityIdentifier =
+    @"kComposeboxSendButtonAccessibilityIdentifier";
diff --git a/ios/chrome/browser/intelligence/actuation/BUILD.gn b/ios/chrome/browser/intelligence/actuation/BUILD.gn
new file mode 100644
index 0000000..d796cf3
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/BUILD.gn
@@ -0,0 +1,17 @@
+# Copyright 2025 The Chromium Authors
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+source_set("actuation") {
+  sources = [
+    "tab_actions.h",
+    "tab_actions.mm",
+  ]
+  deps = [
+    "//base",
+    "//components/tab_groups",
+    "//ios/chrome/browser/saved_tab_groups/ui:utils",
+    "//ios/chrome/browser/shared/model/web_state_list",
+    "//ios/web/public",
+  ]
+}
diff --git a/ios/chrome/browser/intelligence/actuation/tab_actions.h b/ios/chrome/browser/intelligence/actuation/tab_actions.h
new file mode 100644
index 0000000..e92e474
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/tab_actions.h
@@ -0,0 +1,24 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_TAB_ACTIONS_H_
+#define IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_TAB_ACTIONS_H_
+
+#import <set>
+
+#import "components/tab_groups/tab_group_visual_data.h"
+
+class WebStateList;
+
+// Ungroups the tabs at the given indices within the WebStateList.
+void UngroupTabs(const std::set<int>& indices_to_ungroup,
+                 WebStateList* web_state_list);
+
+// Creates a new tab group in the WebStateList based on the provided
+// set of indices and visual data.
+void CreateTabGroup(const std::set<int>& indices,
+                    const tab_groups::TabGroupVisualData& visual_data,
+                    WebStateList* web_state_list);
+
+#endif  // IOS_CHROME_BROWSER_INTELLIGENCE_ACTUATION_TAB_ACTIONS_H_
diff --git a/ios/chrome/browser/intelligence/actuation/tab_actions.mm b/ios/chrome/browser/intelligence/actuation/tab_actions.mm
new file mode 100644
index 0000000..913353b
--- /dev/null
+++ b/ios/chrome/browser/intelligence/actuation/tab_actions.mm
@@ -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.
+
+#import "ios/chrome/browser/intelligence/actuation/tab_actions.h"
+
+#import "base/strings/strcat.h"
+#import "base/strings/utf_string_conversions.h"
+#import "components/tab_groups/tab_group_id.h"
+#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
+
+void UngroupTabs(const std::set<int>& indices_to_ungroup,
+                 WebStateList* web_state_list) {
+  CHECK(web_state_list);
+  web_state_list->RemoveFromGroups(indices_to_ungroup);
+}
+
+void CreateTabGroup(const std::set<int>& indices_for_group,
+                    const tab_groups::TabGroupVisualData& visual_data,
+                    WebStateList* web_state_list) {
+  CHECK(web_state_list);
+
+  if (indices_for_group.empty()) {
+    return;
+  }
+
+  tab_groups::TabGroupId group_id = tab_groups::TabGroupId::GenerateNew();
+  web_state_list->CreateGroup(indices_for_group, visual_data, group_id);
+}
diff --git a/ios/chrome/browser/intelligence/smart_tab_grouping/utils/BUILD.gn b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/BUILD.gn
new file mode 100644
index 0000000..bd4c7bb
--- /dev/null
+++ b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/BUILD.gn
@@ -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.
+
+source_set("utils") {
+  sources = [
+    "smart_tab_grouping_utils.h",
+    "smart_tab_grouping_utils.mm",
+  ]
+  deps = [
+    "//base",
+    "//components/optimization_guide/proto:optimization_guide_proto",
+    "//components/optimization_guide/proto:optimization_guide_proto_gen",
+    "//components/tab_groups",
+    "//ios/chrome/browser/intelligence/actuation",
+    "//ios/chrome/browser/saved_tab_groups/ui:utils",
+    "//ios/chrome/browser/shared/model/web_state_list",
+    "//ios/web/public",
+  ]
+}
diff --git a/ios/chrome/browser/intelligence/smart_tab_grouping/utils/DEPS b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/DEPS
new file mode 100644
index 0000000..4ae9413
--- /dev/null
+++ b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+  "+ios/chrome/browser/saved_tab_groups/ui/tab_group_utils.h",
+]
+
diff --git a/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.h b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.h
new file mode 100644
index 0000000..6fe9a52
--- /dev/null
+++ b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.h
@@ -0,0 +1,23 @@
+// 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_INTELLIGENCE_SMART_TAB_GROUPING_UTILS_SMART_TAB_GROUPING_UTILS_H_
+#define IOS_CHROME_BROWSER_INTELLIGENCE_SMART_TAB_GROUPING_UTILS_SMART_TAB_GROUPING_UTILS_H_
+
+namespace optimization_guide {
+namespace proto {
+class IosSmartTabGroupingResponse;
+}  // namespace proto
+}  // namespace optimization_guide
+
+class WebStateList;
+
+// Applies the smart tab group suggestions from the response proto to the
+// provided WebStateList.
+void ApplySmartTabGroupResponse(
+    const optimization_guide::proto::IosSmartTabGroupingResponse&
+        response_proto,
+    WebStateList* web_state_list);
+
+#endif  // IOS_CHROME_BROWSER_INTELLIGENCE_SMART_TAB_GROUPING_UTILS_SMART_TAB_GROUPING_UTILS_H_
diff --git a/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.mm b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.mm
new file mode 100644
index 0000000..d10c3fa
--- /dev/null
+++ b/ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.mm
@@ -0,0 +1,107 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/intelligence/smart_tab_grouping/utils/smart_tab_grouping_utils.h"
+
+#import <set>
+
+#import "base/strings/strcat.h"
+#import "base/strings/utf_string_conversions.h"
+#import "components/optimization_guide/proto/features/ios_smart_tab_grouping.pb.h"
+#import "components/tab_groups/tab_group_color.h"
+#import "components/tab_groups/tab_group_visual_data.h"
+#import "ios/chrome/browser/intelligence/actuation/tab_actions.h"
+#import "ios/chrome/browser/saved_tab_groups/ui/tab_group_utils.h"
+#import "ios/chrome/browser/shared/model/web_state_list/web_state_list.h"
+#import "ios/web/public/web_state.h"
+
+void ApplySmartTabGroupResponse(
+    const optimization_guide::proto::IosSmartTabGroupingResponse&
+        response_proto,
+    WebStateList* web_state_list) {
+  CHECK(web_state_list);
+
+  WebStateList::ScopedBatchOperation lock =
+      web_state_list->StartBatchOperation();
+
+  // Collect indices of all tabs currently in any group to ungroup them to
+  // ensure a clean state before applying the new smart group suggestions.
+  std::set<int> indices_to_ungroup;
+  for (int i = 0; i < web_state_list->count(); ++i) {
+    if (web_state_list->GetGroupOfWebStateAt(i)) {
+      indices_to_ungroup.insert(i);
+    }
+  }
+
+  if (!indices_to_ungroup.empty()) {
+    UngroupTabs(indices_to_ungroup, web_state_list);
+  }
+
+  // Map tab unique IDs to WebState pointers. This is necessary because
+  // tab indices in the WebStateList will change as tabs are moved into new
+  // groups. The unique ID provides a stable identifier for each tab.
+  std::map<int64_t, web::WebState*> id_to_web_state;
+  for (int i = 0; i < web_state_list->count(); ++i) {
+    web::WebState* web_state = web_state_list->GetWebStateAt(i);
+    if (web_state) {
+      id_to_web_state[web_state->GetUniqueIdentifier().identifier()] =
+          web_state;
+    }
+  }
+
+  const std::vector<tab_groups::TabGroupColorId> available_colors =
+      tab_groups::AllPossibleTabGroupColors();
+  const size_t num_group_colors = available_colors.size();
+  int group_color_index = 0;
+  // Iterate through each tab group suggestion in the response proto.
+  // For each suggestion, gather the tab indices, create the group's visual data
+  // (title with emoji and label, and colour), and create the tab group.
+  for (const auto& group_proto : response_proto.tab_groups()) {
+    if (group_proto.tab_ids().empty()) {
+      continue;
+    }
+
+    std::set<int> indices_in_group;
+
+    for (int64_t tab_id : group_proto.tab_ids()) {
+      auto id_iterator = id_to_web_state.find(tab_id);
+      if (id_iterator == id_to_web_state.end()) {
+        continue;
+      }
+
+      web::WebState* web_state = id_iterator->second;
+
+      int current_index = web_state_list->GetIndexOfWebState(web_state);
+
+      if (current_index != WebStateList::kInvalidIndex) {
+        // Only include the tab in this new group if it's not already
+        // part of a group. This check prevents a tab from being added to
+        // multiple groups, as a tab can only belong to one group at a time.
+        // This check is done in case the model's response repeated tab IDs in
+        // different tab groups.
+        if (!web_state_list->GetGroupOfWebStateAt(current_index)) {
+          indices_in_group.insert(current_index);
+        }
+      }
+    }
+
+    if (indices_in_group.empty()) {
+      continue;
+    }
+
+    std::string title_with_emoji =
+        group_proto.emoji().empty()
+            ? group_proto.label()
+            : base::StrCat({group_proto.emoji(), " ", group_proto.label()});
+    tab_groups::TabGroupColorId color =
+        available_colors[group_color_index % num_group_colors];
+
+    const tab_groups::TabGroupVisualData group_visual_data(
+        base::UTF8ToUTF16(title_with_emoji), color);
+
+    CreateTabGroup(indices_in_group, group_visual_data, web_state_list);
+
+    group_color_index++;
+  }
+}
diff --git a/ios/chrome/browser/location_bar/ui_bundled/location_bar_coordinator.mm b/ios/chrome/browser/location_bar/ui_bundled/location_bar_coordinator.mm
index b2b5f99..3574c809 100644
--- a/ios/chrome/browser/location_bar/ui_bundled/location_bar_coordinator.mm
+++ b/ios/chrome/browser/location_bar/ui_bundled/location_bar_coordinator.mm
@@ -251,27 +251,30 @@
   _locationBarModel = std::make_unique<LocationBarModelImpl>(
       _locationBarModelDelegate.get(), kMaxURLDisplayChars);
 
-  self.omniboxCoordinator = [[OmniboxCoordinator alloc]
-      initWithBaseViewController:nil
-                         browser:self.browser
-                   omniboxClient:std::make_unique<ChromeOmniboxClientIOS>(
-                                     _locationBar.get(), self.browser,
-                                     feature_engagement::TrackerFactory::
-                                         GetForProfile(self.profile))
-             presentationContext:OmniboxPresentationContext::kLocationBar];
-  self.omniboxCoordinator.focusDelegate = self.delegate;
+  if (!IsComposeboxIOSEnabled()) {
+    self.omniboxCoordinator = [[OmniboxCoordinator alloc]
+        initWithBaseViewController:nil
+                           browser:self.browser
+                     omniboxClient:std::make_unique<ChromeOmniboxClientIOS>(
+                                       _locationBar.get(), self.browser,
+                                       feature_engagement::TrackerFactory::
+                                           GetForProfile(self.profile))
+               presentationContext:OmniboxPresentationContext::kLocationBar];
+    self.omniboxCoordinator.focusDelegate = self.delegate;
 
-  self.omniboxCoordinator.presenterDelegate = self.popupPresenterDelegate;
-  [self.omniboxCoordinator start];
+    self.omniboxCoordinator.presenterDelegate = self.popupPresenterDelegate;
+    [self.omniboxCoordinator start];
 
-  [self.omniboxCoordinator.managedViewController
-      willMoveToParentViewController:self.viewController];
-  [self.viewController
-      addChildViewController:self.omniboxCoordinator.managedViewController];
-  [self.viewController setEditView:self.omniboxCoordinator.editView];
-  [self.omniboxCoordinator.managedViewController
-      didMoveToParentViewController:self.viewController];
-  self.viewController.offsetProvider = [self.omniboxCoordinator offsetProvider];
+    [self.omniboxCoordinator.managedViewController
+        willMoveToParentViewController:self.viewController];
+    [self.viewController
+        addChildViewController:self.omniboxCoordinator.managedViewController];
+    [self.viewController setEditView:self.omniboxCoordinator.editView];
+    [self.omniboxCoordinator.managedViewController
+        didMoveToParentViewController:self.viewController];
+    self.viewController.offsetProvider =
+        [self.omniboxCoordinator offsetProvider];
+  }
 
   if (IsAskGeminiChipEnabled() || IsProactiveSuggestionsFrameworkEnabled() ||
       IsLocationBarBadgeMigrationEnabled()) {
@@ -626,6 +629,7 @@
     id<BrowserCoordinatorCommands> commands = HandlerForProtocol(
         self.browser->GetCommandDispatcher(), BrowserCoordinatorCommands);
     [commands hideComposeboxImmediately:NO];
+    return;
   }
   if (self.isCancellingOmniboxEdit) {
     return;
diff --git a/ios/chrome/browser/location_bar/ui_bundled/location_bar_view_controller.mm b/ios/chrome/browser/location_bar/ui_bundled/location_bar_view_controller.mm
index 6c86514..da3a1d7 100644
--- a/ios/chrome/browser/location_bar/ui_bundled/location_bar_view_controller.mm
+++ b/ios/chrome/browser/location_bar/ui_bundled/location_bar_view_controller.mm
@@ -338,11 +338,13 @@
       [[UIIndirectScribbleInteraction alloc] initWithDelegate:self];
   [_locationBarSteadyView addInteraction:scribbleInteraction];
 
-  DCHECK(self.editView) << "The edit view must be set at this point";
+  if (!IsComposeboxIOSEnabled()) {
+    DCHECK(self.editView) << "The edit view must be set at this point";
 
-  [self.view addSubview:self.editView];
-  self.editView.translatesAutoresizingMaskIntoConstraints = NO;
-  AddSameConstraints(self.editView, self.view);
+    [self.view addSubview:self.editView];
+    self.editView.translatesAutoresizingMaskIntoConstraints = NO;
+    AddSameConstraints(self.editView, self.view);
+  }
 
   [self.view addSubview:self.locationBarSteadyView];
   self.locationBarSteadyView.translatesAutoresizingMaskIntoConstraints = NO;
diff --git a/ios/chrome/browser/omnibox/public/omnibox_constants.h b/ios/chrome/browser/omnibox/public/omnibox_constants.h
index 7adf7753..9de70f2 100644
--- a/ios/chrome/browser/omnibox/public/omnibox_constants.h
+++ b/ios/chrome/browser/omnibox/public/omnibox_constants.h
@@ -9,6 +9,8 @@
 
 extern const CGFloat kOmniboxPlaceholderAlpha;
 
+extern NSString* const kOmniboxClearButtonAccessibilityIdentifier;
+
 extern NSString* const kOmniboxLeadingImageDefaultAccessibilityIdentifier;
 
 extern NSString* const kOmniboxLeadingImageEmptyTextAccessibilityIdentifier;
diff --git a/ios/chrome/browser/omnibox/public/omnibox_constants.mm b/ios/chrome/browser/omnibox/public/omnibox_constants.mm
index 8767e46b..66c529d 100644
--- a/ios/chrome/browser/omnibox/public/omnibox_constants.mm
+++ b/ios/chrome/browser/omnibox/public/omnibox_constants.mm
@@ -6,6 +6,9 @@
 
 const CGFloat kOmniboxPlaceholderAlpha = 0.3;
 
+NSString* const kOmniboxClearButtonAccessibilityIdentifier =
+    @"OmniboxClearButtonAccessibilityIdentifier";
+
 NSString* const kOmniboxLeadingImageDefaultAccessibilityIdentifier =
     @"OmniboxLeadingImageDefaultAccessibilityIdentifier";
 
diff --git a/ios/chrome/browser/omnibox/ui/omnibox_container_view.mm b/ios/chrome/browser/omnibox/ui/omnibox_container_view.mm
index b5ad460..050b4e8 100644
--- a/ios/chrome/browser/omnibox/ui/omnibox_container_view.mm
+++ b/ios/chrome/browser/omnibox/ui/omnibox_container_view.mm
@@ -141,7 +141,7 @@
   clear_button.configuration = conf;
   clear_button.tintColor = [UIColor colorNamed:kTextfieldPlaceholderColor];
   SetA11yLabelAndUiAutomationName(clear_button, IDS_IOS_ACCNAME_CLEAR_TEXT,
-                                  @"Clear Text");
+                                  kOmniboxClearButtonAccessibilityIdentifier);
   clear_button.pointerInteractionEnabled = YES;
   clear_button.pointerStyleProvider =
       CreateLiftEffectCirclePointerStyleProvider();
diff --git a/ios/chrome/browser/search_engine_choice/search_engine_choice_learn_more/ui/search_engine_choice_learn_more_view_controller.mm b/ios/chrome/browser/search_engine_choice/search_engine_choice_learn_more/ui/search_engine_choice_learn_more_view_controller.mm
index 04afea4..c7ff5f2 100644
--- a/ios/chrome/browser/search_engine_choice/search_engine_choice_learn_more/ui/search_engine_choice_learn_more_view_controller.mm
+++ b/ios/chrome/browser/search_engine_choice/search_engine_choice_learn_more/ui/search_engine_choice_learn_more_view_controller.mm
@@ -259,6 +259,12 @@
   ]];
 }
 
+- (void)viewDidAppear:(BOOL)animated {
+  [super viewDidAppear:animated];
+  UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification,
+                                  self.navigationController.navigationBar);
+}
+
 #pragma mark - UITextViewDelegate
 
 - (void)textViewDidChangeSelection:(UITextView*)textView {
diff --git a/ios/chrome/browser/search_engine_choice/ui/search_engine_choice_view_controller.mm b/ios/chrome/browser/search_engine_choice/ui/search_engine_choice_view_controller.mm
index 6199de0..afe51579 100644
--- a/ios/chrome/browser/search_engine_choice/ui/search_engine_choice_view_controller.mm
+++ b/ios/chrome/browser/search_engine_choice/ui/search_engine_choice_view_controller.mm
@@ -166,7 +166,8 @@
 
 }  // namespace
 
-@interface SearchEngineChoiceViewController () <UITextViewDelegate>
+@interface SearchEngineChoiceViewController () <UITextViewDelegate,
+                                                UITextDragDelegate>
 @end
 
 @implementation SearchEngineChoiceViewController {
@@ -329,6 +330,7 @@
   // The text alignment needs to be set after the setting the attributed text.
   subtitle1TextView.textAlignment = NSTextAlignmentCenter;
   subtitle1TextView.delegate = self;
+  subtitle1TextView.textDragDelegate = self;
 
   NSLayoutYAxisAnchor* subtitleBottomAnchor = subtitle1TextView.bottomAnchor;
 
@@ -1085,6 +1087,21 @@
   textView.selectedTextRange = nil;
 }
 
+- (UITextItemMenuConfiguration*)textView:(UITextView*)textView
+            menuConfigurationForTextItem:(UITextItem*)textItem
+                             defaultMenu:(UIMenu*)defaultMenu {
+  // Disable Context menu as this is an internal link.
+  return nil;
+}
+
+#pragma mark - UITextDragDelegate
+
+- (NSArray<UIDragItem*>*)textDraggableView:
+                             (UIView<UITextDraggable>*)textDraggableView
+                              itemsForDrag:(id<UITextDragRequest>)dragRequest {
+  return @[];
+}
+
 #pragma mark - UIContentContainer
 
 - (void)viewWillTransitionToSize:(CGSize)size
diff --git a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_table_egtest.mm b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_table_egtest.mm
index a71cf74..0fd4feae 100644
--- a/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_table_egtest.mm
+++ b/ios/chrome/browser/settings/ui_bundled/google_services/manage_accounts/manage_accounts_table_egtest.mm
@@ -196,7 +196,8 @@
 // identity. And finally the remove identity confirmation dialog is opened a
 // third time to remove a second identity.
 // The goal of this test is to confirm the dialog can be opened several times.
-- (void)testRemoveAccountSeveralTime {
+// TODO(crbug.com/460742009): Test is flaky.
+- (void)FLAKY_testRemoveAccountSeveralTime {
   FakeSystemIdentity* fakeIdentity1 = [FakeSystemIdentity fakeIdentity1];
   FakeSystemIdentity* fakeIdentity2 = [FakeSystemIdentity fakeIdentity2];
   FakeSystemIdentity* fakeIdentity3 = [FakeSystemIdentity fakeIdentity3];
@@ -218,12 +219,13 @@
 
   // Cancel it.
   if ([ChromeEarlGrey isIPadIdiom] || iOS26_OR_ABOVE()) {
-    // Cancel it by tapping on the backgrounded item.
+    // There is no Cancel button on ipad and on newer iOS versions.
+    // Tap on Remove fakeIdentity1 button to dismiss the alert.
     [[EarlGrey
-        selectElementWithMatcher:grey_allOf(grey_accessibilityLabel(
-                                                fakeIdentity1.userEmail),
-                                            grey_text(fakeIdentity1.userEmail),
-                                            grey_sufficientlyVisible(), nil)]
+        selectElementWithMatcher:
+            grey_accessibilityID(
+                [kSettingsAccountsRemoveAccountButtonAccessibilityIdentifier
+                    stringByAppendingString:fakeIdentity1.userEmail])]
         performAction:grey_tap()];
   } else {
     [[EarlGrey selectElementWithMatcher:chrome_test_util::CancelButton()]
diff --git a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
index 3b798af4a..eae5a30 100644
--- a/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
+++ b/ios/chrome/browser/settings/ui_bundled/settings_table_view_controller.mm
@@ -449,6 +449,9 @@
 
 - (void)viewDidLoad {
   [super viewDidLoad];
+  if (_settingsAreDismissed) {
+    return;
+  }
 
   self.tableView.accessibilityIdentifier = kSettingsTableViewId;
 
diff --git a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
index 89bcbe0..4d9617ba 100644
--- a/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
+++ b/ios/chrome/browser/shared/coordinator/scene/scene_controller.mm
@@ -1327,54 +1327,8 @@
 
   // Create and start the BVC.
   [self.browserViewWrangler createMainCoordinatorAndInterface];
-  Browser* mainBrowser = self.browserViewWrangler.mainInterface.browser;
 
-  PromosManager* promosManager = PromosManagerFactory::GetForProfile(profile);
-
-  DefaultBrowserPromoSceneAgent* defaultBrowserAgent =
-      [[DefaultBrowserPromoSceneAgent alloc] init];
-  defaultBrowserAgent.promosManager = promosManager;
-  [sceneState addAgent:defaultBrowserAgent];
-  [sceneState
-      addAgent:[[NonModalDefaultBrowserPromoSchedulerSceneAgent alloc] init]];
-
-  // Add scene agents that require CommandDispatcher.
-  CommandDispatcher* mainCommandDispatcher =
-      mainBrowser->GetCommandDispatcher();
-  id<ApplicationCommands> applicationCommandsHandler =
-      HandlerForProtocol(mainCommandDispatcher, ApplicationCommands);
-  id<PolicyChangeCommands> policyChangeCommandsHandler =
-      HandlerForProtocol(mainCommandDispatcher, PolicyChangeCommands);
-
-  [sceneState
-      addAgent:[[SigninPolicySceneAgent alloc]
-                       initWithSceneUIProvider:self
-                    applicationCommandsHandler:applicationCommandsHandler
-                   policyChangeCommandsHandler:policyChangeCommandsHandler]];
-
-  enterprise_idle::IdleService* idleService =
-      enterprise_idle::IdleServiceFactory::GetForProfile(profile);
-  id<SnackbarCommands> snackbarCommandsHandler =
-      static_cast<id<SnackbarCommands>>(mainCommandDispatcher);
-
-  [sceneState addAgent:[[IdleTimeoutPolicySceneAgent alloc]
-                              initWithSceneUIProvider:self
-                           applicationCommandsHandler:applicationCommandsHandler
-                              snackbarCommandsHandler:snackbarCommandsHandler
-                                          idleService:idleService
-                                          mainBrowser:mainBrowser]];
-
-  // Now that the main browser's command dispatcher is created and the newly
-  // started UI coordinators have registered with it, inject it into the
-  // PolicyWatcherBrowserAgent so it can start monitoring UI-impacting policy
-  // changes.
-  PolicyWatcherBrowserAgent* policyWatcherAgent =
-      PolicyWatcherBrowserAgent::FromBrowser(self.mainInterface.browser);
-  _policyWatcherObserver = std::make_unique<base::ScopedObservation<
-      PolicyWatcherBrowserAgent, PolicyWatcherBrowserAgentObserverBridge>>(
-      _policyWatcherObserverBridge.get());
-  _policyWatcherObserver->Observe(policyWatcherAgent);
-  policyWatcherAgent->Initialize(policyChangeCommandsHandler);
+  [self addAgents];
 
   self.screenshotDelegate = [[ScreenshotDelegate alloc]
       initWithBrowserProviderInterface:self.browserViewWrangler];
@@ -1386,44 +1340,6 @@
 
   // Make sure the GeolocationManager is created to observe permission events.
   [GeolocationManager sharedInstance];
-
-  if (ShouldPromoManagerDisplayPromos()) {
-    [sceneState addAgent:[[PromosManagerSceneAgent alloc]
-                             initWithCommandDispatcher:mainCommandDispatcher]];
-  }
-
-  if (IsAppStoreRatingEnabled()) {
-    [sceneState addAgent:[[AppStoreRatingSceneAgent alloc]
-                             initWithPromosManager:promosManager]];
-  }
-
-  [sceneState addAgent:[[WhatsNewSceneAgent alloc]
-                           initWithPromosManager:promosManager]];
-
-  // Do not gate by feature flag so it can run for enabled -> disabled
-  // scenarios.
-  [sceneState addAgent:[[CredentialProviderPromoSceneAgent alloc]
-                           initWithPromosManager:promosManager]];
-
-  if (IsFullscreenSigninPromoManagerMigrationEnabled()) {
-    AuthenticationService* authService =
-        AuthenticationServiceFactory::GetForProfile(profile);
-    PrefService* prefService = profile->GetPrefs();
-    [sceneState
-        addAgent:
-            [[FullscreenSigninPromoSceneAgent alloc]
-                initWithPromosManager:promosManager
-                          authService:authService
-                      identityManager:IdentityManagerFactory::GetForProfile(
-                                          profile)
-                          syncService:SyncServiceFactory::GetForProfile(profile)
-                          prefService:prefService]];
-  }
-
-  if (IsPageActionMenuEnabled()) {
-    [sceneState addAgent:[[BWGPromoSceneAgent alloc]
-                             initWithPromosManager:promosManager]];
-  }
 }
 
 // Determines the mode (normal or incognito) the initial UI should be in.
@@ -1869,6 +1785,98 @@
   }];
 }
 
+// Add scene agents that are not dependent on profileState.
+- (void)addAgents {
+  SceneState* sceneState = self.sceneState;
+  ProfileIOS* profile = self.profile;
+  Browser* mainBrowser = self.browserViewWrangler.mainInterface.browser;
+
+  PromosManager* promosManager = PromosManagerFactory::GetForProfile(profile);
+
+  DefaultBrowserPromoSceneAgent* defaultBrowserAgent =
+      [[DefaultBrowserPromoSceneAgent alloc] init];
+  defaultBrowserAgent.promosManager = promosManager;
+  [sceneState addAgent:defaultBrowserAgent];
+  [sceneState
+      addAgent:[[NonModalDefaultBrowserPromoSchedulerSceneAgent alloc] init]];
+
+  // Add scene agents that require CommandDispatcher.
+  CommandDispatcher* mainCommandDispatcher =
+      mainBrowser->GetCommandDispatcher();
+  id<ApplicationCommands> applicationCommandsHandler =
+      HandlerForProtocol(mainCommandDispatcher, ApplicationCommands);
+  id<PolicyChangeCommands> policyChangeCommandsHandler =
+      HandlerForProtocol(mainCommandDispatcher, PolicyChangeCommands);
+
+  [sceneState
+      addAgent:[[SigninPolicySceneAgent alloc]
+                       initWithSceneUIProvider:self
+                    applicationCommandsHandler:applicationCommandsHandler
+                   policyChangeCommandsHandler:policyChangeCommandsHandler]];
+
+  enterprise_idle::IdleService* idleService =
+      enterprise_idle::IdleServiceFactory::GetForProfile(profile);
+  id<SnackbarCommands> snackbarCommandsHandler =
+      static_cast<id<SnackbarCommands>>(mainCommandDispatcher);
+
+  [sceneState addAgent:[[IdleTimeoutPolicySceneAgent alloc]
+                              initWithSceneUIProvider:self
+                           applicationCommandsHandler:applicationCommandsHandler
+                              snackbarCommandsHandler:snackbarCommandsHandler
+                                          idleService:idleService
+                                          mainBrowser:mainBrowser]];
+
+  // Now that the main browser's command dispatcher is created and the newly
+  // started UI coordinators have registered with it, inject it into the
+  // PolicyWatcherBrowserAgent so it can start monitoring UI-impacting policy
+  // changes.
+  PolicyWatcherBrowserAgent* policyWatcherAgent =
+      PolicyWatcherBrowserAgent::FromBrowser(self.mainInterface.browser);
+  _policyWatcherObserver = std::make_unique<base::ScopedObservation<
+      PolicyWatcherBrowserAgent, PolicyWatcherBrowserAgentObserverBridge>>(
+      _policyWatcherObserverBridge.get());
+  _policyWatcherObserver->Observe(policyWatcherAgent);
+  policyWatcherAgent->Initialize(policyChangeCommandsHandler);
+
+  if (ShouldPromoManagerDisplayPromos()) {
+    [sceneState addAgent:[[PromosManagerSceneAgent alloc]
+                             initWithCommandDispatcher:mainCommandDispatcher]];
+  }
+
+  if (IsAppStoreRatingEnabled()) {
+    [sceneState addAgent:[[AppStoreRatingSceneAgent alloc]
+                             initWithPromosManager:promosManager]];
+  }
+
+  [sceneState addAgent:[[WhatsNewSceneAgent alloc]
+                           initWithPromosManager:promosManager]];
+
+  // Do not gate by feature flag so it can run for enabled -> disabled
+  // scenarios.
+  [sceneState addAgent:[[CredentialProviderPromoSceneAgent alloc]
+                           initWithPromosManager:promosManager]];
+
+  if (IsFullscreenSigninPromoManagerMigrationEnabled()) {
+    AuthenticationService* authService =
+        AuthenticationServiceFactory::GetForProfile(profile);
+    PrefService* prefService = profile->GetPrefs();
+    [sceneState
+        addAgent:
+            [[FullscreenSigninPromoSceneAgent alloc]
+                initWithPromosManager:promosManager
+                          authService:authService
+                      identityManager:IdentityManagerFactory::GetForProfile(
+                                          profile)
+                          syncService:SyncServiceFactory::GetForProfile(profile)
+                          prefService:prefService]];
+  }
+
+  if (IsPageActionMenuEnabled()) {
+    [sceneState addAgent:[[BWGPromoSceneAgent alloc]
+                             initWithPromosManager:promosManager]];
+  }
+}
+
 // Adds agents that may depend on profileState. Called after a profileState has
 // been connected to the sceneState.
 - (void)addProfileStateDependentAgents {
diff --git a/ios/chrome/browser/shared/ui/symbols/symbol_names.h b/ios/chrome/browser/shared/ui/symbols/symbol_names.h
index 1b29b2f..f9fb3fa 100644
--- a/ios/chrome/browser/shared/ui/symbols/symbol_names.h
+++ b/ios/chrome/browser/shared/ui/symbols/symbol_names.h
@@ -10,11 +10,12 @@
 #import "build/build_config.h"
 #import "ios/chrome/browser/shared/ui/symbols/buildflags.h"
 
-/// *******
+/// ****************************************************************************
 /// Import `symbols.h` and not this file directly.
-/// *******
+/// ****************************************************************************
 
-// Branded symbol names.
+// Branded image names.
+// TODO(crbug.com/465345831): Move image names out of this file.
 #if BUILDFLAG(IOS_USE_BRANDED_SYMBOLS)
 extern NSString* const kChromeAIHubHeaderImage;
 extern NSString* const kChromeDefaultBrowserIllustrationImage;
@@ -60,7 +61,9 @@
 extern NSString* const kGeminiNonBrandedLogoImage;
 #endif  // BUILDFLAG(IOS_USE_BRANDED_SYMBOLS)
 
+// ****************************************************************************
 // Custom symbol names.
+// ****************************************************************************
 extern NSString* const kPrivacySymbol;
 extern NSString* const kSafetyCheckSymbol;
 extern NSString* const kArrowClockWiseSymbol;
@@ -71,17 +74,14 @@
 extern NSString* const kEnterpriseSigninBannerSymbol;
 extern NSString* const kEnterpriseSymbol;
 extern NSString* const kPopupBadgeMinusSymbol;
-extern NSString* const kPhotoSymbol;
-extern NSString* const kPhotoBadgeArrowDownSymbol;
 extern NSString* const kPhotoBadgePlusSymbol;
 extern NSString* const kPhotoBadgeMagnifyingglassSymbol;
+extern NSString* const kLocationSymbol;
+extern NSString* const kShieldSymbol;
 extern NSString* const kReadingListSymbol;
 extern NSString* const kRecentTabsSymbol;
-extern NSString* const kTabGroupsSymbol;
 extern NSString* const kLanguageSymbol;
-extern NSString* const kLocationSymbol;
 extern NSString* const kPasswordSymbol;
-extern NSString* const kCropSymbol;
 #if !BUILDFLAG(IS_IOS_MACCATALYST)
 extern NSString* const kMulticolorPasswordSymbol;
 #endif  // BUILDFLAG(IS_IOS_MACCATALYST)
@@ -89,7 +89,6 @@
 extern NSString* const kCameraLensSymbol;
 extern NSString* const kDownTrendSymbol;
 extern NSString* const kUpTrendSymbol;
-extern NSString* const kShieldSymbol;
 extern NSString* const kCloudSlashSymbol;
 extern NSString* const kCloudAndArrowUpSymbol;
 extern NSString* const kDinoSymbol;
@@ -99,8 +98,6 @@
 extern NSString* const kTopOmniboxOptionSymbol;
 extern NSString* const kBottomOmniboxOptionSymbol;
 extern NSString* const kDangerousOmniboxSymbol;
-extern NSString* const kArrowDownSymbol;
-extern NSString* const kArrowUpSymbol;
 extern NSString* const kFamilylinkSymbol;
 extern NSString* const kMyDriveSymbol;
 extern NSString* const kSharedDrivesSymbol;
@@ -111,35 +108,30 @@
 extern NSString* const kPhoneSparkleSymbol;
 extern NSString* const kTextSearchSymbol;
 extern NSString* const kIncognitoRectangle;
-
-// Custom symbol names which can be configured with a color palette. iOS 15+
-// only.
+extern NSString* const kTextSparkSymbol;
 extern NSString* const kIncognitoCircleFillSymbol;
 extern NSString* const kPlusCircleFillSymbol;
 
-// Symbols available on iOS 18.0+.
-extern NSString* const kClockArrowTriangleheadCounterclockwiseRotate90Symbol
-    API_AVAILABLE(ios(18.0));
-
-// Custom symbols added for compatibility with iOS 15.0. These symbols are
-// available as system symbols on iOS 15.1+.
-extern NSString* const kCustomMovePlatterToBottomPhoneSymbol;
-extern NSString* const kCustomMovePlatterToTopPhoneSymbol;
-
-// Custom symbol to replace "palette" symbols on iOS 14. Cannot be used with a
-// palette.
-extern NSString* const kIncognitoCircleFilliOS14Symbol;
-
 // Use custom symbol for camera because the default video icon in iOS should
 // always represent “Apple Facetime”.
 extern NSString* const kCameraSymbol;
 extern NSString* const kCameraFillSymbol;
 
+// ****************************************************************************
 // Default symbol names.
+// ****************************************************************************
 extern NSString* const kChartBarXAxisSymbol;
 extern NSString* const kChartLineDowntrendXYAxisSymbol;
 extern NSString* const kCircleSymbol;
 extern NSString* const kCircleFillSymbol;
+extern NSString* const kPhotoSymbol;
+extern NSString* const kPhotoBadgeArrowDownSymbol;
+extern NSString* const kTabGroupsSymbol;
+extern NSString* const kCropSymbol;
+extern NSString* const kArrowDownSymbol;
+extern NSString* const kArrowUpSymbol;
+extern NSString* const kClockArrowTriangleheadCounterclockwiseRotate90Symbol
+    API_AVAILABLE(ios(18.0));
 extern NSString* const kGearshape2Symbol;
 extern NSString* const kSyncEnabledSymbol;
 extern NSString* const kDefaultBrowserSymbol;
@@ -317,7 +309,6 @@
 extern NSString* const kReaderModeSymbolPreIOS18;
 extern NSString* const kReaderModeSymbolPostIOS18;
 extern NSString* const kCircleBadgeFill;
-extern NSString* const kTextSparkSymbol;
 extern NSString* const kBookSymbol;
 extern NSString* const kKeySymbol;
 extern NSString* const kTextDocument;
diff --git a/ios/chrome/browser/shared/ui/symbols/symbol_names.mm b/ios/chrome/browser/shared/ui/symbols/symbol_names.mm
index 70998a4..c2d3520a 100644
--- a/ios/chrome/browser/shared/ui/symbols/symbol_names.mm
+++ b/ios/chrome/browser/shared/ui/symbols/symbol_names.mm
@@ -6,7 +6,6 @@
 
 // Branded symbol names.
 #if BUILDFLAG(IOS_USE_BRANDED_SYMBOLS)
-// TODO(crbug.com/1489185): Move PNG images out of this file.
 NSString* const kChromeDefaultBrowserIllustrationImage =
     @"chrome_default_browser_illustration";
 NSString* const kChromeDefaultBrowserScreenBannerImage =
@@ -63,7 +62,9 @@
 NSString* const kGeminiNonBrandedLogoImage = @"sparkle";
 #endif  // BUILDFLAG(IOS_USE_BRANDED_SYMBOLS)
 
+// ****************************************************************************
 // Custom symbol names.
+// ****************************************************************************
 NSString* const kPrivacySymbol = @"checkerboard_shield";
 NSString* const kSafetyCheckSymbol = @"checkermark_shield";
 NSString* const kArrowClockWiseSymbol = @"arrow_clockwise";
@@ -74,18 +75,15 @@
 NSString* const kEnterpriseSymbol = @"enterprise";
 NSString* const kPasswordManagerSymbol = @"password_manager";
 NSString* const kPopupBadgeMinusSymbol = @"popup_badge_minus";
-NSString* const kPhotoSymbol = @"photo";
-NSString* const kPhotoBadgeArrowDownSymbol = @"photo.badge.arrow.down";
 NSString* const kPhotoBadgePlusSymbol = @"photo_badge_plus";
 NSString* const kPhotoBadgeMagnifyingglassSymbol =
     @"photo_badge_magnifyingglass";
+NSString* const kLocationSymbol = @"location";
+NSString* const kShieldSymbol = @"shield";
 NSString* const kReadingListSymbol = @"square_bullet_square";
 NSString* const kRecentTabsSymbol = @"laptopcomputer_and_phone";
-NSString* const kTabGroupsSymbol = @"square.grid.2x2";
 NSString* const kLanguageSymbol = @"language";
-NSString* const kLocationSymbol = @"location";
 NSString* const kPasswordSymbol = @"password";
-NSString* const kCropSymbol = @"crop";
 #if !BUILDFLAG(IS_IOS_MACCATALYST)
 NSString* const kMulticolorPasswordSymbol = @"multicolor_password";
 #endif  // BUILDFLAG(IS_IOS_MACCATALYST)
@@ -93,9 +91,6 @@
 NSString* const kCameraLensSymbol = @"camera_lens";
 NSString* const kDownTrendSymbol = @"line_downtrend";
 NSString* const kUpTrendSymbol = @"line_uptrend";
-NSString* const kIncognitoCircleFilliOS14Symbol =
-    @"incognito_circle_fill_ios14";
-NSString* const kShieldSymbol = @"shield";
 NSString* const kCloudSlashSymbol = @"cloud_slash";
 NSString* const kCloudAndArrowUpSymbol = @"cloud_and_arrow_up";
 NSString* const kDinoSymbol = @"dino";
@@ -105,8 +100,6 @@
 NSString* const kTopOmniboxOptionSymbol = @"top_omnibox_option";
 NSString* const kBottomOmniboxOptionSymbol = @"bottom_omnibox_option";
 NSString* const kDangerousOmniboxSymbol = @"dangerous_omnibox";
-NSString* const kArrowDownSymbol = @"arrow.down";
-NSString* const kArrowUpSymbol = @"arrow.up";
 NSString* const kFamilylinkSymbol = @"familylink";
 NSString* const kMyDriveSymbol = @"my_drive";
 NSString* const kSharedDrivesSymbol = @"shared_drives";
@@ -119,29 +112,29 @@
 NSString* const kPhoneSparkleSymbol = @"phone_sparkle";
 NSString* const kTextSearchSymbol = @"text_search";
 NSString* const kIncognitoRectangle = @"incognito_rectangle";
-
-// Custom symbol names which can be configured with a color palette.
+NSString* const kTextSparkSymbol = @"text_spark";
 NSString* const kIncognitoCircleFillSymbol = @"incognito_circle_fill";
 NSString* const kPlusCircleFillSymbol = @"plus_circle_fill";
 
-// Custom symbols added for compatibility with iOS 15.0. These symbols are
-// available as system symbols on iOS 15.1+.
-NSString* const kCustomMovePlatterToBottomPhoneSymbol =
-    @"custom_platter_filled_bottom_and_arrow_down_iphone";
-NSString* const kCustomMovePlatterToTopPhoneSymbol =
-    @"custom_platter_filled_top_and_arrow_up_iphone";
-
 // Use custom symbol for camera because the default video icon in iOS should
 // always represent “Apple Facetime”.
 NSString* const kCameraSymbol = @"custom_camera";
 NSString* const kCameraFillSymbol = @"custom_camera_fill";
 
+// ****************************************************************************
 // Default symbol names.
+// ****************************************************************************
 NSString* const kChartBarXAxisSymbol = @"chart.bar.xaxis";
 NSString* const kChartLineDowntrendXYAxisSymbol =
     @"chart.line.downtrend.xyaxis";
 NSString* const kCircleSymbol = @"circle";
 NSString* const kCircleFillSymbol = @"circle.fill";
+NSString* const kPhotoSymbol = @"photo";
+NSString* const kPhotoBadgeArrowDownSymbol = @"photo.badge.arrow.down";
+NSString* const kTabGroupsSymbol = @"square.grid.2x2";
+NSString* const kCropSymbol = @"crop";
+NSString* const kArrowDownSymbol = @"arrow.down";
+NSString* const kArrowUpSymbol = @"arrow.up";
 NSString* const kGearshape2Symbol = @"gearshape.2";
 NSString* const kSyncEnabledSymbol = @"arrow.triangle.2.circlepath";
 NSString* const kDefaultBrowserSymbol = @"app.badge.checkmark";
@@ -328,7 +321,6 @@
 NSString* const kCircleBadgeFill = @"circlebadge.fill";
 NSString* const kCounterClockWiseSymbol =
     @"clock.arrow.trianglehead.counterclockwise.rotate.90";
-NSString* const kTextSparkSymbol = @"text_spark";
 NSString* const kBuilding2Symbol = @"building.2";
 NSString* const kBookSymbol = @"book";
 NSString* const kKeySymbol = @"key";
diff --git a/ios/chrome/browser/signin/model/ios_chrome_signin_client.mm b/ios/chrome/browser/signin/model/ios_chrome_signin_client.mm
index 921644f..001cfe29 100644
--- a/ios/chrome/browser/signin/model/ios_chrome_signin_client.mm
+++ b/ios/chrome/browser/signin/model/ios_chrome_signin_client.mm
@@ -6,6 +6,7 @@
 
 #import "base/strings/utf_string_conversions.h"
 #import "components/metrics/metrics_service.h"
+#import "components/plus_addresses/core/common/features.h"
 #import "components/signin/ios/browser/wait_for_network_callback_helper_ios.h"
 #import "components/signin/public/base/signin_metrics.h"
 #import "components/signin/public/identity_manager/primary_account_change_event.h"
@@ -23,9 +24,13 @@
 
 class IOSChromeOAuthConsumerRegistry : public signin::OAuthConsumerRegistry {
  protected:
-  signin::OAuthConsumer GetOAuthConsumerFromIdInternal(
-      signin::OAuthConsumerId oauth_consumer_id) const override {
-    NOTREACHED();
+  signin::OAuthConsumer GetOAuthConsumerForEnterprisePlusAddress()
+      const override {
+    CHECK(base::FeatureList::IsEnabled(
+        plus_addresses::features::kPlusAddressesEnabled));
+    return signin::OAuthConsumer(
+        signin::oauth_consumer_name::kEnterprisePlusAddressName,
+        {plus_addresses::features::kEnterprisePlusAddressOAuthScope.Get()});
   }
 };
 
diff --git a/ios/chrome/browser/synced_set_up/coordinator/BUILD.gn b/ios/chrome/browser/synced_set_up/coordinator/BUILD.gn
index c9c934e..cf3c95f 100644
--- a/ios/chrome/browser/synced_set_up/coordinator/BUILD.gn
+++ b/ios/chrome/browser/synced_set_up/coordinator/BUILD.gn
@@ -17,6 +17,7 @@
     "//components/signin/public/identity_manager/objc",
     "//components/sync_device_info",
     "//components/sync_preferences/cross_device_pref_tracker",
+    "//components/sync_preferences/synced_set_up:utils",
     "//ios/chrome/app",
     "//ios/chrome/app/strings",
     "//ios/chrome/browser/ntp/model:util",
@@ -38,7 +39,6 @@
     "//ios/chrome/browser/sync/model/prefs/cross_device_pref_tracker:cross_device_pref_tracker_factory",
     "//ios/chrome/browser/synced_set_up/public",
     "//ios/chrome/browser/synced_set_up/ui",
-    "//ios/chrome/browser/synced_set_up/utils",
     "//ios/web/public",
     "//ui/base",
     "//url",
diff --git a/ios/chrome/browser/synced_set_up/coordinator/synced_set_up_mediator.mm b/ios/chrome/browser/synced_set_up/coordinator/synced_set_up_mediator.mm
index af4d6e6..b3dac03 100644
--- a/ios/chrome/browser/synced_set_up/coordinator/synced_set_up_mediator.mm
+++ b/ios/chrome/browser/synced_set_up/coordinator/synced_set_up_mediator.mm
@@ -19,6 +19,7 @@
 #import "components/sync_device_info/device_info_tracker.h"
 #import "components/sync_device_info/local_device_info_provider.h"
 #import "components/sync_preferences/cross_device_pref_tracker/cross_device_pref_tracker.h"
+#import "components/sync_preferences/synced_set_up/utils.h"
 #import "ios/chrome/app/app_startup_parameters.h"
 #import "ios/chrome/browser/ntp/model/new_tab_page_util.h"
 #import "ios/chrome/browser/shared/model/application_context/application_context.h"
@@ -36,7 +37,6 @@
 #import "ios/chrome/browser/synced_set_up/coordinator/synced_set_up_mediator_delegate.h"
 #import "ios/chrome/browser/synced_set_up/public/synced_set_up_metrics.h"
 #import "ios/chrome/browser/synced_set_up/ui/synced_set_up_consumer.h"
-#import "ios/chrome/browser/synced_set_up/utils/utils.h"
 #import "ios/chrome/grit/ios_strings.h"
 #import "ui/base/l10n/l10n_util.h"
 #import "url/gurl.h"
@@ -434,7 +434,7 @@
   CHECK(localDeviceInfoProvider);
 
   std::map<std::string_view, base::Value> remoteDevicePrefs =
-      GetCrossDevicePrefsFromRemoteDevice(
+      sync_preferences::synced_set_up::GetCrossDevicePrefsFromRemoteDevice(
           _prefTracker, _deviceInfoSyncService->GetDeviceInfoTracker(),
           localDeviceInfoProvider->GetLocalDeviceInfo());
 
@@ -446,9 +446,9 @@
   }
 
   // Cache profile and local-state prefs.
-  CachePrefs(kCrossDeviceToProfilePrefMap, _profilePrefService,
-             _profilePrefsToApply, remoteDevicePrefs);
-  CachePrefs(kCrossDeviceToLocalStatePrefMap,
+  CachePrefs(sync_preferences::synced_set_up::kCrossDeviceToProfilePrefMap,
+             _profilePrefService, _profilePrefsToApply, remoteDevicePrefs);
+  CachePrefs(sync_preferences::synced_set_up::kCrossDeviceToLocalStatePrefMap,
              GetApplicationContext()->GetLocalState(), _localStatePrefsToApply,
              remoteDevicePrefs);
 
diff --git a/ios/chrome/browser/synced_set_up/utils/BUILD.gn b/ios/chrome/browser/synced_set_up/utils/BUILD.gn
index ff6486a..6524816 100644
--- a/ios/chrome/browser/synced_set_up/utils/BUILD.gn
+++ b/ios/chrome/browser/synced_set_up/utils/BUILD.gn
@@ -7,17 +7,15 @@
     "utils.h",
     "utils.mm",
   ]
-  public_deps = [
+  deps = [
+    "//base",
     "//components/commerce/core:pref_names",
     "//components/ntp_tiles:pref_names",
     "//components/omnibox/browser:pref_names",
+    "//components/prefs",
     "//components/safety_check:pref_names",
     "//components/sync_preferences/cross_device_pref_tracker/prefs",
-  ]
-  deps = [
-    "//components/prefs",
-    "//components/sync_preferences/cross_device_pref_tracker",
-    "//components/sync_preferences/cross_device_pref_tracker:timestamped_pref_value",
+    "//components/sync_preferences/synced_set_up:utils",
     "//ios/chrome/app/profile",
     "//ios/chrome/browser/shared/coordinator/scene:scene_state_header",
     "//ios/chrome/browser/shared/model/browser",
@@ -32,11 +30,6 @@
   sources = [ "utils_unittest.mm" ]
   deps = [
     ":utils",
-    "//base/test:test_support",
-    "//components/sync_device_info:test_support",
-    "//components/sync_preferences/cross_device_pref_tracker",
-    "//components/sync_preferences/cross_device_pref_tracker:timestamped_pref_value",
-    "//components/sync_preferences/cross_device_pref_tracker/prefs",
     "//ios/chrome/app/profile",
     "//ios/chrome/app/profile:test_utils",
     "//ios/chrome/browser/scoped_ui_blocker/ui_bundled",
diff --git a/ios/chrome/browser/synced_set_up/utils/utils.h b/ios/chrome/browser/synced_set_up/utils/utils.h
index 8eeed45..adacc47 100644
--- a/ios/chrome/browser/synced_set_up/utils/utils.h
+++ b/ios/chrome/browser/synced_set_up/utils/utils.h
@@ -5,70 +5,10 @@
 #ifndef IOS_CHROME_BROWSER_SYNCED_SET_UP_UTILS_UTILS_H_
 #define IOS_CHROME_BROWSER_SYNCED_SET_UP_UTILS_UTILS_H_
 
-#import <map>
-#import <string_view>
-
-#import "base/containers/fixed_flat_map.h"
-#import "components/commerce/core/pref_names.h"
-#import "components/ntp_tiles/pref_names.h"
-#import "components/omnibox/browser/omnibox_pref_names.h"
-#import "components/safety_check/safety_check_pref_names.h"
-#import "components/sync_preferences/cross_device_pref_tracker/prefs/cross_device_pref_names.h"
-
-namespace base {
-class Value;
-}  // namespace base
-
-namespace syncer {
-class DeviceInfo;
-class DeviceInfoTracker;
-}  // namespace syncer
-
-namespace sync_preferences {
-class CrossDevicePrefTracker;
-}  // namespace sync_preferences
-
 class PrefService;
 @class ProfileState;
 @class SceneState;
 
-// Map of cross-device synced prefs considered by Synced Set Up mapped to their
-// corresponding tracked local-state pref.
-inline constexpr auto kCrossDeviceToLocalStatePrefMap =
-    base::MakeFixedFlatMap<std::string_view, std::string_view>({
-        // keep-sorted start
-        {prefs::kCrossDeviceOmniboxIsInBottomPosition,
-         omnibox::kIsOmniboxInBottomPosition},
-        // keep-sorted end
-    });
-
-// Map of cross device synced prefs considered by Synced Set Up mapped to their
-// corresponding tracked profile pref.
-inline constexpr auto kCrossDeviceToProfilePrefMap =
-    base::MakeFixedFlatMap<std::string_view, std::string_view>({
-        // keep-sorted start
-        {prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-         ntp_tiles::prefs::kMagicStackHomeModuleEnabled},
-        {prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-         ntp_tiles::prefs::kMostVisitedHomeModuleEnabled},
-        {prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
-         commerce::kPriceTrackingHomeModuleEnabled},
-        {prefs::kCrossDeviceSafetyCheckHomeModuleEnabled,
-         safety_check::prefs::kSafetyCheckHomeModuleEnabled},
-        {prefs::kCrossDeviceTabResumptionHomeModuleEnabled,
-         ntp_tiles::prefs::kTabResumptionHomeModuleEnabled},
-        {prefs::kCrossDeviceTipsHomeModuleEnabled,
-         ntp_tiles::prefs::kTipsHomeModuleEnabled},
-        // keep-sorted end
-    });
-
-// Returns a map of tracked pref names and values corresponding to the "best
-// match" prefs for the Synced Set Up flow to apply.
-std::map<std::string_view, base::Value> GetCrossDevicePrefsFromRemoteDevice(
-    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
-    const syncer::DeviceInfoTracker* device_info_tracker,
-    const syncer::DeviceInfo* local_device);
-
 // Returns the active, non-incognito `SceneState` if preconditions for
 // triggering the Synced Set Up flow are met based on `profile_state`, and `nil`
 // otherwise.
diff --git a/ios/chrome/browser/synced_set_up/utils/utils.mm b/ios/chrome/browser/synced_set_up/utils/utils.mm
index 60f3ce6..91f425b4 100644
--- a/ios/chrome/browser/synced_set_up/utils/utils.mm
+++ b/ios/chrome/browser/synced_set_up/utils/utils.mm
@@ -6,15 +6,7 @@
 
 #import <Foundation/Foundation.h>
 
-#import <optional>
-#import <tuple>
-
-#import "base/notreached.h"
-#import "base/values.h"
 #import "components/prefs/pref_service.h"
-#import "components/sync_device_info/device_info_tracker.h"
-#import "components/sync_preferences/cross_device_pref_tracker/cross_device_pref_tracker.h"
-#import "components/sync_preferences/cross_device_pref_tracker/timestamped_pref_value.h"
 #import "ios/chrome/app/profile/profile_init_stage.h"
 #import "ios/chrome/app/profile/profile_state.h"
 #import "ios/chrome/browser/shared/coordinator/scene/scene_state.h"
@@ -23,174 +15,6 @@
 #import "ios/chrome/browser/shared/model/prefs/pref_names.h"
 #import "ios/chrome/browser/shared/public/features/features.h"
 
-namespace {
-
-// Struct representing a unique device, containing a map of cross device pref
-// names and values, and the total number of changes observed by the
-// `CrossDevicePrefTracker` for the device.
-struct DeviceData {
-  // Map of all cross devices prefs and their values associated with this
-  // device.
-  std::map<std::string_view, sync_preferences::TimestampedPrefValue> pref_map;
-  // Total number of observed pref changes on this device.
-  size_t observed_change_count = 0;
-};
-
-// A map of device GUID's to device data containing the devices' respective sets
-// of synced prefs and number of observed remote pref changes.
-using DeviceDataMap = std::map<std::string, DeviceData>;
-
-// Helper for adding `DeviceData` entries related to a `DeviceDataMap`, using
-// prefs contained in `pref_map`.
-template <size_t N>
-void BuildDeviceDataMapFromPrefMap(
-    DeviceDataMap& device_data_map,
-    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
-    const base::fixed_flat_map<std::string_view, std::string_view, N>&
-        pref_map) {
-  sync_preferences::CrossDevicePrefTracker::DeviceFilter filter;
-
-  // Query the tracker for tracked prefs and construct a `DeviceDataMap`
-  // associating device GUID's with sets of prefs.
-  for (const auto& tracked_pref : pref_map) {
-    std::vector<sync_preferences::TimestampedPrefValue> pref_values =
-        pref_tracker->GetValues(tracked_pref.first, filter);
-
-    // Populate the device data map with device GUID's mapped to their set of
-    // synced prefs and number of recent observed changes.
-    for (const sync_preferences::TimestampedPrefValue& pref_value :
-         pref_values) {
-      DeviceData& device_data_entry =
-          device_data_map[pref_value.device_sync_cache_guid];
-
-      // Ensure that only the most recent observed pref change is preserved in
-      // the DeviceData pref map.
-      auto it = device_data_entry.pref_map.find(tracked_pref.first);
-      if (it == device_data_entry.pref_map.end() ||
-          pref_value.last_observed_change_time >=
-              it->second.last_observed_change_time) {
-        device_data_entry.pref_map.insert_or_assign(tracked_pref.first,
-                                                    pref_value.Clone());
-      }
-
-      // Count total observed pref changes.
-      if (!pref_value.last_observed_change_time.is_null()) {
-        device_data_entry.observed_change_count++;
-      }
-    }
-  }
-}
-
-// Returns a map of synced device GUID's to the devices' associated synced pref
-// data.
-DeviceDataMap MapPrefsToDevices(
-    const sync_preferences::CrossDevicePrefTracker* pref_tracker) {
-  DeviceDataMap device_data_map;
-  BuildDeviceDataMapFromPrefMap(device_data_map, pref_tracker,
-                                kCrossDeviceToProfilePrefMap);
-  BuildDeviceDataMapFromPrefMap(device_data_map, pref_tracker,
-                                kCrossDeviceToLocalStatePrefMap);
-  return device_data_map;
-}
-
-// Returns the best fitting device in a `DeviceDataMap` of considered devices
-// and their associated prefs.
-DeviceData GetBestMatchDeviceData(
-    DeviceDataMap& synced_devices,
-    const syncer::DeviceInfoTracker* device_info_tracker,
-    const syncer::DeviceInfo* local_device) {
-  // Criteria for scoring devices against the local device as the best match for
-  // applying synced prefs.
-  using MatchesFormFactor = bool;
-  using MatchesOsType = bool;
-  using RecentPrefChangeCount = size_t;
-
-  using DeviceScore =
-      std::tuple<MatchesFormFactor, MatchesOsType, RecentPrefChangeCount>;
-
-  // Devices cannot be scored.
-  if (synced_devices.empty() || !device_info_tracker || !local_device) {
-    return {};
-  }
-
-  // Use a std::set to automatically order the scores.
-  // We store {score, guid} pairs. The set orders primarily by score.
-  using ScoredDevice = std::pair<DeviceScore, std::string_view>;
-  std::set<ScoredDevice> scored_remote_devices;
-
-  const std::string& local_device_guid = local_device->guid();
-
-  for (const auto& [guid, data] : synced_devices) {
-    // 1. Skip local device and devices with no prefs.
-    if (guid == local_device_guid || data.pref_map.empty()) {
-      continue;
-    }
-
-    // 2. Ensure the device info exists.
-    const syncer::DeviceInfo* device_info =
-        device_info_tracker->GetDeviceInfo(guid);
-    if (!device_info) {
-      continue;
-    }
-
-    // 3. Calculate and insert the score.
-    DeviceScore score = {
-        device_info->form_factor() == local_device->form_factor(),
-        device_info->os_type() == local_device->os_type(),
-        data.observed_change_count};
-    scored_remote_devices.insert({score, guid});
-  }
-
-  if (scored_remote_devices.empty()) {
-    return {};
-  }
-
-  // The best device is the last element in the ordered set.
-  const auto& best_match = *scored_remote_devices.rbegin();
-  const std::string best_guid = std::string(best_match.second);
-
-  // Final check: Compare activity level with the local device, if present.
-  auto local_it = synced_devices.find(local_device_guid);
-  if (local_it != synced_devices.end()) {
-    if (local_it->second.observed_change_count >
-        synced_devices.at(best_guid).observed_change_count) {
-      // Local device has more activity; prefer to keep local settings.
-      return {};
-    }
-  }
-  return std::move(synced_devices.at(best_guid));
-}
-
-// Returns a map of tracked pref names and their values extracted from a set of
-// `DeviceData`.
-std::map<std::string_view, base::Value> GetCrossDevicePrefValuesForDevice(
-    DeviceData& device) {
-  std::map<std::string_view, base::Value> prefs;
-  for (const auto& [cross_device_pref_name, timestamped_pref_value] :
-       device.pref_map) {
-    prefs.insert(std::make_pair(cross_device_pref_name,
-                                timestamped_pref_value.value.Clone()));
-  }
-  return prefs;
-}
-
-}  // namespace
-
-std::map<std::string_view, base::Value> GetCrossDevicePrefsFromRemoteDevice(
-    const sync_preferences::CrossDevicePrefTracker* pref_tracker,
-    const syncer::DeviceInfoTracker* device_info_tracker,
-    const syncer::DeviceInfo* local_device) {
-  if (!pref_tracker || !device_info_tracker || !local_device) {
-    return {};
-  }
-  DeviceDataMap device_data_map = MapPrefsToDevices(pref_tracker);
-  DeviceData best_match_device_data = GetBestMatchDeviceData(
-      device_data_map, device_info_tracker, local_device);
-  std::map<std::string_view, base::Value> cross_device_pref_values =
-      GetCrossDevicePrefValuesForDevice(best_match_device_data);
-  return cross_device_pref_values;
-}
-
 SceneState* GetEligibleSceneForSyncedSetUp(ProfileState* profile_state) {
   if (!profile_state) {
     return nil;
diff --git a/ios/chrome/browser/synced_set_up/utils/utils_unittest.mm b/ios/chrome/browser/synced_set_up/utils/utils_unittest.mm
index e99a2f3..5a3e069 100644
--- a/ios/chrome/browser/synced_set_up/utils/utils_unittest.mm
+++ b/ios/chrome/browser/synced_set_up/utils/utils_unittest.mm
@@ -4,19 +4,6 @@
 
 #import "ios/chrome/browser/synced_set_up/utils/utils.h"
 
-#import <optional>
-#import <string>
-
-#import "base/test/task_environment.h"
-#import "base/time/time.h"
-#import "base/values.h"
-#import "components/sync/protocol/sync_enums.pb.h"
-#import "components/sync_device_info/device_info.h"
-#import "components/sync_device_info/device_info_util.h"
-#import "components/sync_device_info/fake_device_info_tracker.h"
-#import "components/sync_preferences/cross_device_pref_tracker/cross_device_pref_tracker.h"
-#import "components/sync_preferences/cross_device_pref_tracker/prefs/cross_device_pref_names.h"
-#import "components/sync_preferences/cross_device_pref_tracker/timestamped_pref_value.h"
 #import "ios/chrome/app/profile/profile_init_stage.h"
 #import "ios/chrome/app/profile/profile_state.h"
 #import "ios/chrome/app/profile/profile_state_test_utils.h"
@@ -29,123 +16,16 @@
 #import "testing/platform_test.h"
 #import "third_party/ocmock/OCMock/OCMock.h"
 
-namespace {
-
-// Test implementation of `CrossDevicePrefTracker`.
-class TestCrossDevicePrefTracker
-    : public sync_preferences::CrossDevicePrefTracker {
- public:
-  TestCrossDevicePrefTracker() = default;
-  ~TestCrossDevicePrefTracker() override = default;
-
-  // `KeyedService` overrides.
-  void Shutdown() override {}
-
-  // `CrossDevicePrefTracker` overrides.
-  void AddObserver(Observer* observer) override {}
-  void RemoveObserver(Observer* observer) override {}
-
-  std::vector<sync_preferences::TimestampedPrefValue> GetValues(
-      std::string_view pref_name,
-      const DeviceFilter& filter) const override {
-    auto it = pref_values_.find(pref_name);
-    if (it == pref_values_.end()) {
-      return {};
-    }
-
-    std::vector<sync_preferences::TimestampedPrefValue> result;
-    for (const auto& timestamped_value : it->second) {
-      sync_preferences::TimestampedPrefValue copied_value =
-          timestamped_value.Clone();
-      result.push_back(std::move(copied_value));
-    }
-    return result;
-  }
-
-  std::optional<sync_preferences::TimestampedPrefValue> GetMostRecentValue(
-      std::string_view pref_name,
-      const DeviceFilter& filter) const override {
-    return std::nullopt;
-  }
-
-  // Testing Method for injecting pref values into the tracker.
-  void AddSyncedPrefValue(std::string_view pref_name,
-                          sync_preferences::TimestampedPrefValue& value) {
-    pref_values_[pref_name].push_back(std::move(value));
-  }
-
- private:
-  // Testing member. Map containing TimestampedPrefValues mapped to their
-  // associated pref's name.
-  std::map<std::string_view,
-           std::vector<sync_preferences::TimestampedPrefValue>>
-      pref_values_;
-};
-
-}  // namespace
-
-// Test suite for Synced Set Up utility functions.
+// Test suite for `GetEligibleSceneForSyncedSetUp()`.
 class SyncedSetUpUtilsTest : public PlatformTest {
- public:
-  void InitializeProfileState() {
+ protected:
+  void SetUp() override {
+    PlatformTest::SetUp();
+
     profile_state_ = [[ProfileState alloc] initWithAppState:nil];
     ASSERT_NSEQ(profile_state_.foregroundActiveScene, nil);
   }
 
-  // Creates a DeviceInfo object.
-  std::unique_ptr<syncer::DeviceInfo> CreateDeviceInfoForTesting(
-      std::string guid,
-      syncer::DeviceInfo::FormFactor form_factor,
-      syncer::DeviceInfo::OsType os_type,
-      base::Time last_updated_timestamp = base::Time::Now()) {
-    return CreateFakeDeviceInfo(guid, "Device Name", std::nullopt,
-                                sync_pb::SyncEnums::TYPE_UNSET, os_type,
-                                form_factor, "manufacturer", "model",
-                                std::string(), last_updated_timestamp);
-  }
-
-  // Helper for creating a DeviceInfo object.
-  std::unique_ptr<syncer::DeviceInfo> CreateFakeDeviceInfo(
-      const std::string& guid,
-      const std::string& name = "name",
-      const std::optional<syncer::DeviceInfo::SharingInfo>& sharing_info =
-          std::nullopt,
-      sync_pb::SyncEnums_DeviceType device_type =
-          sync_pb::SyncEnums_DeviceType_TYPE_UNSET,
-      syncer::DeviceInfo::OsType os_type = syncer::DeviceInfo::OsType::kUnknown,
-      syncer::DeviceInfo::FormFactor form_factor =
-          syncer::DeviceInfo::FormFactor::kUnknown,
-      const std::string& manufacturer_name = "manufacturer",
-      const std::string& model_name = "model",
-      const std::string& full_hardware_class = std::string(),
-      base::Time last_updated_timestamp = base::Time::Now()) {
-    return std::make_unique<syncer::DeviceInfo>(
-        guid, name, "chrome_version", "user_agent", device_type, os_type,
-        form_factor, "device_id", manufacturer_name, model_name,
-        full_hardware_class, last_updated_timestamp,
-        syncer::DeviceInfoUtil::GetPulseInterval(),
-        /*send_tab_to_self_receiving_enabled=*/
-        false,
-        sync_pb::
-            SyncEnums_SendTabReceivingType_SEND_TAB_RECEIVING_TYPE_CHROME_OR_UNSPECIFIED,
-        sharing_info,
-        /*paask_info=*/std::nullopt,
-        /*fcm_registration_token=*/std::string(),
-        /*interested_data_types=*/syncer::DataTypeSet(),
-        /*auto_sign_out_last_signin_timestamp=*/std::nullopt);
-  }
-
-  // Helper for configuring a TimestampedPrefValue.
-  void ConfigureTimestampedPrefValue(
-      sync_preferences::TimestampedPrefValue& timestamped_value,
-      base::Value value,
-      std::string device_sync_cache_guid,
-      base::Time last_observed_change_time = base::Time::Now()) {
-    timestamped_value.value = value.Clone();
-    timestamped_value.last_observed_change_time = last_observed_change_time;
-    timestamped_value.device_sync_cache_guid = device_sync_cache_guid;
-  }
-
   // Helper function to create and connect a scene with a specific activation
   // level.
   SceneState* ConnectSceneWithActivationLevel(SceneActivationLevel level) {
@@ -163,483 +43,12 @@
     return scene;
   }
 
- protected:
   ProfileState* profile_state_;
-  base::test::TaskEnvironment task_environment_;
-  TestCrossDevicePrefTracker pref_tracker_;
-  syncer::FakeDeviceInfoTracker device_info_tracker_;
 };
 
-// Test that a device with a matching form factor is chosen as the best fit
-// device.
-TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByFormFactor) {
-  // Local device (iOS phone).
-  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
-      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // Android tablet.
-  std::unique_ptr<syncer::DeviceInfo> android_tablet =
-      CreateDeviceInfoForTesting("android_tablet",
-                                 syncer::DeviceInfo::FormFactor::kTablet,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  // Android phone (match).
-  std::unique_ptr<syncer::DeviceInfo> android_phone =
-      CreateDeviceInfoForTesting("android_phone",
-                                 syncer::DeviceInfo::FormFactor::kPhone,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  // iOS tablet.
-  std::unique_ptr<syncer::DeviceInfo> ios_tablet = CreateDeviceInfoForTesting(
-      "ios_tablet", syncer::DeviceInfo::FormFactor::kTablet,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  device_info_tracker_.Add(local_device.get());
-  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
-  device_info_tracker_.Add(android_tablet.get());
-  device_info_tracker_.Add(android_phone.get());
-  device_info_tracker_.Add(ios_tablet.get());
-
-  // Configure some `TimestampedPrefValue` objects associated with the tracked
-  // device GUID's and add them to the pref tracker.
-  sync_preferences::TimestampedPrefValue local_device_magic_stack_enabled;
-  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
-                                base::Value(true), local_device.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      local_device_magic_stack_enabled);
-
-  sync_preferences::TimestampedPrefValue android_tablet_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue android_tablet_most_visited_enabled;
-  ConfigureTimestampedPrefValue(android_tablet_magic_stack_enabled,
-                                base::Value(true),
-                                android_tablet.get()->guid());
-  ConfigureTimestampedPrefValue(android_tablet_most_visited_enabled,
-                                base::Value(false),
-                                android_tablet.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      android_tablet_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      android_tablet_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue android_phone_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue android_phone_most_visited_enabled;
-  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
-                                base::Value(false),
-                                android_phone.get()->guid());
-  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
-                                base::Value(true), android_phone.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      android_phone_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      android_phone_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_tablet_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_tablet_most_visited_enabled;
-  ConfigureTimestampedPrefValue(ios_tablet_magic_stack_enabled,
-                                base::Value(false), ios_tablet.get()->guid());
-  ConfigureTimestampedPrefValue(ios_tablet_most_visited_enabled,
-                                base::Value(false), ios_tablet.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_tablet_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_tablet_most_visited_enabled);
-
-  // Expect that the prefs from the Android phone are returned.
-  std::map<std::string_view, base::Value> expected_result;
-  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-                          android_phone_magic_stack_enabled.value.Clone()});
-  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-                          android_phone_most_visited_enabled.value.Clone()});
-
-  std::map<std::string_view, base::Value> result =
-      GetCrossDevicePrefsFromRemoteDevice(&pref_tracker_, &device_info_tracker_,
-                                          local_device.get());
-  ASSERT_TRUE(!result.empty());
-  ASSERT_EQ(result.size(), expected_result.size());
-
-  // Compare the resultant map to the expected map.
-  for (const auto& [pref_name, pref_value] : expected_result) {
-    auto it = result.find(pref_name);
-    ASSERT_NE(it, result.end());
-    EXPECT_EQ(it->second, pref_value);
-  }
-}
-
-// Test that a device with a matching OS is chosen as the best fit device if
-// there is no device with a matching form factor.
-TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByOsType) {
-  // Local device (iOS phone).
-  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
-      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // Android tablet.
-  std::unique_ptr<syncer::DeviceInfo> android_tablet =
-      CreateDeviceInfoForTesting("android_tablet",
-                                 syncer::DeviceInfo::FormFactor::kTablet,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  // iOS tablet (match).
-  std::unique_ptr<syncer::DeviceInfo> ios_tablet = CreateDeviceInfoForTesting(
-      "ios_tablet", syncer::DeviceInfo::FormFactor::kTablet,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  device_info_tracker_.Add(local_device.get());
-  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
-  device_info_tracker_.Add(android_tablet.get());
-  device_info_tracker_.Add(ios_tablet.get());
-
-  // Configure some `TimestampedPrefValue` objects associated with the tracked
-  // device GUID's and add them to the pref tracker.
-  sync_preferences::TimestampedPrefValue local_device_magic_stack_enabled;
-  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
-                                base::Value(true), local_device.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      local_device_magic_stack_enabled);
-
-  sync_preferences::TimestampedPrefValue android_tablet_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue android_tablet_most_visited_enabled;
-  ConfigureTimestampedPrefValue(android_tablet_magic_stack_enabled,
-                                base::Value(true),
-                                android_tablet.get()->guid());
-  ConfigureTimestampedPrefValue(android_tablet_most_visited_enabled,
-                                base::Value(false),
-                                android_tablet.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      android_tablet_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      android_tablet_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_tablet_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_tablet_most_visited_enabled;
-  ConfigureTimestampedPrefValue(ios_tablet_magic_stack_enabled,
-                                base::Value(false), ios_tablet.get()->guid());
-  ConfigureTimestampedPrefValue(ios_tablet_most_visited_enabled,
-                                base::Value(false), ios_tablet.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_tablet_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_tablet_most_visited_enabled);
-
-  // Expect that the prefs from the iOS tablet are returned.
-  std::map<std::string_view, base::Value> expected_result;
-  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-                          ios_tablet_magic_stack_enabled.value.Clone()});
-  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-                          ios_tablet_most_visited_enabled.value.Clone()});
-
-  std::map<std::string_view, base::Value> result =
-      GetCrossDevicePrefsFromRemoteDevice(&pref_tracker_, &device_info_tracker_,
-                                          local_device.get());
-  ASSERT_TRUE(!result.empty());
-  ASSERT_EQ(result.size(), expected_result.size());
-
-  // compare the returned map to the expected map
-  for (const auto& [pref_name, pref_value] : expected_result) {
-    auto it = result.find(pref_name);
-    ASSERT_NE(it, result.end());
-    EXPECT_EQ(it->second, pref_value);
-  }
-}
-
-// Test that a device with the highest volume of observed pref changes is chosen
-// as the best fit device if the synced devices score the same against the
-// current device on form factor and OS.
-TEST_F(SyncedSetUpUtilsTest, TestMatchPrefsByObservedChangeCount) {
-  // Local device (iOS phone).
-  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
-      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // Android phone.
-  std::unique_ptr<syncer::DeviceInfo> android_phone =
-      CreateDeviceInfoForTesting("android_phone",
-                                 syncer::DeviceInfo::FormFactor::kPhone,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  // iOS phone.
-  std::unique_ptr<syncer::DeviceInfo> ios_phone = CreateDeviceInfoForTesting(
-      "ios_phone", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // iOS phone (match).
-  std::unique_ptr<syncer::DeviceInfo> ios_phone_2 = CreateDeviceInfoForTesting(
-      "ios_phone_2", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  device_info_tracker_.Add(local_device.get());
-  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
-  device_info_tracker_.Add(android_phone.get());
-  device_info_tracker_.Add(ios_phone.get());
-  device_info_tracker_.Add(ios_phone_2.get());
-
-  // Configure some `TimestampedPrefValue` objects associated with the tracked
-  // device GUID's and add them to the pref tracker.
-  sync_preferences::TimestampedPrefValue local_device_magic_stack_enabled;
-  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
-                                base::Value(true), local_device.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      local_device_magic_stack_enabled);
-
-  sync_preferences::TimestampedPrefValue android_phone_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue android_phone_most_visited_enabled;
-  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
-                                base::Value(true), android_phone.get()->guid());
-  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
-                                base::Value(false),
-                                android_phone.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      android_phone_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      android_phone_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_phone_1_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_1_most_visited_enabled;
-  ConfigureTimestampedPrefValue(ios_phone_1_magic_stack_enabled,
-                                base::Value(false), ios_phone.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_1_most_visited_enabled,
-                                base::Value(false), ios_phone.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_phone_1_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_phone_1_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_phone_2_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_2_most_visited_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_2_price_tracking_enabled;
-  ConfigureTimestampedPrefValue(ios_phone_2_magic_stack_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_2_most_visited_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_2_price_tracking_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_phone_2_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_phone_2_most_visited_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
-      ios_phone_2_price_tracking_enabled);
-
-  // Expect that the prefs from the second iOS phone with more changes are
-  // returned.
-  std::map<std::string_view, base::Value> expected_result;
-  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-                          ios_phone_2_magic_stack_enabled.value.Clone()});
-  expected_result.insert({prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-                          ios_phone_2_most_visited_enabled.value.Clone()});
-  expected_result.insert({prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
-                          ios_phone_2_price_tracking_enabled.value.Clone()});
-
-  std::map<std::string_view, base::Value> result =
-      GetCrossDevicePrefsFromRemoteDevice(&pref_tracker_, &device_info_tracker_,
-                                          local_device.get());
-  ASSERT_TRUE(!result.empty());
-  ASSERT_EQ(result.size(), expected_result.size());
-
-  // Compare the resultant map to the expected map.
-  for (const auto& [pref_name, pref_value] : expected_result) {
-    auto it = result.find(pref_name);
-    ASSERT_NE(it, result.end());
-    EXPECT_EQ(it->second, pref_value);
-  }
-}
-
-// Tests that no new prefs to apply are returned if the local device has a
-// higher volume of observed pref changes than the otherwise best fitting
-// device.
-TEST_F(SyncedSetUpUtilsTest, TestKeepLocalPrefsByChangeActivity) {
-  // Local device (iOS phone).
-  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
-      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // Android phone.
-  std::unique_ptr<syncer::DeviceInfo> android_phone =
-      CreateDeviceInfoForTesting("android_phone",
-                                 syncer::DeviceInfo::FormFactor::kPhone,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  // iOS phone.
-  std::unique_ptr<syncer::DeviceInfo> ios_phone = CreateDeviceInfoForTesting(
-      "ios_phone", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // iOS phone (match).
-  std::unique_ptr<syncer::DeviceInfo> ios_phone_2 = CreateDeviceInfoForTesting(
-      "ios_phone_2", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  device_info_tracker_.Add(local_device.get());
-  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
-  device_info_tracker_.Add(android_phone.get());
-  device_info_tracker_.Add(ios_phone.get());
-  device_info_tracker_.Add(ios_phone_2.get());
-
-  // Configure some `TimestampedPrefValue` objects associated with the tracked
-  // device GUID's and add them to the pref tracker.
-  sync_preferences::TimestampedPrefValue local_device_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue local_device_most_visited_enabled;
-  sync_preferences::TimestampedPrefValue local_device_price_tracking_enabled;
-  sync_preferences::TimestampedPrefValue local_device_safety_check_enabled;
-  ConfigureTimestampedPrefValue(local_device_magic_stack_enabled,
-                                base::Value(true), local_device.get()->guid());
-  ConfigureTimestampedPrefValue(local_device_most_visited_enabled,
-                                base::Value(true), local_device.get()->guid());
-  ConfigureTimestampedPrefValue(local_device_price_tracking_enabled,
-                                base::Value(true), local_device.get()->guid());
-  ConfigureTimestampedPrefValue(local_device_safety_check_enabled,
-                                base::Value(true), local_device.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      local_device_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      local_device_most_visited_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
-      local_device_price_tracking_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceSafetyCheckHomeModuleEnabled,
-      local_device_safety_check_enabled);
-
-  sync_preferences::TimestampedPrefValue android_phone_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue android_phone_most_visited_enabled;
-  ConfigureTimestampedPrefValue(android_phone_magic_stack_enabled,
-                                base::Value(true), android_phone.get()->guid());
-  ConfigureTimestampedPrefValue(android_phone_most_visited_enabled,
-                                base::Value(false),
-                                android_phone.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      android_phone_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      android_phone_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_phone_1_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_1_most_visited_enabled;
-  ConfigureTimestampedPrefValue(ios_phone_1_magic_stack_enabled,
-                                base::Value(false), ios_phone.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_1_most_visited_enabled,
-                                base::Value(false), ios_phone.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_phone_1_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_phone_1_most_visited_enabled);
-
-  sync_preferences::TimestampedPrefValue ios_phone_2_magic_stack_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_2_most_visited_enabled;
-  sync_preferences::TimestampedPrefValue ios_phone_2_price_tracking_enabled;
-  ConfigureTimestampedPrefValue(ios_phone_2_magic_stack_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_2_most_visited_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  ConfigureTimestampedPrefValue(ios_phone_2_price_tracking_enabled,
-                                base::Value(true), ios_phone_2.get()->guid());
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-      ios_phone_2_magic_stack_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMostVisitedHomeModuleEnabled,
-      ios_phone_2_most_visited_enabled);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDevicePriceTrackingHomeModuleEnabled,
-      ios_phone_2_price_tracking_enabled);
-
-  // Expect that no new prefs are returned.
-  std::map<std::string_view, base::Value> result =
-      GetCrossDevicePrefsFromRemoteDevice(&pref_tracker_, &device_info_tracker_,
-                                          local_device.get());
-  EXPECT_TRUE(result.empty());
-}
-
-// Tests that if a pref has multiple observed changes only the most recently
-// observed pref change is retrieved.
-TEST_F(SyncedSetUpUtilsTest, TestReturnsMostRecentObservedPrefChanges) {
-  const base::Time kNow = base::Time::Now();
-
-  // Local device (iOS phone).
-  std::unique_ptr<syncer::DeviceInfo> local_device = CreateDeviceInfoForTesting(
-      "local_device", syncer::DeviceInfo::FormFactor::kPhone,
-      syncer::DeviceInfo::OsType::kIOS);
-
-  // Android phone (match).
-  std::unique_ptr<syncer::DeviceInfo> android_phone =
-      CreateDeviceInfoForTesting("android_phone",
-                                 syncer::DeviceInfo::FormFactor::kPhone,
-                                 syncer::DeviceInfo::OsType::kAndroid);
-
-  device_info_tracker_.Add(local_device.get());
-  device_info_tracker_.SetLocalCacheGuid(local_device.get()->guid());
-  device_info_tracker_.Add(android_phone.get());
-
-  // Configure some `TimestampedPrefValue` objects for the same pref associated
-  // with the Android phone GUID's and add them to the pref tracker. These
-  // represent the same pref being changed several times over a period of time.
-  sync_preferences::TimestampedPrefValue magic_stack_enabled_day;
-  sync_preferences::TimestampedPrefValue magic_stack_enabled_now;
-  sync_preferences::TimestampedPrefValue magic_stack_enabled_week;
-  ConfigureTimestampedPrefValue(magic_stack_enabled_day, base::Value(true),
-                                android_phone.get()->guid(),
-                                kNow - base::Days(1));
-  ConfigureTimestampedPrefValue(magic_stack_enabled_now, base::Value(false),
-                                android_phone.get()->guid(), kNow);
-  ConfigureTimestampedPrefValue(magic_stack_enabled_week, base::Value(true),
-                                android_phone.get()->guid(),
-                                kNow - base::Days(7));
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_day);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_now);
-  pref_tracker_.AddSyncedPrefValue(
-      prefs::kCrossDeviceMagicStackHomeModuleEnabled, magic_stack_enabled_week);
-
-  // Expect that the pref is returned with its most recently set value.
-  std::map<std::string_view, base::Value> expected_result;
-  expected_result.insert({prefs::kCrossDeviceMagicStackHomeModuleEnabled,
-                          magic_stack_enabled_now.value.Clone()});
-
-  std::map<std::string_view, base::Value> result =
-      GetCrossDevicePrefsFromRemoteDevice(&pref_tracker_, &device_info_tracker_,
-                                          local_device.get());
-  ASSERT_TRUE(!result.empty());
-  ASSERT_EQ(result.size(), expected_result.size());
-
-  // Compare the resultant map to the expected map.
-  for (const auto& [pref_name, pref_value] : expected_result) {
-    auto it = result.find(pref_name);
-    ASSERT_NE(it, result.end());
-    EXPECT_EQ(it->second, pref_value);
-  }
-}
-
 // Tests that the active scene is returned when all preconditions are met (main
 // provider active, profile ready, no blockers).
 TEST_F(SyncedSetUpUtilsTest, ReturnsActiveSceneWhenAllPreconditionsMet) {
-  InitializeProfileState();
   SetProfileStateInitStage(profile_state_, ProfileInitStage::kFinal);
 
   SceneState* scene =
@@ -652,7 +61,6 @@
 
 // Tests that `nil` is returned if the input `ProfileState` is `null`.
 TEST_F(SyncedSetUpUtilsTest, ReturnsNilWhenProfileStateIsNull) {
-  InitializeProfileState();
   SceneState* result = GetEligibleSceneForSyncedSetUp(nil);
 
   EXPECT_EQ(result, nil);
@@ -660,7 +68,6 @@
 
 // Tests that `nil` is returned if the profile initialization is not complete.
 TEST_F(SyncedSetUpUtilsTest, ReturnsNilWhenProfileIsNotFinalized) {
-  InitializeProfileState();
   SetProfileStateInitStage(profile_state_, ProfileInitStage::kProfileLoaded);
 
   ConnectSceneWithActivationLevel(SceneActivationLevelForegroundActive);
@@ -672,7 +79,6 @@
 
 // Tests that `nil` is returned if a UI blocker is present.
 TEST_F(SyncedSetUpUtilsTest, ReturnsNilWhenUIBlockerIsPresent) {
-  InitializeProfileState();
   SetProfileStateInitStage(profile_state_, ProfileInitStage::kFinal);
 
   SceneState* scene =
@@ -687,7 +93,6 @@
 
 // Tests that `nil` is returned if there is no foreground active scene.
 TEST_F(SyncedSetUpUtilsTest, ReturnsNilWhenNoForegroundActiveSceneExists) {
-  InitializeProfileState();
   SetProfileStateInitStage(profile_state_, ProfileInitStage::kFinal);
 
   ConnectSceneWithActivationLevel(SceneActivationLevelForegroundInactive);
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.h b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.h
index ce4b43179..3c200f6 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.h
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.h
@@ -51,6 +51,9 @@
 // Whether the active cell is from a pinned tab.
 @property(nonatomic, assign, readonly) BOOL activeCellPinned;
 
+// Whether the top toolbar is hidden during the animation.
+@property(nonatomic, assign, readonly) BOOL topToolbarHidden;
+
 - (instancetype)initWithDestinationFrame:(CGRect)destinationFrame
                              originFrame:(CGRect)originFrame
                               activeGrid:(UIViewController*)activeGrid
@@ -64,6 +67,7 @@
                bottomToolbarSnapshotView:(UIView*)bottomToolbarSnapshotView
                    shouldScaleTopToolbar:(BOOL)shouldScaleTopToolbar
                                incognito:(BOOL)incognito
+                        topToolbarHidden:(BOOL)topToolbarHidden
     NS_DESIGNATED_INITIALIZER;
 
 - (instancetype)init NS_UNAVAILABLE;
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.mm
index 0724d194..7a1abf0 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_grid_animation_parameters.mm
@@ -18,7 +18,8 @@
                   topToolbarSnapshotView:(UIView*)topToolbarSnapshotView
                bottomToolbarSnapshotView:(UIView*)bottomToolbarSnapshotView
                    shouldScaleTopToolbar:(BOOL)shouldScaleTopToolbar
-                               incognito:(BOOL)incognito {
+                               incognito:(BOOL)incognito
+                        topToolbarHidden:(BOOL)topToolbarHidden {
   self = [super init];
   if (self) {
     _destinationFrame = destinationFrame;
@@ -34,6 +35,7 @@
     _activeCellPinned = activeCellPinned;
     _shouldScaleTopToolbar = shouldScaleTopToolbar;
     _incognito = incognito;
+    _topToolbarHidden = topToolbarHidden;
   }
   return self;
 }
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_to_grid_animation.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_to_grid_animation.mm
index 9c299a78..c5bf425 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_to_grid_animation.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/animations/tab_to_grid_animation.mm
@@ -41,6 +41,7 @@
   UIView* activeGridView = _animationParameters.activeGrid.view;
   UIView* pinnedTabsView = _animationParameters.pinnedTabs.view;
   BOOL isActiveCellPinned = _animationParameters.activeCellPinned;
+  BOOL isTopToolbarHidden = _animationParameters.topToolbarHidden;
 
   // Ratio of destination frame width over the current frame width.
   CGFloat destinationOverCurrentFrameRatio =
@@ -192,7 +193,11 @@
 
   // Toolbars animation.
   void (^toolbarsAnimation)() = ^{
-    topToolbarSnapshotView.alpha = 0;
+    if (!isTopToolbarHidden) {
+      // If the top toolbar is hidden, the snapshot should not be fade out as
+      // the toolbar background behind it should not appear.
+      topToolbarSnapshotView.alpha = 0;
+    }
     bottomToolbarSnapshotView.alpha = 0;
   };
 
diff --git a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_handler.mm b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_handler.mm
index 39ccb8b..550b4f1 100644
--- a/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_handler.mm
+++ b/ios/chrome/browser/tab_switcher/ui_bundled/tab_grid/transitions/tab_grid_transition_handler.mm
@@ -223,7 +223,11 @@
   CGRect primaryToolbarFrameInWindow =
       [primaryToolbarView.superview convertRect:primaryToolbarView.frame
                                          toView:nil];
-  CGFloat topToolbarHeight = CGRectGetMaxY(primaryToolbarFrameInWindow);
+
+  BOOL topToolbarHidden = [self shouldHideTopToolbar];
+  CGFloat topToolbarHeight =
+      topToolbarHidden ? _tabGridViewController.view.safeAreaInsets.top
+                       : CGRectGetMaxY(primaryToolbarFrameInWindow);
 
   // Get the "bottom toolbar height" (everything below the web content area).
   UIView* bottomToolbarView =
@@ -245,6 +249,17 @@
                                                  view:tabContentView]
                                 .layoutFrame;
 
+  // No top toolbar snapshot for regular browser NTPs for grid to tab
+  // animations. `topToolbarHidden` is not directly used here as the screenshot
+  // of the content below the status bar is needed when doing a Tab to Grid
+  // transition.
+  UIView* topToolbarSnapshotView =
+      topToolbarHidden &&
+              _direction == TabGridTransitionDirection::kFromTabGridToBrowser
+          ? nil
+          : [self snapshotOfViewPortionAboveRect:tabContentView
+                                      middleRect:contentAreaFrame];
+
   // Get the animation's destination and origin frames.
   CGRect destinationFrame =
       _direction == TabGridTransitionDirection::kFromBrowserToTabGrid
@@ -268,14 +283,13 @@
                 contentSnapshot:_tabGridCellItem.snapshot
                topToolbarHeight:topToolbarHeight
             bottomToolbarHeight:bottomToolbarHeight
-         topToolbarSnapshotView:
-             [self snapshotOfViewPortionAboveRect:tabContentView
-                                       middleRect:contentAreaFrame]
+         topToolbarSnapshotView:topToolbarSnapshotView
       bottomToolbarSnapshotView:
           [self snapshotOfViewPortionBelowRect:tabContentView
                                     middleRect:contentAreaFrame]
           shouldScaleTopToolbar:scaleTopToolbar
-                      incognito:_incognito];
+                      incognito:_incognito
+               topToolbarHidden:topToolbarHidden];
 }
 
 // Returns the frame for the snapshotted content of the active tab.
@@ -283,7 +297,7 @@
 // However, currently the BVC instances are themselves contained within a
 // BVCContainer view controller. This means that the
 // `viewControllerForTab.view` is not the BVC's view; rather it's the view of
-// the view controller that contains the BVC. Unfortunatley, the layout guide
+// the view controller that contains the BVC. Unfortunately, the layout guide
 // needed here is attached to the BVC's view, which is the first (and only)
 // subview of the BVCContainerViewController's view.
 // TODO(crbug.com/40583629) Clean up this arrangement.
@@ -326,4 +340,11 @@
   return nil;
 }
 
+// Returns YES if the transition should hide the top toolbar (use the safe area
+// insets instead of the top toolbar LayoutGuide).
+- (BOOL)shouldHideTopToolbar {
+  return _isRegularBrowserNTP && !CanShowTabStrip(_tabGridViewController) &&
+         IsSplitToolbarMode(_tabGridViewController);
+}
+
 @end
diff --git a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
index 7595a11..77acb4c2 100644
--- a/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
+++ b/ios/chrome/common/ui/promo_style/promo_style_view_controller.mm
@@ -85,6 +85,7 @@
 }  // namespace
 
 @interface PromoStyleViewController () <ButtonStackActionDelegate,
+                                        UITextDragDelegate,
                                         UIScrollViewDelegate>
 
 @property(nonatomic, strong) UIImageView* bannerImageView;
@@ -655,6 +656,7 @@
     _disclaimerView.editable = NO;
     _disclaimerView.adjustsFontForContentSizeCategory = YES;
     _disclaimerView.delegate = self;
+    _disclaimerView.textDragDelegate = self;
     _disclaimerView.backgroundColor = UIColor.clearColor;
     _disclaimerView.linkTextAttributes =
         @{NSForegroundColorAttributeName : [UIColor colorNamed:kBlueColor]};
@@ -1263,6 +1265,21 @@
   textView.selectedTextRange = nil;
 }
 
+- (UITextItemMenuConfiguration*)textView:(UITextView*)textView
+            menuConfigurationForTextItem:(UITextItem*)textItem
+                             defaultMenu:(UIMenu*)defaultMenu {
+  // Disable Context menu as this is an internal link.
+  return nil;
+}
+
+#pragma mark - UITextDragDelegate
+
+- (NSArray<UIDragItem*>*)textDraggableView:
+                             (UIView<UITextDraggable>*)textDraggableView
+                              itemsForDrag:(id<UITextDragRequest>)dragRequest {
+  return @[];
+}
+
 #pragma mark - UIResponder
 
 // To always be able to register key commands via -keyCommands, the VC must be
diff --git a/ios/chrome/test/earl_grey2/BUILD.gn b/ios/chrome/test/earl_grey2/BUILD.gn
index a00e63e..69e5525 100644
--- a/ios/chrome/test/earl_grey2/BUILD.gn
+++ b/ios/chrome/test/earl_grey2/BUILD.gn
@@ -194,6 +194,7 @@
     "//ios/chrome/browser/bring_android_tabs/ui_bundled:eg2_tests",
     "//ios/chrome/browser/browser_view/test:eg2_tests",
     "//ios/chrome/browser/bubble/ui_bundled:eg2_tests",
+    "//ios/chrome/browser/composebox/ui:eg2_tests",
     "//ios/chrome/browser/content_suggestions/ui_bundled/app_bundle_promo/test:eg2_tests",
     "//ios/chrome/browser/content_suggestions/ui_bundled/price_tracking_promo/test:eg2_tests",
     "//ios/chrome/browser/content_suggestions/ui_bundled/safety_check/test:eg2_tests",
diff --git a/ios/web_view/framework/sources.gni b/ios/web_view/framework/sources.gni
index a31fd2c..269408b3 100644
--- a/ios/web_view/framework/sources.gni
+++ b/ios/web_view/framework/sources.gni
@@ -340,6 +340,7 @@
   "//components/password_manager/ios",
   "//components/plus_addresses/core/browser/settings",
   "//components/plus_addresses/core/browser/webdata",
+  "//components/plus_addresses/core/common:features",
   "//components/pref_registry",
   "//components/prefs",
   "//components/profile_metrics",
diff --git a/ios/web_view/internal/signin/DEPS b/ios/web_view/internal/signin/DEPS
index 7dad1a5..c6d2175 100644
--- a/ios/web_view/internal/signin/DEPS
+++ b/ios/web_view/internal/signin/DEPS
@@ -1,3 +1,4 @@
 include_rules = [
   "+components/signin/internal/identity_manager",
+  "+components/plus_addresses/core/common/features.h"
 ]
diff --git a/ios/web_view/internal/signin/ios_web_view_signin_client.mm b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
index 9fa72d2f..5055c50 100644
--- a/ios/web_view/internal/signin/ios_web_view_signin_client.mm
+++ b/ios/web_view/internal/signin/ios_web_view_signin_client.mm
@@ -5,6 +5,7 @@
 #import "ios/web_view/internal/signin/ios_web_view_signin_client.h"
 
 #import "base/notimplemented.h"
+#import "components/plus_addresses/core/common/features.h"
 #import "components/signin/ios/browser/wait_for_network_callback_helper_ios.h"
 #import "components/signin/public/identity_manager/primary_account_change_event.h"
 #import "components/version_info/channel.h"
@@ -16,9 +17,13 @@
 
 class IOSWebViewOAuthConsumerRegistry : public signin::OAuthConsumerRegistry {
  protected:
-  signin::OAuthConsumer GetOAuthConsumerFromIdInternal(
-      signin::OAuthConsumerId oauth_consumer_id) const override {
-    NOTREACHED();
+  signin::OAuthConsumer GetOAuthConsumerForEnterprisePlusAddress()
+      const override {
+    CHECK(base::FeatureList::IsEnabled(
+        plus_addresses::features::kPlusAddressesEnabled));
+    return signin::OAuthConsumer(
+        signin::oauth_consumer_name::kEnterprisePlusAddressName,
+        {plus_addresses::features::kEnterprisePlusAddressOAuthScope.Get()});
   }
 };
 
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc
index 68273d2..cbe789e4 100644
--- a/media/renderers/paint_canvas_video_renderer.cc
+++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -666,7 +666,7 @@
 
   ~VideoImageGenerator() override = default;
 
-  sk_sp<SkData> GetEncodedData() const override { return nullptr; }
+  sk_sp<const SkData> GetEncodedData() const override { return nullptr; }
 
   bool GetPixels(SkPixmap dst_pixmap,
                  size_t frame_index,
diff --git a/net/BUILD.gn b/net/BUILD.gn
index 015f67b5..5516490 100644
--- a/net/BUILD.gn
+++ b/net/BUILD.gn
@@ -943,6 +943,7 @@
     "shared_dictionary/shared_dictionary_network_transaction.h",
     "shared_dictionary/shared_dictionary_network_transaction_factory.cc",
     "shared_dictionary/shared_dictionary_network_transaction_factory.h",
+    "shared_dictionary/shared_dictionary_transaction_outcome.h",
     "socket/client_socket_factory.cc",
     "socket/client_socket_factory.h",
     "socket/client_socket_handle.cc",
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index e93ab18..0b82ecf2 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2025-12-01 12:53 UTC
+# Last updated: 2025-12-02 12:53 UTC
 PinsListTimestamp
-1764593614
+1764680000
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json
index 4e42e0bf..1ecd2d41 100644
--- a/net/http/transport_security_state_static_pins.json
+++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@
 // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets'
 // refer to, and the timestamp at which the pins list was last updated.
 //
-// Last updated: 2025-12-01 12:53 UTC
+// Last updated: 2025-12-02 12:53 UTC
 //
 {
   "pinsets": [
diff --git a/net/shared_dictionary/shared_dictionary_network_transaction.cc b/net/shared_dictionary/shared_dictionary_network_transaction.cc
index 2b64b490..6fd9ccd 100644
--- a/net/shared_dictionary/shared_dictionary_network_transaction.cc
+++ b/net/shared_dictionary/shared_dictionary_network_transaction.cc
@@ -38,6 +38,7 @@
 #include "net/shared_dictionary/shared_dictionary_constants.h"
 #include "net/shared_dictionary/shared_dictionary_header_checker_source_stream.h"
 #include "net/shared_dictionary/shared_dictionary_isolation_key.h"
+#include "net/shared_dictionary/shared_dictionary_transaction_outcome.h"
 #include "net/ssl/ssl_private_key.h"
 
 namespace net {
@@ -167,6 +168,30 @@
 
   shared_dictionary_encoding_type_ = ParseSharedDictionaryEncodingType(
       *network_transaction_->GetResponseInfo()->headers);
+
+  if (shared_dictionary_) {
+    // Log UMA for whether the server used the dictionary if one was advertised.
+    switch (shared_dictionary_encoding_type_) {
+      case SharedDictionaryEncodingType::kSharedBrotli:
+        base::UmaHistogramEnumeration(
+            "Net.SharedDictionary.Transaction.Outcome",
+            SharedDictionaryTransactionOutcome::kDictionaryUsedBrotli);
+        break;
+
+      case SharedDictionaryEncodingType::kSharedZstd:
+        base::UmaHistogramEnumeration(
+            "Net.SharedDictionary.Transaction.Outcome",
+            SharedDictionaryTransactionOutcome::kDictionaryUsedZstandard);
+        break;
+
+      case SharedDictionaryEncodingType::kNotUsed:
+        base::UmaHistogramEnumeration(
+            "Net.SharedDictionary.Transaction.Outcome",
+            SharedDictionaryTransactionOutcome::kDictionaryNotUsed);
+        break;
+    }
+  }
+
   if (shared_dictionary_encoding_type_ ==
       SharedDictionaryEncodingType::kNotUsed) {
     std::move(callback).Run(result);
diff --git a/net/shared_dictionary/shared_dictionary_network_transaction_unittest.cc b/net/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
index 01e50626..8b2413a 100644
--- a/net/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
+++ b/net/shared_dictionary/shared_dictionary_network_transaction_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/functional/callback_helpers.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/notreached.h"
+#include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "crypto/hash.h"
 #include "net/base/features.h"
@@ -23,6 +24,7 @@
 #include "net/log/net_log_with_source.h"
 #include "net/shared_dictionary/shared_dictionary.h"
 #include "net/shared_dictionary/shared_dictionary_constants.h"
+#include "net/shared_dictionary/shared_dictionary_transaction_outcome.h"
 #include "net/ssl/ssl_private_key.h"
 #include "net/test/gtest_util.h"
 #include "net/test/test_with_task_environment.h"
@@ -252,6 +254,7 @@
 };
 
 TEST_F(SharedDictionaryNetworkTransactionTest, SyncDictionary) {
+  base::HistogramTester histogram_tester;
   MockHttpRequest request(*scoped_mock_transaction_);
   request.dictionary_getter = base::BindRepeating(
       [](const std::optional<SharedDictionaryIsolationKey>& isolation_key,
@@ -268,6 +271,9 @@
                                 NetLogWithSource()),
               test::IsError(ERR_IO_PENDING));
   EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
+  histogram_tester.ExpectUniqueSample(
+      "Net.SharedDictionary.Transaction.Outcome",
+      SharedDictionaryTransactionOutcome::kDictionaryUsedBrotli, 1);
 
   scoped_refptr<IOBufferWithSize> buf =
       base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
@@ -281,6 +287,7 @@
 }
 
 TEST_F(SharedDictionaryNetworkTransactionTest, NotAllowedToUseDictionary) {
+  base::HistogramTester histogram_tester;
   // Change MockTransaction to check that there is no available-dictionary
   // header.
   scoped_mock_transaction_->handler =
@@ -303,6 +310,8 @@
                                 NetLogWithSource()),
               test::IsError(ERR_IO_PENDING));
   EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
+  histogram_tester.ExpectTotalCount("Net.SharedDictionary.Transaction.Outcome",
+                                    0);
 
   scoped_refptr<IOBufferWithSize> buf =
       base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
@@ -664,6 +673,7 @@
 }
 
 TEST_F(SharedDictionaryNetworkTransactionTest, NoSbrContentEncoding) {
+  base::HistogramTester histogram_tester;
   // Change MockTransaction to remove `content-encoding: dcb`.
   scoped_mock_transaction_->response_headers = "";
 
@@ -683,6 +693,9 @@
                                 NetLogWithSource()),
               test::IsError(ERR_IO_PENDING));
   EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
+  histogram_tester.ExpectUniqueSample(
+      "Net.SharedDictionary.Transaction.Outcome",
+      SharedDictionaryTransactionOutcome::kDictionaryNotUsed, 1);
 
   scoped_refptr<IOBufferWithSize> buf =
       base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
@@ -1074,6 +1087,7 @@
 }
 
 TEST_F(SharedDictionaryNetworkTransactionTest, SharedZstd) {
+  base::HistogramTester histogram_tester;
   // Override MockTransaction to use `content-encoding: dcz`.
   scoped_mock_transaction_.reset();
   ScopedMockTransaction new_mock_transaction(kZstdDictionaryTestTransaction);
@@ -1094,6 +1108,9 @@
                                 NetLogWithSource()),
               test::IsError(ERR_IO_PENDING));
   EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
+  histogram_tester.ExpectUniqueSample(
+      "Net.SharedDictionary.Transaction.Outcome",
+      SharedDictionaryTransactionOutcome::kDictionaryUsedZstandard, 1);
 
   scoped_refptr<IOBufferWithSize> buf =
       base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
diff --git a/net/shared_dictionary/shared_dictionary_transaction_outcome.h b/net/shared_dictionary/shared_dictionary_transaction_outcome.h
new file mode 100644
index 0000000..1e0153d
--- /dev/null
+++ b/net/shared_dictionary/shared_dictionary_transaction_outcome.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 NET_SHARED_DICTIONARY_SHARED_DICTIONARY_TRANSACTION_OUTCOME_H_
+#define NET_SHARED_DICTIONARY_SHARED_DICTIONARY_TRANSACTION_OUTCOME_H_
+
+namespace net {
+
+// Used for UMA. Logged to "Net.SharedDictionary.Transaction.Outcome".
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+//
+// LINT.IfChange(SharedDictionaryTransactionOutcome)
+enum class SharedDictionaryTransactionOutcome {
+  kDictionaryUsedBrotli = 0,
+  kDictionaryUsedZstandard = 1,
+  kDictionaryNotUsed = 2,
+  kMaxValue = kDictionaryNotUsed,
+};
+// LINT.ThenChange(//tools/metrics/histograms/metadata/net/enums.xml:SharedDictionaryTransactionOutcome)
+
+}  // namespace net
+
+#endif  // NET_SHARED_DICTIONARY_SHARED_DICTIONARY_TRANSACTION_OUTCOME_H_
diff --git a/net/socket/client_socket_pool.h b/net/socket/client_socket_pool.h
index 45aa8275..87150ef6 100644
--- a/net/socket/client_socket_pool.h
+++ b/net/socket/client_socket_pool.h
@@ -373,6 +373,8 @@
     return AdditionalCapacity();
   }
 
+  SocketPoolState StateForTest() const { return State(); }
+
  protected:
   ClientSocketPool(size_t socket_soft_cap,
                    SocketPoolAdditionalCapacity additional_capacity,
@@ -413,6 +415,10 @@
 
   void UpdateStateAfterRelease();
 
+  // This is used to reset the pool to the initial uncapped state when the
+  // socket pool is fully flushed out before later reuse.
+  void ResetState() { state_ = SocketPoolState::kUncapped; }
+
   const ProxyChain& GetProxyChain() const { return proxy_chain_; }
 
  private:
diff --git a/net/socket/socket_pool_additional_capacity_unittest.cc b/net/socket/socket_pool_additional_capacity_unittest.cc
index 72a4f05..ed830038 100644
--- a/net/socket/socket_pool_additional_capacity_unittest.cc
+++ b/net/socket/socket_pool_additional_capacity_unittest.cc
@@ -5,10 +5,12 @@
 #include "net/socket/socket_pool_additional_capacity.h"
 
 #include "base/notimplemented.h"
+#include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "net/base/features.h"
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/connect_job_factory.h"
+#include "net/socket/socket_test_util.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "third_party/fuzztest/src/fuzztest/fuzztest.h"
 
@@ -16,10 +18,6 @@
 
 namespace {
 
-// This should be kept in sync with the field trial config's default pool.
-const SocketPoolAdditionalCapacity kFieldTrialPool =
-    SocketPoolAdditionalCapacity::CreateForTest(0.000001, 256, 0.01, 0.2);
-
 TEST(SocketPoolAdditionalCapacityTest, CreateWithDisabledFeature) {
   base::test::ScopedFeatureList scoped_feature_list;
   scoped_feature_list.InitAndDisableFeature(
@@ -457,80 +455,14 @@
   size_t sockets_in_use_{0};
 };
 
-// The goal of this test is to walk a pool back and forth between being
-// capped and uncapped, tracking at what point the transition occurs
-// and using that data to validate expected behavior. We take this walk
-// about 1000 times as there is randomization in the transition points.
-TEST(SocketPoolAdditionalCapacityTest, ValidateMockClientSocketPool) {
+TEST(SocketPoolAdditionalCapacityTest,
+     ValidateAdditionalCapacityForMockClientSocketPool) {
   MockClientSocketPool pool;
-  size_t total_sockets_seen_at_capping_point = 0;
-  size_t capping_points_seen = 0;
-  size_t minimum_sockets_seen_at_capping_point = 512;
-  size_t maximum_sockets_seen_at_capping_point = 0;
-  size_t total_sockets_seen_at_uncapping_point = 0;
-  size_t uncapping_points_seen = 0;
-  size_t minimum_sockets_seen_at_uncapping_point = 512;
-  size_t maximum_sockets_seen_at_uncapping_point = 0;
-  for (size_t i = 0; i < 1000; ++i) {
-    while (pool.RequestSocket() == SocketPoolState::kUncapped) {
-      continue;
-    }
-    total_sockets_seen_at_capping_point += pool.SocketsInUse();
-    ++capping_points_seen;
-    if (minimum_sockets_seen_at_capping_point > pool.SocketsInUse()) {
-      minimum_sockets_seen_at_capping_point = pool.SocketsInUse();
-    }
-    if (maximum_sockets_seen_at_capping_point < pool.SocketsInUse()) {
-      maximum_sockets_seen_at_capping_point = pool.SocketsInUse();
-    }
-    while (pool.ReleaseSocket() == SocketPoolState::kCapped) {
-      continue;
-    }
-    total_sockets_seen_at_uncapping_point += pool.SocketsInUse();
-    ++uncapping_points_seen;
-    if (minimum_sockets_seen_at_uncapping_point > pool.SocketsInUse()) {
-      minimum_sockets_seen_at_uncapping_point = pool.SocketsInUse();
-    }
-    if (maximum_sockets_seen_at_uncapping_point < pool.SocketsInUse()) {
-      maximum_sockets_seen_at_uncapping_point = pool.SocketsInUse();
-    }
-  }
-  int average_sockets_seen_at_capping_point =
-      total_sockets_seen_at_capping_point / capping_points_seen;
-  int average_sockets_seen_at_uncapping_point =
-      total_sockets_seen_at_uncapping_point / uncapping_points_seen;
-  int capping_range = maximum_sockets_seen_at_capping_point -
-                      minimum_sockets_seen_at_capping_point;
-  int uncapping_range = maximum_sockets_seen_at_uncapping_point -
-                        minimum_sockets_seen_at_uncapping_point;
-  int average_difference = average_sockets_seen_at_capping_point -
-                           average_sockets_seen_at_uncapping_point;
-
-  // The pool should always uncap between 256 and 512.
-  EXPECT_GE(minimum_sockets_seen_at_capping_point, 256);
-  EXPECT_LE(maximum_sockets_seen_at_capping_point, 512);
-
-  // The pool should always uncap between 255 and 511.
-  EXPECT_GE(minimum_sockets_seen_at_uncapping_point, 255);
-  EXPECT_LE(maximum_sockets_seen_at_uncapping_point, 511);
-
-  // We expect the capping range to start, average, and end after the uncapping.
-  EXPECT_GT(minimum_sockets_seen_at_capping_point,
-            minimum_sockets_seen_at_uncapping_point);
-  EXPECT_GT(average_sockets_seen_at_capping_point,
-            average_sockets_seen_at_uncapping_point);
-  EXPECT_GT(maximum_sockets_seen_at_capping_point,
-            maximum_sockets_seen_at_uncapping_point);
-
-  // We expect a range of 150 to 250 for both capping and uncapping ranges.
-  EXPECT_GT(capping_range, 150);
-  EXPECT_LT(capping_range, 250);
-  EXPECT_GT(uncapping_range, 150);
-  EXPECT_LT(uncapping_range, 250);
-
-  // We expect a range 20 to 80 between the average capping and uncapping.
-  EXPECT_GT(average_difference, 20);
-  EXPECT_LT(average_difference, 80);
+  ValidateAdditionalCapacityForSocketPool(
+      base::BindLambdaForTesting([&]() { return pool.RequestSocket(); }),
+      base::DoNothing(),
+      base::BindLambdaForTesting([&]() { return pool.ReleaseSocket(); }),
+      base::BindLambdaForTesting([&]() { return pool.SocketsInUse(); }));
 }
 
 }  // namespace
diff --git a/net/socket/socket_test_util.cc b/net/socket/socket_test_util.cc
index 79772bd9..90db6de 100644
--- a/net/socket/socket_test_util.cc
+++ b/net/socket/socket_test_util.cc
@@ -2398,4 +2398,80 @@
 }
 #endif
 
+void ValidateAdditionalCapacityForSocketPool(
+    base::RepeatingCallback<SocketPoolState()> request_socket,
+    base::RepeatingCallback<void()> wait_for_socket_initialization,
+    base::RepeatingCallback<SocketPoolState()> release_socket,
+    base::RepeatingCallback<size_t()> sockets_in_use) {
+  size_t total_sockets_seen_at_capping_point = 0;
+  size_t capping_points_seen = 0;
+  size_t minimum_sockets_seen_at_capping_point = 512;
+  size_t maximum_sockets_seen_at_capping_point = 0;
+  size_t total_sockets_seen_at_uncapping_point = 0;
+  size_t uncapping_points_seen = 0;
+  size_t minimum_sockets_seen_at_uncapping_point = 512;
+  size_t maximum_sockets_seen_at_uncapping_point = 0;
+  for (size_t i = 0; i < 100; ++i) {
+    while (request_socket.Run() == SocketPoolState::kUncapped) {
+      continue;
+    }
+    wait_for_socket_initialization.Run();
+    total_sockets_seen_at_capping_point += sockets_in_use.Run();
+    ++capping_points_seen;
+    if (minimum_sockets_seen_at_capping_point > sockets_in_use.Run()) {
+      minimum_sockets_seen_at_capping_point = sockets_in_use.Run();
+    }
+    if (maximum_sockets_seen_at_capping_point < sockets_in_use.Run()) {
+      maximum_sockets_seen_at_capping_point = sockets_in_use.Run();
+    }
+    while (release_socket.Run() == SocketPoolState::kCapped) {
+      continue;
+    }
+    total_sockets_seen_at_uncapping_point += sockets_in_use.Run();
+    ++uncapping_points_seen;
+    if (minimum_sockets_seen_at_uncapping_point > sockets_in_use.Run()) {
+      minimum_sockets_seen_at_uncapping_point = sockets_in_use.Run();
+    }
+    if (maximum_sockets_seen_at_uncapping_point < sockets_in_use.Run()) {
+      maximum_sockets_seen_at_uncapping_point = sockets_in_use.Run();
+    }
+  }
+  int average_sockets_seen_at_capping_point =
+      total_sockets_seen_at_capping_point / capping_points_seen;
+  int average_sockets_seen_at_uncapping_point =
+      total_sockets_seen_at_uncapping_point / uncapping_points_seen;
+  int capping_range = maximum_sockets_seen_at_capping_point -
+                      minimum_sockets_seen_at_capping_point;
+  int uncapping_range = maximum_sockets_seen_at_uncapping_point -
+                        minimum_sockets_seen_at_uncapping_point;
+  int average_difference = average_sockets_seen_at_capping_point -
+                           average_sockets_seen_at_uncapping_point;
+
+  // The pool should always uncap between 256 and 512.
+  EXPECT_GE(minimum_sockets_seen_at_capping_point, 256u);
+  EXPECT_LE(maximum_sockets_seen_at_capping_point, 512u);
+
+  // The pool should always uncap between 255 and 511.
+  EXPECT_GE(minimum_sockets_seen_at_uncapping_point, 255u);
+  EXPECT_LE(maximum_sockets_seen_at_uncapping_point, 511u);
+
+  // We expect the capping range to start, average, and end after the uncapping.
+  EXPECT_GE(minimum_sockets_seen_at_capping_point,
+            minimum_sockets_seen_at_uncapping_point);
+  EXPECT_GE(average_sockets_seen_at_capping_point,
+            average_sockets_seen_at_uncapping_point);
+  EXPECT_GE(maximum_sockets_seen_at_capping_point,
+            maximum_sockets_seen_at_uncapping_point);
+
+  // We expect a range of 140 to 260 for both capping and uncapping ranges.
+  EXPECT_GE(capping_range, 140);
+  EXPECT_LE(capping_range, 260);
+  EXPECT_GE(uncapping_range, 140);
+  EXPECT_LE(uncapping_range, 260);
+
+  // We expect a range 20 to 80 between the average capping and uncapping.
+  EXPECT_GE(average_difference, 20);
+  EXPECT_LE(average_difference, 80);
+}
+
 }  // namespace net
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h
index a1488b5..b261106 100644
--- a/net/socket/socket_test_util.h
+++ b/net/socket/socket_test_util.h
@@ -41,6 +41,7 @@
 #include "net/socket/client_socket_pool.h"
 #include "net/socket/datagram_client_socket.h"
 #include "net/socket/socket_performance_watcher.h"
+#include "net/socket/socket_pool_additional_capacity.h"
 #include "net/socket/socket_tag.h"
 #include "net/socket/ssl_client_socket.h"
 #include "net/socket/transport_client_socket.h"
@@ -1550,6 +1551,20 @@
 uint64_t GetTaggedBytes(int32_t expected_tag);
 #endif
 
+// This should be kept in sync with the field trial config's default pool.
+const SocketPoolAdditionalCapacity kFieldTrialPool =
+    SocketPoolAdditionalCapacity::CreateForTest(0.000001, 256, 0.01, 0.2);
+
+// The goal of this test is to walk a pool back and forth between being
+// capped and uncapped, tracking at what point the transition occurs
+// and using that data to validate expected behavior. We take this walk
+// about 100 times as there is randomization in the transition points.
+void ValidateAdditionalCapacityForSocketPool(
+    base::RepeatingCallback<SocketPoolState()> request_socket,
+    base::RepeatingCallback<void()> wait_for_socket_initialization,
+    base::RepeatingCallback<SocketPoolState()> release_socket,
+    base::RepeatingCallback<size_t()> sockets_in_use);
+
 }  // namespace net
 
 #endif  // NET_SOCKET_SOCKET_TEST_UTIL_H_
diff --git a/net/socket/websocket_transport_client_socket_pool.cc b/net/socket/websocket_transport_client_socket_pool.cc
index 7c3710eb..24f75db6 100644
--- a/net/socket/websocket_transport_client_socket_pool.cc
+++ b/net/socket/websocket_transport_client_socket_pool.cc
@@ -84,8 +84,9 @@
 
   NetLogTcpClientSocketPoolRequestedSocket(request_net_log, group_id);
   request_net_log.BeginEvent(NetLogEventType::SOCKET_POOL);
+  UpdateStateBeforeAllocation();
 
-  if (ReachedMaxSocketsLimit() &&
+  if (State() == SocketPoolState::kCapped &&
       respect_limits == ClientSocketPool::RespectLimits::ENABLED) {
     request_net_log.AddEvent(NetLogEventType::SOCKET_POOL_STALLED_MAX_SOCKETS);
     stalled_request_queue_.emplace_back(
@@ -173,6 +174,7 @@
   } else {
     pending_callbacks_.erase(reinterpret_cast<ClientSocketHandleID>(handle));
   }
+  UpdateStateAfterRelease();
 
   ActivateStalledRequest();
 }
@@ -183,6 +185,7 @@
     int64_t generation) {
   CHECK_GT(handed_out_socket_count_, 0u);
   --handed_out_socket_count_;
+  UpdateStateAfterRelease();
 
   ActivateStalledRequest();
 }
@@ -214,6 +217,7 @@
   stalled_request_map_.clear();
   stalled_request_queue_.clear();
   flushing_ = false;
+  ResetState();
 }
 
 void WebSocketTransportClientSocketPool::CloseIdleSockets(
@@ -382,10 +386,6 @@
   }
 }
 
-bool WebSocketTransportClientSocketPool::ReachedMaxSocketsLimit() const {
-  return SocketsInUse() >= SocketSoftCap();
-}
-
 void WebSocketTransportClientSocketPool::HandOutSocket(
     std::unique_ptr<StreamSocket> socket,
     const LoadTimingInfo::ConnectTiming& connect_timing,
@@ -439,7 +439,8 @@
   // Usually we will only be able to activate one stalled request at a time,
   // however if all the connects fail synchronously for some reason, we may be
   // able to clear the whole queue at once.
-  while (!stalled_request_queue_.empty() && !ReachedMaxSocketsLimit()) {
+  while (!stalled_request_queue_.empty() &&
+         State() == SocketPoolState::kUncapped) {
     StalledRequest request = std::move(stalled_request_queue_.front());
     stalled_request_queue_.pop_front();
     stalled_request_map_.erase(request.handle);
diff --git a/net/socket/websocket_transport_client_socket_pool.h b/net/socket/websocket_transport_client_socket_pool.h
index 45f92ac..71fde93 100644
--- a/net/socket/websocket_transport_client_socket_pool.h
+++ b/net/socket/websocket_transport_client_socket_pool.h
@@ -203,7 +203,6 @@
                           base::WeakPtr<ClientSocketHandle> weak_handle,
                           CompletionOnceCallback callback,
                           int rv);
-  bool ReachedMaxSocketsLimit() const;
   void HandOutSocket(std::unique_ptr<StreamSocket> socket,
                      const LoadTimingInfo::ConnectTiming& connect_timing,
                      ClientSocketHandle* handle,
diff --git a/net/socket/websocket_transport_client_socket_pool_unittest.cc b/net/socket/websocket_transport_client_socket_pool_unittest.cc
index 6af66532..98d8eda 100644
--- a/net/socket/websocket_transport_client_socket_pool_unittest.cc
+++ b/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -17,6 +17,7 @@
 #include "base/run_loop.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/single_thread_task_runner.h"
+#include "base/test/bind.h"
 #include "base/test/scoped_feature_list.h"
 #include "base/test/task_environment.h"
 #include "base/time/time.h"
@@ -138,10 +139,12 @@
 
   static void RunUntilIdle() { base::RunLoop().RunUntilIdle(); }
 
-  int StartRequest(RequestPriority priority) {
+  int StartRequest(
+      RequestPriority priority,
+      WebSocketTransportClientSocketPool* non_default_pool = nullptr) {
     return test_base_.StartRequestUsingPool(
-        &pool_, group_id_, priority, ClientSocketPool::RespectLimits::ENABLED,
-        params_);
+        non_default_pool ?: &pool_, group_id_, priority,
+        ClientSocketPool::RespectLimits::ENABLED, params_);
   }
 
   int GetOrderOfRequest(size_t index) {
@@ -1440,6 +1443,25 @@
   EXPECT_THAT(connect_job_v6_and_v4.GetLoadState(), LOAD_STATE_CONNECTING);
 }
 
+TEST_F(WebSocketTransportClientSocketPoolTest,
+       ValidateAdditionalCapacityForWebSocketTransportClientSocketPool) {
+  WebSocketTransportClientSocketPool pool(
+      /*socket_soft_cap=*/256, kFieldTrialPool, ProxyChain::Direct(),
+      &common_connect_job_params_);
+  ValidateAdditionalCapacityForSocketPool(
+      base::BindLambdaForTesting([&]() {
+        StartRequest(kDefaultPriority, &pool);
+        return pool.StateForTest();
+      }),
+      base::BindLambdaForTesting([&]() { RunUntilIdle(); }),
+      base::BindLambdaForTesting([&]() {
+        EXPECT_TRUE(ReleaseOneConnection(ClientSocketPoolTest::NO_KEEP_ALIVE));
+        return pool.StateForTest();
+      }),
+      base::BindLambdaForTesting([&]() { return pool.SocketsInUse(); }));
+  ReleaseAllConnections(ClientSocketPoolTest::NO_KEEP_ALIVE);
+}
+
 }  // namespace
 
 }  // namespace net
diff --git a/printing/common/metafile_utils.cc b/printing/common/metafile_utils.cc
index 77d8a6b..172a49dc 100644
--- a/printing/common/metafile_utils.cc
+++ b/printing/common/metafile_utils.cc
@@ -319,7 +319,7 @@
 }
 #endif
 
-sk_sp<SkData> SerializeOopPicture(SkPicture* pic, void* ctx) {
+SkSerialReturnType SerializeOopPicture(SkPicture* pic, void* ctx) {
   const auto* context = reinterpret_cast<const ContentToProxyTokenMap*>(ctx);
   uint32_t pic_id = pic->uniqueID();
   auto iter = context->find(pic_id);
@@ -350,7 +350,7 @@
   return iter->second;
 }
 
-sk_sp<SkData> SerializeOopTypeface(SkTypeface* typeface, void* ctx) {
+SkSerialReturnType SerializeOopTypeface(SkTypeface* typeface, void* ctx) {
   auto* context = reinterpret_cast<TypefaceSerializationContext*>(ctx);
   SkTypefaceID typeface_id = typeface->uniqueID();
   bool data_included = context->insert(typeface_id).second;
@@ -399,7 +399,7 @@
   return typeface;
 }
 
-sk_sp<SkData> SerializeRasterImage(SkImage* img, void* ctx) {
+SkSerialReturnType SerializeRasterImage(SkImage* img, void* ctx) {
   if (!img) {
     return nullptr;
   }
diff --git a/printing/metafile_skia_unittest.cc b/printing/metafile_skia_unittest.cc
index df763ad..8a2cebd 100644
--- a/printing/metafile_skia_unittest.cc
+++ b/printing/metafile_skia_unittest.cc
@@ -259,8 +259,7 @@
     ImageSerializationContext images;
     SkSerialProcs procs = SerializationProcs(&subframes, nullptr, &images);
 
-    sk_sp<SkData> encoded_data =
-        (*procs.fImageProc)(image.get(), procs.fImageCtx);
+    auto encoded_data = procs.fImageProc(image.get(), procs.fImageCtx);
     ASSERT_TRUE(encoded_data);
     EXPECT_GT(encoded_data->size(), sizeof(uint32_t));
 
@@ -304,8 +303,7 @@
     PictureSerializationContext subframes;
     ImageSerializationContext images;
     SkSerialProcs procs = SerializationProcs(&subframes, nullptr, &images);
-    sk_sp<SkData> encoded_data =
-        (*procs.fImageProc)(jpeg_img.get(), procs.fImageCtx);
+    auto encoded_data = procs.fImageProc(jpeg_img.get(), procs.fImageCtx);
     ASSERT_TRUE(encoded_data);
     EXPECT_GT(encoded_data->size(), sizeof(uint32_t));
 
@@ -343,8 +341,7 @@
   ImageSerializationContext images;
   SkSerialProcs procs = SerializationProcs(&subframes, nullptr, &images);
 
-  sk_sp<SkData> encoded_data1 =
-      (*procs.fImageProc)(unencoded_img.get(), procs.fImageCtx);
+  auto encoded_data1 = procs.fImageProc(unencoded_img.get(), procs.fImageCtx);
   ASSERT_TRUE(encoded_data1);
   EXPECT_GT(encoded_data1->size(), sizeof(uint32_t));
 
@@ -363,8 +360,7 @@
   }
 
   // Call the serialization proc on the image for the second time.
-  sk_sp<SkData> encoded_data2 =
-      (*procs.fImageProc)(unencoded_img.get(), procs.fImageCtx);
+  auto encoded_data2 = procs.fImageProc(unencoded_img.get(), procs.fImageCtx);
   ASSERT_TRUE(encoded_data2);
   EXPECT_EQ(encoded_data2->size(), sizeof(uint32_t));
 
diff --git a/services/viz/public/cpp/compositing/quads_mojom_traits.cc b/services/viz/public/cpp/compositing/quads_mojom_traits.cc
index 13bfa36..3751578 100644
--- a/services/viz/public/cpp/compositing/quads_mojom_traits.cc
+++ b/services/viz/public/cpp/compositing/quads_mojom_traits.cc
@@ -178,6 +178,7 @@
   quad->secure_output_only = data.secure_output_only();
   quad->is_video_frame = data.is_video_frame();
   quad->force_rgbx = data.force_rgbx();
+  quad->is_normalized_coords = data.is_normalized_coords();
 
   if (!data.ReadDamageRect(&quad->damage_rect))
     return false;
diff --git a/services/viz/public/cpp/compositing/quads_mojom_traits.h b/services/viz/public/cpp/compositing/quads_mojom_traits.h
index 19c7725..fb9e443 100644
--- a/services/viz/public/cpp/compositing/quads_mojom_traits.h
+++ b/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -422,6 +422,12 @@
     return quad->tex_coord_rect_;
   }
 
+  static bool is_normalized_coords(const viz::DrawQuad& input) {
+    const viz::TextureDrawQuad* quad =
+        viz::TextureDrawQuad::MaterialCast(&input);
+    return quad->is_normalized_coords;
+  }
+
   static SkColor4f background_color(const viz::DrawQuad& input) {
     const viz::TextureDrawQuad* quad =
         viz::TextureDrawQuad::MaterialCast(&input);
diff --git a/services/viz/public/mojom/compositing/quads.mojom b/services/viz/public/mojom/compositing/quads.mojom
index e97e25a..d3380ae 100644
--- a/services/viz/public/mojom/compositing/quads.mojom
+++ b/services/viz/public/mojom/compositing/quads.mojom
@@ -95,6 +95,7 @@
   bool secure_output_only;
   bool is_video_frame;
   bool force_rgbx;
+  bool is_normalized_coords;
   ProtectedVideoState protected_video_type;
   gfx.mojom.Rect? damage_rect;
   OverlayPriority overlay_priority_hint;
diff --git a/skia/config/SkUserConfig.h b/skia/config/SkUserConfig.h
index 4e83b83..842e4d7 100644
--- a/skia/config/SkUserConfig.h
+++ b/skia/config/SkUserConfig.h
@@ -135,16 +135,15 @@
 
 #define SK_AVOID_SLOW_RASTER_PIPELINE_BLURS
 
-#define SK_DISABLE_LEGACY_NONRECORDER_IMAGE_APIS
-
 #define SK_SUPPORT_LEGACY_RRECT_TRANSFORM
 
-#define SK_ENABLE_SKOTTIE_FILLRULE
-
 // Ensures Chromium is not using any mutable path APIs.  Only remove after the
 // editing methods on SkPath are truly gone.
 #define SK_HIDE_PATH_EDIT_METHODS
 
+#define SK_DISABLE_LEGACY_NONCONST_ENCODED_IMAGE_DATA
+#define SK_DISABLE_LEGACY_NONCONST_SERIAL_PROCS
+
 ///////////////////////// Imported from BUILD.gn and skia_common.gypi
 
 /* In some places Skia can use static initializers for global initialization,
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index fe97ff63..918dd7d 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -6553,6 +6553,21 @@
             ]
         }
     ],
+    "CloudProfileReporting": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "CloudProfileReporting"
+                    ]
+                }
+            ]
+        }
+    ],
     "CoalesceSelectionchangeEvent": [
         {
             "platforms": [
@@ -20417,26 +20432,6 @@
             ]
         }
     ],
-    "PurgeVariationsSeedFromMemory": [
-        {
-            "platforms": [
-                "android",
-                "ios",
-                "chromeos",
-                "linux",
-                "mac",
-                "windows"
-            ],
-            "experiments": [
-                {
-                    "name": "Enabled",
-                    "enable_features": [
-                        "PurgeVariationsSeedFromMemory"
-                    ]
-                }
-            ]
-        }
-    ],
     "PushMessagingDisallowSenderIDs": [
         {
             "platforms": [
diff --git a/third_party/angle b/third_party/angle
index c4fe7ab..1e01eea 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit c4fe7abe14469bafce44bc4e9502e84c458d4801
+Subproject commit 1e01eea083a0e03e1a3b7581d2a600e608d46430
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 8990b735..bb178b84 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -296,7 +296,6 @@
     ":make_generated_origin_trials",
     ":make_runtime_feature_state_contexts_impl",
     "//components/viz/common",
-    "//third_party/blink/common/privacy_budget",
     "//third_party/blink/public/common:common_export",
     "//third_party/blink/public/common:headers",
     "//ui/base/mojom:ui_base_types",
@@ -363,7 +362,6 @@
     "//services/metrics/public/cpp:metrics_cpp",
     "//services/metrics/public/cpp:ukm_builders",
     "//services/metrics/public/mojom",
-    "//third_party/blink/common/privacy_budget:unit_tests",
     "//third_party/blink/public/common",
     "//ui/gfx:test_support",
   ]
diff --git a/third_party/blink/common/privacy_budget/BUILD.gn b/third_party/blink/common/privacy_budget/BUILD.gn
deleted file mode 100644
index 1574bad7..0000000
--- a/third_party/blink/common/privacy_budget/BUILD.gn
+++ /dev/null
@@ -1,97 +0,0 @@
-# Copyright 2020 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//testing/libfuzzer/fuzzer_test.gni")
-
-component("privacy_budget") {
-  visibility = [
-    ":*",
-    "//third_party/blink/common",
-    "//third_party/blink/public/common",
-  ]
-
-  configs += [ "//third_party/blink/common:blink_common_implementation" ]
-
-  sources = [
-    "identifiability_metrics.cc",
-    "identifiability_study_settings.cc",
-    "identifiable_token_builder.cc",
-  ]
-
-  deps = [
-    "//base",
-    "//services/metrics/public/cpp:metrics_cpp",
-    "//services/metrics/public/cpp:ukm_builders",
-    "//services/metrics/public/mojom",
-    "//skia",
-    "//third_party/blink/public/common:common_export",
-    "//third_party/blink/public/common/privacy_budget",
-    "//third_party/blink/public/mojom:web_feature_mojo_bindings",
-  ]
-}
-
-source_set("unit_tests") {
-  testonly = true
-
-  sources = [
-    "identifiability_internal_templates_unittest.cc",
-    "identifiability_metrics_unittest.cc",
-    "identifiability_study_settings_unittest.cc",
-    "identifiable_surface_unittest.cc",
-    "identifiable_token_builder_unittest.cc",
-    "identifiable_token_unittest.cc",
-    "test_ukm_recorder.cc",
-    "test_ukm_recorder.h",
-  ]
-
-  deps = [
-    ":privacy_budget",
-    ":test_support",
-    "//base",
-    "//base/test:test_support",
-    "//components/ukm:test_support",
-    "//services/metrics/public/cpp:metrics_cpp",
-    "//services/metrics/public/cpp:ukm_builders",
-    "//testing/gmock",
-    "//testing/gtest",
-    "//third_party/blink/public/common",
-    "//third_party/blink/public/common/privacy_budget:internal",
-    "//third_party/blink/public/common/privacy_budget:test_support",
-  ]
-}
-
-component("test_support") {
-  testonly = true
-
-  defines = [ "IS_PRIVACY_BUDGET_TEST_SUPPORT_IMPL" ]
-
-  sources = [ "identifiability_sample_test_utils.cc" ]
-
-  deps = [
-    ":privacy_budget",
-    "//base",
-    "//services/metrics/public/cpp:ukm_builders",
-    "//services/metrics/public/mojom",
-    "//third_party/blink/public/common",
-    "//third_party/blink/public/common/privacy_budget:test_support",
-  ]
-}
-
-fuzzer_test("identifiable_token_builder_fuzzer") {
-  sources = [ "identifiable_token_builder_fuzzer.cc" ]
-
-  deps = [
-    "//base",
-    "//third_party/blink/public/common",
-  ]
-}
-
-fuzzer_test("identifiable_token_builder_atomic_fuzzer") {
-  sources = [ "identifiable_token_builder_atomic_fuzzer.cc" ]
-
-  deps = [
-    "//base",
-    "//third_party/blink/public/common",
-  ]
-}
diff --git a/third_party/blink/common/privacy_budget/DEPS b/third_party/blink/common/privacy_budget/DEPS
deleted file mode 100644
index 43589b5..0000000
--- a/third_party/blink/common/privacy_budget/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
-    "+skia/ext"
-]
\ No newline at end of file
diff --git a/third_party/blink/common/privacy_budget/DIR_METADATA b/third_party/blink/common/privacy_budget/DIR_METADATA
deleted file mode 100644
index 5e0dd183..0000000
--- a/third_party/blink/common/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1,2 +0,0 @@
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
-
diff --git a/third_party/blink/common/privacy_budget/OWNERS b/third_party/blink/common/privacy_budget/OWNERS
deleted file mode 100644
index dc54869..0000000
--- a/third_party/blink/common/privacy_budget/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/blink/public/common/privacy_budget/OWNERS
diff --git a/third_party/blink/common/privacy_budget/README.md b/third_party/blink/common/privacy_budget/README.md
deleted file mode 100644
index 15ba5ae..0000000
--- a/third_party/blink/common/privacy_budget/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Privacy Budget: Core Metrics and Aggregation
-
-See [Privacy Budget: Code
-Locations](../../../../docs/privacy_budget/privacy_budget_code_locations.md) for
-details.
-
diff --git a/third_party/blink/common/privacy_budget/identifiability_internal_templates_unittest.cc b/third_party/blink/common/privacy_budget/identifiability_internal_templates_unittest.cc
deleted file mode 100644
index ea7ce28..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_internal_templates_unittest.cc
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h"
-
-#include <cstdint>
-#include <limits>
-#include <type_traits>
-
-#include "build/build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-namespace internal {
-
-TEST(IdentifiabilityInternalTemplatesTest, DigestOfObjectRepresentation) {
-  const int kV = 5;
-  const int& kRV = kV;
-  const volatile int& kRVV = kV;
-
-  // Note that both little and big endian systems produce the same result from
-  // DigestOfObjectRepresentation();
-
-  // Positive unsigned integers.
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(UINT8_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(UINT16_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(UINT32_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(UINT64_C(5)));
-
-  // Positive signed integers.
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(INT8_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(INT16_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(INT32_C(5)));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(INT64_C(5)));
-  // char
-  EXPECT_EQ(INT64_C(65), DigestOfObjectRepresentation('A'));
-
-  // Negative integers.
-  EXPECT_EQ(INT64_C(-5), DigestOfObjectRepresentation(INT8_C(-5)));
-  EXPECT_EQ(INT64_C(-5), DigestOfObjectRepresentation(INT16_C(-5)));
-  EXPECT_EQ(INT64_C(-5), DigestOfObjectRepresentation(INT32_C(-5)));
-  EXPECT_EQ(INT64_C(-5), DigestOfObjectRepresentation(INT64_C(-5)));
-
-  // Large unsigned integer. These wrap around for 2s complement arithmetic.
-  EXPECT_EQ(INT64_C(-1),
-            DigestOfObjectRepresentation(std::numeric_limits<uint64_t>::max()));
-
-  // CV qualified types should be unwrapped.
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(kV));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(kRV));
-  EXPECT_EQ(INT64_C(5), DigestOfObjectRepresentation(kRVV));
-}
-
-}  // namespace internal
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_metric_builder_unittest.cc b/third_party/blink/common/privacy_budget/identifiability_metric_builder_unittest.cc
deleted file mode 100644
index 77f671b6..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_metric_builder_unittest.cc
+++ /dev/null
@@ -1,284 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
-
-#include <cinttypes>
-#include <limits>
-#include <string_view>
-
-#include "base/strings/stringprintf.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/common/privacy_budget/test_ukm_recorder.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom.h"
-
-namespace blink {
-
-TEST(IdentifiabilityMetricBuilderTest, Set) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-
-  IdentifiabilityMetricBuilder builder(ukm::SourceIdObj{});
-  constexpr int64_t kInputHash = 2;
-  constexpr int64_t kValue = 3;
-
-  const auto kSurface = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kInputHash);
-
-  builder.Add(kSurface, kValue);
-  builder.Record(&recorder);
-
-  ASSERT_EQ(1u, collector.entries().size());
-  auto& entry = collector.entries().front();
-
-  EXPECT_EQ(entry.metrics.size(), 1u);
-  EXPECT_EQ(entry.metrics.begin()->surface, kSurface);
-  EXPECT_EQ(entry.metrics.begin()->value, kValue);
-}
-
-TEST(IdentifiabilityMetricBuilderTest, BuilderOverload) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-
-  constexpr int64_t kValue = 3;
-  constexpr int64_t kInputHash = 2;
-  constexpr auto kSurface = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kInputHash);
-
-  const auto kSource = ukm::SourceIdObj::New();
-  IdentifiabilityMetricBuilder(kSource).Add(kSurface, kValue).Record(&recorder);
-
-  ASSERT_EQ(1u, collector.entries().size());
-  test::ScopedIdentifiabilityTestSampleCollector::Entry expected_entry =
-      collector.entries().front();
-  collector.ClearEntries();
-
-  // Yes, it seems cyclical, but this tests that the overloaded constructors
-  // for IdentifiabilityMetricBuilder are equivalent.
-  const ukm::SourceId kUkmSource = kSource.ToInt64();
-  IdentifiabilityMetricBuilder(kUkmSource)
-      .Add(kSurface, kValue)
-      .Record(&recorder);
-  ASSERT_EQ(1u, collector.entries().size());
-  test::ScopedIdentifiabilityTestSampleCollector::Entry entry =
-      collector.entries().front();
-
-  EXPECT_EQ(expected_entry.source, entry.source);
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetWebfeature) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-
-  constexpr int64_t kValue = 3;
-  constexpr int64_t kTestInput =
-      static_cast<int64_t>(mojom::WebFeature::kEventSourceDocument);
-
-  IdentifiabilityMetricBuilder builder(ukm::SourceIdObj{});
-  builder.AddWebFeature(mojom::WebFeature::kEventSourceDocument, kValue)
-      .Record(&recorder);
-  ASSERT_EQ(1u, collector.entries().size());
-  auto entry = collector.entries().front();
-  collector.ClearEntries();
-
-  // Only testing that using SetWebfeature(x,y) is equivalent to
-  // .Set(IdentifiableSurface::FromTypeAndToken(kWebFeature, x), y);
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(IdentifiableSurface::FromTypeAndToken(
-               IdentifiableSurface::Type::kWebFeature, kTestInput),
-           kValue)
-      .Record(&recorder);
-  ASSERT_EQ(1u, collector.entries().size());
-  auto expected_entry = collector.entries().front();
-
-  ASSERT_EQ(entry.metrics.size(), 1u);
-  EXPECT_EQ(entry.metrics, expected_entry.metrics);
-}
-
-namespace {
-
-// clang flags this function as unused although it's used in the MATCHER_P()
-// definition below. Hence the [[maybe_unused]].
-[[maybe_unused]] bool HasSingleEntryWithValue(
-    const test::ScopedIdentifiabilityTestSampleCollector& collector,
-    int64_t value) {
-  if (collector.entries().size() != 1u) {
-    SCOPED_TRACE(base::StringPrintf("Expected unique entry. Found %zu entries.",
-                                    collector.entries().size()));
-    return false;
-  }
-  if (collector.entries().front().metrics.size() != 1u) {
-    SCOPED_TRACE(
-        base::StringPrintf("Expected unique metric. Found %zu entries.",
-                           collector.entries().front().metrics.size()));
-    return false;
-  }
-  return collector.entries().front().metrics.front().value.ToUkmMetricValue() ==
-         value;
-}
-
-MATCHER_P(FirstMetricIs,
-          entry,
-          base::StringPrintf("entry is %s0x%" PRIx64,
-                             negation ? "not " : "",
-                             entry)) {
-  return HasSingleEntryWithValue(arg, entry);
-}  // namespace
-
-enum class Never { kGonna, kGive, kYou, kUp };
-
-constexpr IdentifiableSurface kTestSurface =
-    IdentifiableSurface::FromTypeAndToken(
-        IdentifiableSurface::Type::kReservedInternal,
-        0);
-
-// Sample values
-const char kAbcd[] = "abcd";
-const int64_t kExpectedHashOfAbcd = -0x08a5c475eb66bd73;
-
-// 5.1f
-const int64_t kExpectedHashOfOnePointFive = 0x3ff8000000000000;
-
-}  // namespace
-
-TEST(IdentifiabilityMetricBuilderTest, SetChar) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, 'A')
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(65)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetCharArray) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiableToken sample(kAbcd);
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, sample)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(kExpectedHashOfAbcd));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetStringPiece) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  // StringPiece() needs an explicit constructor invocation.
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, IdentifiableToken(std::string_view(kAbcd)))
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(kExpectedHashOfAbcd));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetStdString) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiableToken sample((std::string(kAbcd)));
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, sample)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(kExpectedHashOfAbcd));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetInt) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, -5)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(-5)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetIntRef) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  int x = -5;
-  int& xref = x;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, xref)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(-5)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetIntConstRef) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  int x = -5;
-  const int& xref = x;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, xref)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(-5)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetUnsigned) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, 5u)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(5)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetUint64) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, UINT64_C(5))
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(5)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetBigUnsignedInt) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  // Slightly different in that this value cannot be converted into the sample
-  // type without loss. Hence it is digested as raw bytes.
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, std::numeric_limits<uint64_t>::max())
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(-1)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetFloat) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, 1.5f)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(kExpectedHashOfOnePointFive));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetDouble) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, 1.5l)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(kExpectedHashOfOnePointFive));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetEnum) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, Never::kUp)
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(3)));
-}
-
-TEST(IdentifiabilityMetricBuilderTest, SetParameterPack) {
-  test::ScopedIdentifiabilityTestSampleCollector collector;
-  test::TestUkmRecorder recorder;
-  IdentifiabilityMetricBuilder(ukm::SourceIdObj{})
-      .Add(kTestSurface, IdentifiableToken(1, 2, 3.0, 4, 'a'))
-      .Record(&recorder);
-  EXPECT_THAT(collector, FirstMetricIs(INT64_C(0x672cf4c107b5b22)));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_metrics.cc b/third_party/blink/common/privacy_budget/identifiability_metrics.cc
deleted file mode 100644
index c2d1f283..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_metrics.cc
+++ /dev/null
@@ -1,71 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
-
-#include <cstdint>
-
-#include "base/containers/span.h"
-#include "base/hash/legacy_hash.h"
-
-namespace blink {
-
-uint64_t IdentifiabilityDigestOfBytes(base::span<const uint8_t> in) {
-  // The chosen hash function satisfies the following requirements:
-  //
-  //   * Fast. These hashes will need to be calculated during performance
-  //     critical code.
-  //   * Suitable for fingerprinting. I.e. broad domain, good diffusion, low
-  //     collision rate.
-  //   * Resistant to hash flooding.
-  //   * Able to use the entire 64-bit space we have at our disposal.
-  //   * Either support iterative operation or be usable as a primitive for
-  //     constructing one.
-  //   * Remains stable for the duration of the identifiability study O(months).
-  //     This one is trivial. It just means that the hash is not in danger of
-  //     imminent change.
-  //   * Implemented, well tested, and usable by //content, //chrome, as well
-  //     as //blink/common.
-  //
-  // It is not a requirement for the digest to be a cryptographic hash. I.e. not
-  // necessary to deter second-preimage construction.
-  //
-  // base::PersistentHash(): (Rejected)
-  //   - Based on SuperFastHash() which doesn't meet the fingerprinting
-  //     requirement due to a high collision rate.
-  //   - Digest is 32-bits.
-  //   - No stateful implementation in //base. Blink's StringHasher is
-  //     interestingly a stateful implementation of SuperFastHash but is not
-  //     available in //blink/public/common.
-  //
-  // base::legacy::CityHash64{WithSeed}(): (Selected)
-  //   - Based on Google's CityHash 1.0.3. Some known weaknesses, but still
-  //     good enough.
-  //   - No ready-to-use chaining implementation.
-  //   + Digest is 64-bits.
-  //   + Seeded variant is a useful primitive for a chained hash function.
-  //     Would be better if it took two seeds, but one is also usable.
-  //
-  // Other hash functions were considered, but were rejected due to one or more
-  // of the following reasons:
-  //   - An implementation was not available.
-  //   - The version available has significant known weaknesses.
-  //
-  // One in particular that would have been nice to have is FarmHash.
-  //
-  // CityHash is quite efficient for small buffers. Operation counts are
-  // roughly as follows. For small buffers, fetches dominate.:
-  //
-  //     Length │  Fetches │   Muls  │ Shifts  │
-  //     ───────┼──────────┼─────────┼─────────┤
-  //     1..16  │     3    │    3    │    4    │
-  //     ───────┼──────────┼─────────┼─────────┤
-  //     17..32 │     4    │    3    │    8    │
-  //     ───────┼──────────┼─────────┼─────────┤
-  //     33..64 │    10    │    4    │   18    │
-  //     ───────┴──────────┴─────────┴─────────┘
-  return base::legacy::CityHash64(in);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_metrics_unittest.cc b/third_party/blink/common/privacy_budget/identifiability_metrics_unittest.cc
deleted file mode 100644
index a5e66a01..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_metrics_unittest.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
-
-#include <cstdint>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-TEST(IdentifiabilityMetricsTest, IdentifiabilityDigestOfBytes_Basic) {
-  const uint8_t kInput[] = {1, 2, 3, 4, 5};
-  auto digest = IdentifiabilityDigestOfBytes(kInput);
-
-  // Due to our requirement that the digest be stable and persistable, this test
-  // should always pass once the code reaches the stable branch.
-  EXPECT_EQ(UINT64_C(0x7cd845f1db5ad659), digest);
-}
-
-TEST(IdentifiabilityMetricsTest, IdentifiabilityDigestOfBytes_Padding) {
-  const uint8_t kTwoBytes[] = {1, 2};
-  const std::vector<uint8_t> kLong(16 * 1024, 'x');
-
-  // Ideally we should be using all 64-bits or at least the 56 LSBs.
-  EXPECT_EQ(UINT64_C(0xb74c74c9fcf0505a),
-            IdentifiabilityDigestOfBytes(kTwoBytes));
-  EXPECT_EQ(UINT64_C(0x76b3567105dc5253), IdentifiabilityDigestOfBytes(kLong));
-}
-
-TEST(IdentifiabilityMetricsTest, IdentifiabilityDigestOfBytes_EdgeCases) {
-  const std::vector<uint8_t> kEmpty;
-  const uint8_t kOneByte[] = {1};
-
-  // As before, these tests should always pass.
-  EXPECT_EQ(UINT64_C(0x9ae16a3b2f90404f), IdentifiabilityDigestOfBytes(kEmpty));
-  EXPECT_EQ(UINT64_C(0x6209312a69a56947),
-            IdentifiabilityDigestOfBytes(kOneByte));
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_sample_test_utils.cc b/third_party/blink/common/privacy_budget/identifiability_sample_test_utils.cc
deleted file mode 100644
index f7ae5b07..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_sample_test_utils.cc
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "third_party/blink/public/common/privacy_budget/identifiability_sample_test_utils.h"
-
-namespace blink {
-
-bool CountingSettingsProvider::IsMetaExperimentActive() const {
-  ++state_->count_of_is_meta_experiment_active;
-  return state_->response_for_is_meta_experiment_active;
-}
-
-bool CountingSettingsProvider::IsActive() const {
-  ++state_->count_of_is_active;
-  return state_->response_for_is_active;
-}
-
-bool CountingSettingsProvider::IsAnyTypeOrSurfaceBlocked() const {
-  ++state_->count_of_is_any_type_or_surface_blocked;
-  return state_->response_for_is_anything_blocked;
-}
-
-bool CountingSettingsProvider::IsSurfaceAllowed(
-    IdentifiableSurface surface) const {
-  ++state_->count_of_is_surface_allowed;
-  return state_->response_for_is_allowed;
-}
-
-bool CountingSettingsProvider::IsTypeAllowed(
-    IdentifiableSurface::Type type) const {
-  ++state_->count_of_is_type_allowed;
-  return state_->response_for_is_allowed;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_study_settings.cc b/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
deleted file mode 100644
index 0bf0873b..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_study_settings.cc
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-
-#include <initializer_list>
-#include <optional>
-#include <random>
-
-#include "base/check.h"
-#include "base/compiler_specific.h"
-#include "base/no_destructor.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/threading/sequence_local_storage_slot.h"
-#include "base/trace_event/common/trace_event_common.h"
-#include "base/trace_event/trace_event.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace blink {
-
-namespace {
-
-bool IdentifiabilityTracingEnabled() {
-  bool tracing_enabled;
-  TRACE_EVENT_CATEGORY_GROUP_ENABLED(
-      TRACE_DISABLED_BY_DEFAULT("identifiability"), &tracing_enabled);
-  return tracing_enabled;
-}
-
-// IdentifiabilityStudySettings is meant to be used as a global singleton. Its
-// use is subject to the following constraints.
-//
-//   1. The embedder should be able to set the
-//      IdentifiabilityStudySettingsProvider at any point during execution. This
-//      relaxation allows the embedder to perform any required initialization
-//      without blocking process startup.
-//
-//   2. Get() and the returned IdentifiabilityStudySettings instance should be
-//      usable from any thread. The returned object must always be well
-//      formed with an infinite lifetime.
-//
-//   3. Calling Get() "prior" to the embedder calling SetProvider() should be
-//      harmless and non-blocking.
-//
-//   4. Be fast.
-class ThreadsafeSettingsWrapper {
- public:
-  ThreadsafeSettingsWrapper() = default;
-
-  const IdentifiabilityStudySettings* GetSettings() {
-    // Access to initialized_settings_ is behind a memory barrier used for
-    // accessing the atomic flag |initialized_|. The state of
-    // |initialized_settings_| is consistent due to the acquire-release
-    // semantics enforced by |AtomicFlag|. I.e. writes prior to
-    // AtomicFlag::Set() is visible after a AtomicFlag::IsSet() which returns
-    // true.
-    //
-    // If the flag is not set, then |default_settings_| can be used instead.
-    //
-    // In either case, the returned pointer...
-    //   1. ... Points to a well formed IdentifiabilityStudySettings object.
-    //   2. ... Is valid for the remainder of the process lifetime.
-    //   3. ... Is safe to use from any thread.
-    if (!initialized_.IsSet())
-      return &default_settings_;
-    return &initialized_settings_.value();
-  }
-
-  // Same restrictions as IdentifiabilityStudySettings::SetGlobalProvider().
-  void SetProvider(
-      std::unique_ptr<IdentifiabilityStudySettingsProvider> provider) {
-    DCHECK(!initialized_.IsSet());
-    initialized_settings_.emplace(std::move(provider));
-    initialized_.Set();
-  }
-
-  void ResetStateForTesting() {
-    initialized_settings_.reset();
-    initialized_.UnsafeResetForTesting();
-  }
-
-  // Function local static initializer is initialized in a threadsafe manner.
-  // This object itself is cheap to construct.
-  static ThreadsafeSettingsWrapper* GetWrapper() {
-    static base::NoDestructor<ThreadsafeSettingsWrapper> wrapper;
-    return wrapper.get();
-  }
-
- private:
-  std::optional<IdentifiabilityStudySettings> initialized_settings_;
-  const IdentifiabilityStudySettings default_settings_;
-  base::AtomicFlag initialized_;
-};
-
-}  // namespace
-
-IdentifiabilityStudySettingsProvider::~IdentifiabilityStudySettingsProvider() =
-    default;
-
-IdentifiabilityStudySettings::IdentifiabilityStudySettings() = default;
-
-IdentifiabilityStudySettings::IdentifiabilityStudySettings(
-    std::unique_ptr<IdentifiabilityStudySettingsProvider> provider)
-    : provider_(std::move(provider)),
-      is_enabled_(provider_->IsActive()),
-      is_any_surface_or_type_blocked_(provider_->IsAnyTypeOrSurfaceBlocked()),
-      is_meta_experiment_active_(provider_->IsMetaExperimentActive()) {}
-
-IdentifiabilityStudySettings::~IdentifiabilityStudySettings() = default;
-
-// static
-const IdentifiabilityStudySettings* IdentifiabilityStudySettings::Get() {
-  return ThreadsafeSettingsWrapper::GetWrapper()->GetSettings();
-}
-
-// static
-void IdentifiabilityStudySettings::SetGlobalProvider(
-    std::unique_ptr<IdentifiabilityStudySettingsProvider> provider) {
-  ThreadsafeSettingsWrapper::GetWrapper()->SetProvider(std::move(provider));
-}
-
-void IdentifiabilityStudySettings::ResetStateForTesting() {
-  ThreadsafeSettingsWrapper::GetWrapper()->ResetStateForTesting();
-}
-
-bool IdentifiabilityStudySettings::IsActive() const {
-  return is_enabled_ || is_meta_experiment_active_;
-}
-
-bool IdentifiabilityStudySettings::ShouldSampleWebFeature(
-    mojom::WebFeature feature) const {
-  return ShouldSampleSurface(IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, feature));
-}
-
-bool IdentifiabilityStudySettings::ShouldSampleSurface(
-    IdentifiableSurface surface) const {
-  if (!ShouldSampleAnything()) [[likely]] {
-    return false;
-  }
-
-  if (!is_any_surface_or_type_blocked_) [[likely]] {
-    return true;
-  }
-
-  if (is_meta_experiment_active_) {
-    return true;
-  }
-
-  return provider_->IsSurfaceAllowed(surface);
-}
-
-bool IdentifiabilityStudySettings::ShouldSampleType(
-    IdentifiableSurface::Type type) const {
-  if (!ShouldSampleAnything()) [[likely]] {
-    return false;
-  }
-
-  if (!is_any_surface_or_type_blocked_) [[likely]] {
-    return true;
-  }
-
-  if (is_meta_experiment_active_) {
-    return true;
-  }
-
-  return provider_->IsTypeAllowed(type);
-}
-
-bool IdentifiabilityStudySettings::ShouldSampleAnything() const {
-  return IsActive() || IdentifiabilityTracingEnabled();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc b/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc
deleted file mode 100644
index cadc1fa..0000000
--- a/third_party/blink/common/privacy_budget/identifiability_study_settings_unittest.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
-#include <memory>
-
-#include "base/memory/raw_ptr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_sample_test_utils.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace blink {
-
-TEST(IdentifiabilityStudySettingsTest, DisabledProvider) {
-  CallCounts counts{.response_for_is_active = false};
-
-  IdentifiabilityStudySettings settings(
-      std::make_unique<CountingSettingsProvider>(&counts));
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_EQ(1, counts.count_of_is_any_type_or_surface_blocked);
-
-  EXPECT_FALSE(settings.IsActive());
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_FALSE(settings.ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_FALSE(
-      settings.ShouldSampleType(IdentifiableSurface::Type::kCanvasReadback));
-
-  // None of these should have been called.
-  EXPECT_EQ(0, counts.count_of_is_surface_allowed);
-  EXPECT_EQ(0, counts.count_of_is_type_allowed);
-}
-
-TEST(IdentifiabilityStudySettingsTest, MetaExperimentActive) {
-  CallCounts counts{.response_for_is_meta_experiment_active = true};
-
-  IdentifiabilityStudySettings settings(
-      std::make_unique<CountingSettingsProvider>(&counts));
-
-  // No other calls should be made.
-  EXPECT_TRUE(settings.IsActive());
-  EXPECT_TRUE(settings.ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_TRUE(
-      settings.ShouldSampleType(IdentifiableSurface::Type::kWebFeature));
-
-  EXPECT_EQ(1, counts.count_of_is_meta_experiment_active);
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_EQ(1, counts.count_of_is_any_type_or_surface_blocked);
-  EXPECT_EQ(0, counts.count_of_is_surface_allowed);
-  EXPECT_EQ(0, counts.count_of_is_type_allowed);
-}
-
-TEST(IdentifiabilityStudySettingsTest,
-     MetaExperimentActiveWithBlockedTypeOrSurface) {
-  CallCounts counts{
-      .response_for_is_meta_experiment_active = true,
-      .response_for_is_active = true,
-      .response_for_is_anything_blocked = true,
-      .response_for_is_allowed = false,
-  };
-
-  IdentifiabilityStudySettings settings(
-      std::make_unique<CountingSettingsProvider>(&counts));
-
-  // No other calls should be made.
-  EXPECT_TRUE(settings.IsActive());
-  EXPECT_TRUE(settings.ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_TRUE(
-      settings.ShouldSampleType(IdentifiableSurface::Type::kWebFeature));
-
-  EXPECT_EQ(1, counts.count_of_is_meta_experiment_active);
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_EQ(1, counts.count_of_is_any_type_or_surface_blocked);
-  EXPECT_EQ(0, counts.count_of_is_surface_allowed);
-  EXPECT_EQ(0, counts.count_of_is_type_allowed);
-}
-
-TEST(IdentifiabilityStudySettingsTest, IsActiveButNothingIsBlocked) {
-  CallCounts counts{.response_for_is_meta_experiment_active = false,
-                    .response_for_is_active = true,
-                    .response_for_is_anything_blocked = false,
-
-                    // Note that this contradicts the above, but it shouldn't
-                    // matter since Is*Blocked() should not be called at all.
-                    .response_for_is_allowed = true};
-
-  IdentifiabilityStudySettings settings(
-      std::make_unique<CountingSettingsProvider>(&counts));
-
-  // No other calls should be made.
-  EXPECT_TRUE(settings.IsActive());
-  EXPECT_TRUE(settings.ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_TRUE(
-      settings.ShouldSampleType(IdentifiableSurface::Type::kWebFeature));
-
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_EQ(1, counts.count_of_is_any_type_or_surface_blocked);
-  EXPECT_EQ(0, counts.count_of_is_surface_allowed);
-  EXPECT_EQ(0, counts.count_of_is_type_allowed);
-}
-
-TEST(IdentifiabilityStudySettingsTest, IsSurfaceOrTypeBlocked) {
-  CallCounts counts{.response_for_is_meta_experiment_active = false,
-                    .response_for_is_active = true,
-                    .response_for_is_anything_blocked = true,
-                    .response_for_is_allowed = false};
-
-  IdentifiabilityStudySettings settings(
-      std::make_unique<CountingSettingsProvider>(&counts));
-
-  // No other calls should be made.
-  EXPECT_TRUE(settings.IsActive());
-  EXPECT_FALSE(settings.ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_FALSE(
-      settings.ShouldSampleType(IdentifiableSurface::Type::kWebFeature));
-
-  EXPECT_EQ(1, counts.count_of_is_active);
-  EXPECT_EQ(1, counts.count_of_is_any_type_or_surface_blocked);
-  EXPECT_EQ(1, counts.count_of_is_surface_allowed);
-  EXPECT_EQ(1, counts.count_of_is_type_allowed);
-}
-
-TEST(IdentifiabilityStudySettingsTest, DefaultSettings) {
-  auto* default_settings = IdentifiabilityStudySettings::Get();
-  EXPECT_FALSE(default_settings->IsActive());
-  EXPECT_FALSE(default_settings->ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_FALSE(default_settings->ShouldSampleType(
-      IdentifiableSurface::Type::kWebFeature));
-}
-
-TEST(IdentifiabilityStudySettingsTest, StaticSetProvider) {
-  CallCounts counts{.response_for_is_meta_experiment_active = false,
-                    .response_for_is_active = true,
-                    .response_for_is_anything_blocked = true,
-                    .response_for_is_allowed = true};
-
-  IdentifiabilityStudySettings::SetGlobalProvider(
-      std::make_unique<CountingSettingsProvider>(&counts));
-  auto* settings = IdentifiabilityStudySettings::Get();
-  EXPECT_TRUE(settings->IsActive());
-  EXPECT_TRUE(settings->ShouldSampleSurface(IdentifiableSurface()));
-  EXPECT_EQ(1, counts.count_of_is_surface_allowed);
-
-  IdentifiabilityStudySettings::ResetStateForTesting();
-
-  auto* default_settings = IdentifiabilityStudySettings::Get();
-  EXPECT_FALSE(default_settings->IsActive());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiable_surface_unittest.cc b/third_party/blink/common/privacy_budget/identifiable_surface_unittest.cc
deleted file mode 100644
index 54800d7..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_surface_unittest.cc
+++ /dev/null
@@ -1,102 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-#include <functional>
-#include <unordered_set>
-
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-TEST(IdentifiableSurfaceTest, FromTypeAndTokenIsConstexpr) {
-  constexpr uint64_t kTestInputHash = 5u;
-  constexpr auto kSurface = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHash);
-
-  static_assert(
-      (kTestInputHash << 8) +
-              static_cast<uint64_t>(IdentifiableSurface::Type::kWebFeature) ==
-          kSurface.ToUkmMetricHash(),
-      "");
-  static_assert(IdentifiableSurface::Type::kWebFeature == kSurface.GetType(),
-                "");
-  static_assert(kTestInputHash == kSurface.GetInputHash(), "");
-}
-
-TEST(IdentifiableSurfaceTest, FromKeyIsConstexpr) {
-  constexpr uint64_t kTestInputHash = 5u;
-  constexpr uint64_t kTestMetricHash =
-      ((kTestInputHash << 8) |
-       static_cast<uint64_t>(IdentifiableSurface::Type::kWebFeature));
-  constexpr auto kSurface =
-      IdentifiableSurface::FromMetricHash(kTestMetricHash);
-  static_assert(kTestMetricHash == kSurface.ToUkmMetricHash(), "");
-  static_assert(IdentifiableSurface::Type::kWebFeature == kSurface.GetType(),
-                "");
-}
-
-TEST(IdentifiableSurfaceTest, AllowsMaxTypeValue) {
-  constexpr uint64_t kInputHash = UINT64_C(0x1123456789abcdef);
-  constexpr auto kSurface = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kMax, kInputHash);
-
-  EXPECT_EQ(UINT64_C(0x23456789abcdefff), kSurface.ToUkmMetricHash());
-  EXPECT_EQ(IdentifiableSurface::Type::kMax, kSurface.GetType());
-
-  // The lower 56 bits of kInputHash should match GetInputHash().
-  EXPECT_EQ(kInputHash << 8, kSurface.GetInputHash() << 8);
-  EXPECT_NE(kInputHash, kSurface.GetInputHash());
-}
-
-TEST(IdentifiableSurfaceTest, IdentifiableSurfaceHash) {
-  constexpr uint64_t kTestInputHashA = 1;
-  constexpr uint64_t kTestInputHashB = 3;
-
-  // surface2 == surface3 != surface1
-  auto surface1 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashA);
-  auto surface2 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashB);
-  auto surface3 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashB);
-
-  IdentifiableSurfaceHash hash_object;
-
-  size_t hash1 = hash_object(surface1);
-  size_t hash2 = hash_object(surface2);
-  size_t hash3 = hash_object(surface3);
-
-  EXPECT_NE(hash1, hash2);
-  EXPECT_EQ(hash3, hash2);
-
-  std::unordered_set<IdentifiableSurface, IdentifiableSurfaceHash> surface_set;
-  surface_set.insert(surface1);
-  surface_set.insert(surface2);
-  surface_set.insert(surface3);
-
-  EXPECT_EQ(surface_set.size(), 2u);
-  EXPECT_EQ(surface_set.count(surface1), 1u);
-}
-
-TEST(IdentifiableSurfaceTest, Comparison) {
-  constexpr uint64_t kTestInputHashA = 1;
-  constexpr uint64_t kTestInputHashB = 3;
-
-  // surface2 == surface3 != surface1
-  auto surface1 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashA);
-  auto surface2 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashB);
-  auto surface3 = IdentifiableSurface::FromTypeAndToken(
-      IdentifiableSurface::Type::kWebFeature, kTestInputHashB);
-
-  EXPECT_TRUE(surface2 == surface3);
-  EXPECT_TRUE(surface1 != surface3);
-  EXPECT_TRUE(surface1 < surface2);
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiable_token_builder.cc b/third_party/blink/common/privacy_budget/identifiable_token_builder.cc
deleted file mode 100644
index c412f0c..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_token_builder.cc
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-
-#include <algorithm>
-#include <iterator>
-#include <type_traits>
-
-#include "base/check.h"
-#include "base/check_op.h"
-#include "base/hash/legacy_hash.h"
-
-namespace blink {
-
-IdentifiableTokenBuilder::IdentifiableTokenBuilder()
-    : chaining_value_(kChainingValueSeed) {
-  // Ensures that BlockBuffer iterators are random-access on all platforms.
-  static_assert(
-      std::is_same<std::random_access_iterator_tag,
-                   std::iterator_traits<
-                       BlockBuffer::iterator>::iterator_category>::value,
-      "Iterator operations may not be constant time.");
-}
-
-IdentifiableTokenBuilder::IdentifiableTokenBuilder(
-    const IdentifiableTokenBuilder& other) {
-  partial_ = other.partial_;
-  position_ = partial_.begin();
-  std::advance(position_, other.PartialSize());
-  chaining_value_ = other.chaining_value_;
-}
-
-IdentifiableTokenBuilder::IdentifiableTokenBuilder(ByteSpan buffer)
-    : IdentifiableTokenBuilder() {
-  AddBytes(buffer);
-}
-
-IdentifiableTokenBuilder& IdentifiableTokenBuilder::AddBytes(ByteSpan message) {
-  DCHECK(position_ != partial_.end());
-  // Phase 1:
-  //    Slurp in as much of the message as necessary if there's a partial block
-  //    already assembled. Copying is expensive, so |partial_| is only involved
-  //    when there's some left over bytes from a prior round.
-  if (partial_.begin() != position_ && !message.empty())
-    message = SkimIntoPartial(message);
-
-  if (message.empty())
-    return *this;
-
-  // Phase 2:
-  //    Consume as many full blocks as possible from |message|.
-  DCHECK(position_ == partial_.begin());
-  while (message.size() >= kBlockSizeInBytes) {
-    DigestBlock(message.first<kBlockSizeInBytes>());
-    message = message.subspan(kBlockSizeInBytes);
-  }
-  if (message.empty())
-    return *this;
-
-  // Phase 3:
-  //    Whatever remains is stuffed into the partial buffer.
-  message = SkimIntoPartial(message);
-  DCHECK(message.empty());
-  return *this;
-}
-
-IdentifiableTokenBuilder& IdentifiableTokenBuilder::AddAtomic(ByteSpan buffer) {
-  AlignPartialBuffer();
-  AddValue(buffer.size_bytes());
-  AddBytes(buffer);
-  AlignPartialBuffer();
-  return *this;
-}
-
-IdentifiableTokenBuilder::operator IdentifiableToken() const {
-  return GetToken();
-}
-
-IdentifiableToken IdentifiableTokenBuilder::GetToken() const {
-  if (position_ == partial_.begin())
-    return chaining_value_;
-
-  return IdentifiableToken(
-      base::legacy::CityHash64WithSeed(GetPartialBlock(), chaining_value_));
-}
-
-IdentifiableTokenBuilder::ByteSpan IdentifiableTokenBuilder::SkimIntoPartial(
-    ByteSpan message) {
-  DCHECK(!message.empty() && position_ != partial_.end());
-  const auto to_copy = std::min<size_t>(
-      std::distance(position_, partial_.end()), message.size());
-  position_ = std::copy_n(message.begin(), to_copy, position_);
-  if (position_ == partial_.end())
-    DigestBlock(TakeCompletedBlock());
-  return message.subspan(to_copy);
-}
-
-void IdentifiableTokenBuilder::AlignPartialBuffer() {
-  const auto padding_to_add =
-      kBlockAlignment - (PartialSize() % kBlockAlignment);
-  if (padding_to_add == kBlockAlignment)
-    return;
-
-  position_ = std::fill_n(position_, padding_to_add, 0);
-
-  if (position_ == partial_.end())
-    DigestBlock(TakeCompletedBlock());
-
-  DCHECK(position_ != partial_.end());
-  DCHECK(IsAligned());
-}
-
-void IdentifiableTokenBuilder::DigestBlock(ConstFullBlockSpan block) {
-  // partial_ should've been flushed before calling this.
-  DCHECK(position_ == partial_.begin());
-
-  // The chaining value (initialized with the initialization vector
-  // kChainingValueSeed) is only used for diffusion. There's no length padding
-  // being done here since we aren't interested in second-preimage issues.
-  //
-  // There is a concern over hash flooding, but that's something the entire
-  // study has more-or-less accepted for some metrics and is dealt with during
-  // the analysis phase.
-  chaining_value_ =
-      base::legacy::CityHash64WithSeed(base::span(block), chaining_value_);
-}
-
-size_t IdentifiableTokenBuilder::PartialSize() const {
-  return std::distance<BlockBuffer::const_iterator>(partial_.begin(),
-                                                    position_);
-}
-
-IdentifiableTokenBuilder::ConstFullBlockSpan
-IdentifiableTokenBuilder::TakeCompletedBlock() {
-  DCHECK(position_ == partial_.end());
-  auto buffer = base::span(partial_);
-  position_ = partial_.begin();
-  return buffer;
-}
-
-bool IdentifiableTokenBuilder::IsAligned() const {
-  return PartialSize() % kBlockAlignment == 0;
-}
-
-IdentifiableTokenBuilder::ByteSpan IdentifiableTokenBuilder::GetPartialBlock()
-    const {
-  return ByteSpan(partial_).first(PartialSize());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiable_token_builder_atomic_fuzzer.cc b/third_party/blink/common/privacy_budget/identifiable_token_builder_atomic_fuzzer.cc
deleted file mode 100644
index 575cc8d..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_token_builder_atomic_fuzzer.cc
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include <cstdint>
-#include <string>
-
-#include "base/containers/span.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-
-// Similar to identifiable_token_builder_fuzzer except uses AddAtomic() instead
-// of AddBytes().
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* fuzz_data,
-                                      size_t fuzz_data_size) {
-  FuzzedDataProvider fdp(fuzz_data, fuzz_data_size);
-  auto partition_count = fdp.ConsumeIntegralInRange<size_t>(0, fuzz_data_size);
-  blink::IdentifiableTokenBuilder token_builder;
-  for (size_t i = 0; i < partition_count; ++i) {
-    auto partition = fdp.ConsumeRandomLengthString(fuzz_data_size);
-    token_builder.AddAtomic(base::as_byte_span(partition));
-  }
-  auto remainder = fdp.ConsumeRemainingBytes<uint8_t>();
-  token_builder.AddAtomic(base::as_byte_span(remainder));
-  return 0;
-}
diff --git a/third_party/blink/common/privacy_budget/identifiable_token_builder_fuzzer.cc b/third_party/blink/common/privacy_budget/identifiable_token_builder_fuzzer.cc
deleted file mode 100644
index a6303270..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_token_builder_fuzzer.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <fuzzer/FuzzedDataProvider.h>
-
-#include <cstdint>
-#include <string>
-
-#include "base/containers/span.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* fuzz_data,
-                                      size_t fuzz_data_size) {
-  FuzzedDataProvider fdp(fuzz_data, fuzz_data_size);
-  auto partition_count = fdp.ConsumeIntegralInRange<size_t>(0, fuzz_data_size);
-  blink::IdentifiableTokenBuilder token_builder;
-  for (size_t i = 0; i < partition_count; ++i) {
-    auto partition = fdp.ConsumeRandomLengthString(fuzz_data_size);
-    token_builder.AddBytes(base::as_byte_span(partition));
-  }
-  auto remainder = fdp.ConsumeRemainingBytes<uint8_t>();
-  token_builder.AddBytes(base::as_byte_span(remainder));
-  return 0;
-}
diff --git a/third_party/blink/common/privacy_budget/identifiable_token_builder_unittest.cc b/third_party/blink/common/privacy_budget/identifiable_token_builder_unittest.cc
deleted file mode 100644
index ae258fae..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_token_builder_unittest.cc
+++ /dev/null
@@ -1,189 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-
-#include <cstdint>
-#include <vector>
-
-#include "base/containers/span.h"
-#include "base/rand_util.h"
-#include "base/strings/strcat.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-namespace blink {
-
-TEST(IdentifiableTokenBuilderTest, Empty) {
-  IdentifiableTokenBuilder sample;
-  EXPECT_EQ(IdentifiableToken(INT64_C(0x5ad32e10d3a3c2b5)), sample.GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, ConstructVsAdd) {
-  const char kOneByte[1] = {'a'};
-  IdentifiableTokenBuilder add_token;
-  add_token.AddBytes(base::as_byte_span(kOneByte));
-
-  IdentifiableTokenBuilder construct_token(base::as_byte_span(kOneByte));
-  EXPECT_EQ(add_token.GetToken(), construct_token.GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, OneByte) {
-  const char kOneByte[1] = {'a'};
-  IdentifiableTokenBuilder sample;
-  sample.AddBytes(base::as_byte_span(kOneByte));
-  EXPECT_EQ(IdentifiableToken(INT64_C(0x6de50a5cefa7ba0e)), sample.GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, TwoBytesInTwoTakes) {
-  const char kBytes[] = {'a', 'b'};
-  auto bytes_span = base::as_byte_span(kBytes);
-  IdentifiableTokenBuilder whole_span_token(bytes_span);
-  IdentifiableTokenBuilder two_parts_token;
-  two_parts_token.AddBytes(bytes_span.first(1u));
-  two_parts_token.AddBytes(bytes_span.last(1u));
-  EXPECT_EQ(whole_span_token.GetToken(), two_parts_token.GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, SixtySixBytesInTwoTakes) {
-  constexpr size_t kSize = 66;
-  std::vector<char> big_array(kSize, 'a');
-  auto bytes_span = base::as_byte_span(big_array);
-  IdentifiableTokenBuilder whole_span_token(bytes_span);
-  IdentifiableTokenBuilder two_parts_token;
-  two_parts_token.AddBytes(bytes_span.first(kSize / 2));
-  two_parts_token.AddBytes(bytes_span.last(kSize / 2));
-  EXPECT_EQ(whole_span_token.GetToken(), two_parts_token.GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, AddValue) {
-  const auto kExpectedToken = IdentifiableToken(INT64_C(0xe475af2a732298e2));
-
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(INT8_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(UINT8_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(INT16_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(UINT16_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(INT32_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(UINT32_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(INT64_C(1)).GetToken());
-  EXPECT_EQ(kExpectedToken,
-            IdentifiableTokenBuilder().AddValue(UINT64_C(1)).GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, AddAtomic_AlwaysConstant) {
-  const uint8_t kS1[] = {1, 2, 3, 4, 5};
-  EXPECT_EQ(IdentifiableToken(INT64_C(0xfaeb0b8e769729b9)),
-            IdentifiableTokenBuilder().AddAtomic(base::span(kS1)).GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, AddAtomic_PadSuffix) {
-  const uint8_t kS1[] = {1, 2, 3, 4, 5};
-  const uint8_t kS1_padded[] = {5, 0, 0, 0, 0, 0, 0, 0,  // Little endian 5
-                                1, 2, 3, 4, 5, 0, 0, 0};
-  EXPECT_EQ(
-      IdentifiableTokenBuilder().AddAtomic(base::span(kS1)).GetToken(),
-      IdentifiableTokenBuilder().AddBytes(base::span(kS1_padded)).GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, AddAtomic_PadPrefix) {
-  const uint8_t kS2_pre[] = {1, 2};
-  const uint8_t kS2[] = {3, 4, 5};
-  const uint8_t kS2_padded[] = {1, 2, 0, 0, 0, 0, 0, 0,
-                                3, 0, 0, 0, 0, 0, 0, 0,  // Little endian 3
-                                3, 4, 5, 0, 0, 0, 0, 0};
-  EXPECT_EQ(
-      IdentifiableTokenBuilder()
-          .AddBytes(base::span(kS2_pre))
-          .AddAtomic(base::span(kS2))
-          .GetToken(),
-      IdentifiableTokenBuilder().AddBytes(base::span(kS2_padded)).GetToken());
-}
-
-TEST(IdentifiableTokenBuilderTest, AddVsAddAtomic) {
-  const uint8_t kA1[] = {'a', 'b', 'c', 'd'};
-  const uint8_t kA2[] = {'e', 'f', 'g', 'h'};
-  const uint8_t kB1[] = {'a'};
-  const uint8_t kB2[] = {'b', 'c', 'd', 'e', 'f', 'g', 'h'};
-
-  // Adding buffers wth AddBytes() doesn't distinguish between the two
-  // partitions, and this is intentional.
-  IdentifiableTokenBuilder builder_A;
-  builder_A.AddBytes(base::span(kA1));
-  builder_A.AddBytes(base::span(kA2));
-  auto token_for_A = builder_A.GetToken();
-
-  IdentifiableTokenBuilder builder_B;
-  builder_B.AddBytes(base::span(kB1));
-  builder_B.AddBytes(base::span(kB2));
-  auto token_for_B = builder_B.GetToken();
-
-  EXPECT_EQ(token_for_A, token_for_B);
-
-  // However AtomicAdd distinguishes between the two.
-  IdentifiableTokenBuilder atomic_A;
-  atomic_A.AddAtomic(base::span(kA1));
-  atomic_A.AddAtomic(base::span(kA2));
-  auto atomic_token_for_A = atomic_A.GetToken();
-
-  IdentifiableTokenBuilder atomic_B;
-  atomic_B.AddAtomic(base::span(kB1));
-  atomic_B.AddAtomic(base::span(kB2));
-  auto atomic_token_for_B = atomic_B.GetToken();
-
-  EXPECT_NE(atomic_token_for_A, atomic_token_for_B);
-}
-
-TEST(IdentifiableTokenBuilderTest, LotsOfRandomPartitions) {
-  constexpr size_t kLargeBufferSize = 1000 * 1000 * 10;
-  constexpr size_t kCycle = 149;  // A prime
-  std::vector<uint8_t> data(kLargeBufferSize);
-  for (size_t i = 0; i < kLargeBufferSize; ++i) {
-    data[i] = i % kCycle;
-  }
-
-  int partition_count = base::RandInt(50, 500);
-
-  // Pick |partition_count| random numbers between 0 and kLargeBufferSize (half
-  // open) that will indicate where the partitions are. In reality there will be
-  // |partition_count + 1| partitions:
-  //
-  //   |<--------->:<------------>:<---    ..  ...->:<---------------------->|
-  //   |           :              :        ..  ...  :                        |
-  //   0      partitions[0]  partitions[1] .. partitions[n-1] kLargeBufferSize
-  std::vector<size_t> partitions;
-  for (int i = 0; i < partition_count; ++i)
-    partitions.push_back(base::RandInt(0, kLargeBufferSize));
-  std::sort(partitions.begin(), partitions.end());
-
-  std::string trace;
-  base::StringAppendF(&trace, "Partitions[%d]={0", partition_count + 2);
-  for (auto p : partitions)
-    base::StringAppendF(&trace, ", %zu", p);
-  base::StringAppendF(&trace, ", %zu}", kLargeBufferSize);
-  SCOPED_TRACE(trace);
-
-  IdentifiableTokenBuilder partitioned_sample;
-  size_t low = 0;
-  for (auto high : partitions) {
-    ASSERT_LE(low, high);
-    partitioned_sample.AddBytes(base::span(data).subspan(low, high - low));
-    low = high;
-  }
-  partitioned_sample.AddBytes(
-      base::span(data).subspan(low, kLargeBufferSize - low));
-
-  IdentifiableTokenBuilder full_buffer_sample(data);
-  EXPECT_EQ(full_buffer_sample.GetToken(), partitioned_sample.GetToken());
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/identifiable_token_unittest.cc b/third_party/blink/common/privacy_budget/identifiable_token_unittest.cc
deleted file mode 100644
index 92f56da..0000000
--- a/third_party/blink/common/privacy_budget/identifiable_token_unittest.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-#include <string_view>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace blink {
-
-namespace {
-
-// The set of candidate conversion templates depend on whether the conversion is
-// explicit or implicit. This class is used to exercise implicit conversion of
-// IdIdentifiableApiSample.
-struct ImplicitConverter {
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  ImplicitConverter(IdentifiableToken sample) : sample(sample) {}
-
-  IdentifiableToken sample;
-};
-
-}  // namespace
-
-TEST(IdentifiableTokenTest, SampleBool) {
-  bool source_value = false;
-  auto expected_value = INT64_C(0);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleSignedChar) {
-  auto source_value = static_cast<signed char>(-65);
-  auto expected_value = INT64_C(-65);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleChar) {
-  auto source_value = 'A';
-  auto expected_value = INT64_C(65);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleInt) {
-  auto source_value = 123;
-  auto expected_value = INT64_C(123);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleNegativeInt) {
-  auto source_value = -123;
-  auto expected_value = INT64_C(-123);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleUnsigned) {
-  auto source_value = UINT64_C(123);
-  auto expected_value = INT64_C(123);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleBigUnsignedThatFits) {
-  auto source_value =
-      static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) + 1;
-  auto expected_value = std::numeric_limits<int64_t>::min();
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleFloat) {
-  auto source_value = 5.1f;
-  auto expected_value = INT64_C(0x4014666660000000);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleDouble) {
-  auto source_value = 5.1;
-  auto expected_value = INT64_C(0x4014666666666666);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleConstCharArray) {
-  EXPECT_EQ(IdentifiableToken(INT64_C(0xf75a3b8a1499428d)),
-            IdentifiableToken("abcd"));
-  // No implicit converter for const char[].
-}
-
-TEST(IdentifiableTokenTest, SampleStdString) {
-  EXPECT_EQ(IdentifiableToken(INT64_C(0xf75a3b8a1499428d)),
-            IdentifiableToken(std::string("abcd")));
-  // No implicit converter for std::string.
-}
-
-TEST(IdentifiableTokenTest, SampleStringPiece) {
-  auto source_value = std::string_view("abcd");
-  auto expected_value = INT64_C(0xf75a3b8a1499428d);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  // No implicit converter for StringPiece.
-}
-
-TEST(IdentifiableTokenTest, SampleCharSpan) {
-  auto source_value = base::span_from_cstring("abcd");
-  auto expected_value = INT64_C(0xf75a3b8a1499428d);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleStringSpan) {
-  std::string strings[] = {"baby", "shark", "du duu du duu du du"};
-  auto source_value = base::span(strings);
-  auto expected_value = INT64_C(0xd37aad882e58faa5);
-  EXPECT_EQ(IdentifiableToken(expected_value), IdentifiableToken(source_value));
-  EXPECT_EQ(IdentifiableToken(expected_value),
-            ImplicitConverter(source_value).sample);
-}
-
-TEST(IdentifiableTokenTest, SampleTuple) {
-  EXPECT_EQ(IdentifiableToken(INT64_C(0x5848123245be627a)),
-            IdentifiableToken(1, 2, 3, 4, 5));
-  // No implicit converter for tuples.
-}
-
-TEST(IdentifiableTokenTest, SampleHeterogenousTuple) {
-  EXPECT_EQ(IdentifiableToken(INT64_C(0x672cf4c107b5b22)),
-            IdentifiableToken(1, 2, 3.0, 4, 'a'));
-  // No implicit converter for tuples.
-}
-
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/scoped_identifiability_test_sample_collector.cc b/third_party/blink/common/privacy_budget/scoped_identifiability_test_sample_collector.cc
deleted file mode 100644
index c3d33944..0000000
--- a/third_party/blink/common/privacy_budget/scoped_identifiability_test_sample_collector.cc
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-
-#include <memory>
-
-#include "base/notreached.h"
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "services/metrics/public/mojom/ukm_interface.mojom.h"
-#include "third_party/blink/common/privacy_budget/aggregating_sample_collector.h"
-
-namespace blink {
-namespace test {
-
-ScopedIdentifiabilityTestSampleCollector::
-    ScopedIdentifiabilityTestSampleCollector()
-    : scoped_default_(this) {}
-
-ScopedIdentifiabilityTestSampleCollector::
-    ~ScopedIdentifiabilityTestSampleCollector() = default;
-
-void ScopedIdentifiabilityTestSampleCollector::Record(
-    ukm::UkmRecorder* recorder,
-    ukm::SourceId source,
-    std::vector<IdentifiableSample> metrics) {
-  entries_.emplace_back(source, std::move(metrics));
-  AggregatingSampleCollector::UkmMetricsContainerType metrics_map;
-  for (auto metric : entries_.back().metrics) {
-    metrics_map.emplace(metric.surface.ToUkmMetricHash(),
-                        metric.value.ToUkmMetricValue());
-  }
-  recorder->AddEntry(ukm::mojom::UkmEntry::New(
-      source, ukm::builders::Identifiability::kEntryNameHash,
-      std::move(metrics_map)));
-}
-
-void ScopedIdentifiabilityTestSampleCollector::Flush(
-    ukm::UkmRecorder* recorder) {}
-
-void ScopedIdentifiabilityTestSampleCollector::FlushSource(
-    ukm::UkmRecorder* recorder,
-    ukm::SourceId source) {}
-
-void ScopedIdentifiabilityTestSampleCollector::ClearEntries() {
-  entries_.clear();
-}
-
-}  // namespace test
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/test_ukm_recorder.cc b/third_party/blink/common/privacy_budget/test_ukm_recorder.cc
deleted file mode 100644
index 8599ba2..0000000
--- a/third_party/blink/common/privacy_budget/test_ukm_recorder.cc
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/common/privacy_budget/test_ukm_recorder.h"
-
-#include <vector>
-
-#include "services/metrics/public/mojom/ukm_interface.mojom.h"
-
-namespace blink {
-namespace test {
-
-TestUkmRecorder::TestUkmRecorder() = default;
-TestUkmRecorder::~TestUkmRecorder() = default;
-
-std::vector<const ukm::mojom::UkmEntry*> TestUkmRecorder::GetEntriesByHash(
-    uint64_t event_hash) const {
-  std::vector<const ukm::mojom::UkmEntry*> result;
-  for (const auto& entry : entries_) {
-    if (entry->event_hash == event_hash)
-      result.push_back(entry.get());
-  }
-  return result;
-}
-
-}  // namespace test
-}  // namespace blink
diff --git a/third_party/blink/common/privacy_budget/test_ukm_recorder.h b/third_party/blink/common/privacy_budget/test_ukm_recorder.h
deleted file mode 100644
index 5ddbff7e..0000000
--- a/third_party/blink/common/privacy_budget/test_ukm_recorder.h
+++ /dev/null
@@ -1,66 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_COMMON_PRIVACY_BUDGET_TEST_UKM_RECORDER_H_
-#define THIRD_PARTY_BLINK_COMMON_PRIVACY_BUDGET_TEST_UKM_RECORDER_H_
-
-#include <vector>
-
-#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "services/metrics/public/mojom/ukm_interface.mojom.h"
-
-namespace blink {
-namespace test {
-
-// This is a barebones UkmRecorder that has just enough functionality to support
-// the testing being done in this directory.
-//
-// Why this and not `ukm::TestUkmRecorder` ? That one has too many dependencies
-// none of which is necessary for the testing we are doing here in which we are
-// only testing whether the identifiability reporting mechanism properly encodes
-// and passes metrics to the underlying `UkmRecorder`.
-class TestUkmRecorder : public ukm::UkmRecorder {
- public:
-  TestUkmRecorder();
-  ~TestUkmRecorder() override;
-
-  // Count of event entries. This is not the count of metrics since there can be
-  // more than one in each event.
-  size_t entries_count() const { return entries_.size(); }
-
-  // The entries themselves in the order in which they were received.
-  const std::vector<ukm::mojom::UkmEntryPtr>& entries() const {
-    return entries_;
-  }
-
-  // Returns a vector of pointers to entries whose `UkmEntry::event_hash`
-  // matches `event_hash`. The returned pointers should remain valid until
-  // `Purge()` is called or this recorder is destroyed.
-  std::vector<const ukm::mojom::UkmEntry*> GetEntriesByHash(
-      uint64_t event_hash) const;
-
-  // Delete all received entries.
-  void Purge() { entries_.clear(); }
-
-  // UkmRecorder
-  void AddEntry(ukm::mojom::UkmEntryPtr entry) override {
-    entries_.emplace_back(std::move(entry));
-  }
-  void RecordWebDXFeatures(ukm::SourceId source_id,
-                           const std::set<int32_t>& features,
-                           const size_t max_feature_value) override {}
-  void UpdateSourceURL(ukm::SourceId, const GURL&) override {}
-  void UpdateAppURL(ukm::SourceId, const GURL&, const ukm::AppType) override {}
-  void RecordNavigation(ukm::SourceId,
-                        const ukm::UkmSource::NavigationData&) override {}
-  void MarkSourceForDeletion(ukm::SourceId) override {}
-
- private:
-  std::vector<ukm::mojom::UkmEntryPtr> entries_;
-};
-
-}  // namespace test
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_COMMON_PRIVACY_BUDGET_TEST_UKM_RECORDER_H_
diff --git a/third_party/blink/public/common/BUILD.gn b/third_party/blink/public/common/BUILD.gn
index 8cd4386..a11d2f5 100644
--- a/third_party/blink/public/common/BUILD.gn
+++ b/third_party/blink/public/common/BUILD.gn
@@ -71,7 +71,6 @@
   output_name = "blink_common"
 
   public_deps = [
-    "//third_party/blink/common/privacy_budget",
     "//third_party/blink/public/common:headers",
     "//third_party/blink/public/mojom:mojom_modules",
     "//third_party/blink/public/mojom:web_bluetooth_mojo_bindings",
@@ -334,7 +333,6 @@
     "//skia",
     "//skia/public/mojom:shared_typemap_traits",
     "//third_party/blink/public:runtime_features_for_public",
-    "//third_party/blink/public/common/privacy_budget",
     "//third_party/blink/public/common/tokens:tokens_headers",
     "//third_party/blink/public/mojom:mojom_modules_headers",
     "//third_party/blink/public/mojom:mojom_platform_shared",
diff --git a/third_party/blink/public/common/privacy_budget/BUILD.gn b/third_party/blink/public/common/privacy_budget/BUILD.gn
deleted file mode 100644
index bd2501bf..0000000
--- a/third_party/blink/public/common/privacy_budget/BUILD.gn
+++ /dev/null
@@ -1,49 +0,0 @@
-# Copyright 2020 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-source_set("internal") {
-  sources = [ "identifiability_internal_templates.h" ]
-
-  deps = [ "//base" ]
-
-  visibility = [
-    ":*",
-    "//third_party/blink/common/privacy_budget:*",
-  ]
-}
-
-source_set("privacy_budget") {
-  sources = [
-    "identifiability_metrics.h",
-    "identifiability_study_settings.h",
-    "identifiability_study_settings_provider.h",
-    "identifiable_sample.h",
-    "identifiable_surface.h",
-    "identifiable_token.h",
-    "identifiable_token_builder.h",
-  ]
-
-  deps = [
-    ":internal",
-    "//base",
-    "//services/metrics/public/cpp:metrics_cpp",
-    "//services/metrics/public/cpp:ukm_builders",
-    "//services/network/public/cpp",
-    "//third_party/blink/public/common:common_export",
-    "//third_party/blink/public/mojom:web_feature_mojo_bindings",
-  ]
-}
-
-source_set("test_support") {
-  testonly = true
-
-  sources = [ "identifiability_sample_test_utils.h" ]
-
-  public_deps = [ "//third_party/blink/public/common:headers" ]
-
-  deps = [
-    ":internal",
-    "//third_party/blink/public/common:common_export",
-  ]
-}
diff --git a/third_party/blink/public/common/privacy_budget/COMMON_METADATA b/third_party/blink/public/common/privacy_budget/COMMON_METADATA
deleted file mode 100644
index 7718598..0000000
--- a/third_party/blink/public/common/privacy_budget/COMMON_METADATA
+++ /dev/null
@@ -1,7 +0,0 @@
-monorail: {
-  component: "Privacy>Fingerprinting"
-}
-team_email: "privacy-sandbox-dev@chromium.org"
-buganizer_public: {
-  component_id: 1456351
-}
diff --git a/third_party/blink/public/common/privacy_budget/DEPS b/third_party/blink/public/common/privacy_budget/DEPS
deleted file mode 100644
index fd57f1c..0000000
--- a/third_party/blink/public/common/privacy_budget/DEPS
+++ /dev/null
@@ -1,5 +0,0 @@
-include_rules = [
-    "+services/metrics/public/mojom",
-    "+services/metrics/public/cpp",
-    "+third_party/blink/public/mojom/web_feature"
-]
diff --git a/third_party/blink/public/common/privacy_budget/DIR_METADATA b/third_party/blink/public/common/privacy_budget/DIR_METADATA
deleted file mode 100644
index 5e0dd183..0000000
--- a/third_party/blink/public/common/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1,2 +0,0 @@
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
-
diff --git a/third_party/blink/public/common/privacy_budget/OWNERS b/third_party/blink/public/common/privacy_budget/OWNERS
deleted file mode 100644
index a21ac823..0000000
--- a/third_party/blink/public/common/privacy_budget/OWNERS
+++ /dev/null
@@ -1,3 +0,0 @@
-antoniosartori@chromium.org
-caraitto@chromium.org
-mkwst@chromium.org
diff --git a/third_party/blink/public/common/privacy_budget/README.md b/third_party/blink/public/common/privacy_budget/README.md
deleted file mode 100644
index 832a955..0000000
--- a/third_party/blink/public/common/privacy_budget/README.md
+++ /dev/null
@@ -1,6 +0,0 @@
-# Privacy Budget: Core Metrics and Aggregation
-
-See [Privacy Budget: Code
-Locations](../../../../../docs/privacy_budget/privacy_budget_code_locations.md) for
-details.
-
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h b/third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h
deleted file mode 100644
index 2b96d05..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_
-
-#include <array>
-#include <concepts>
-#include <cstdint>
-#include <cstring>
-#include <type_traits>
-
-#include "base/containers/span.h"
-#include "base/numerics/byte_conversions.h"
-
-namespace blink {
-
-namespace internal {
-
-// Calculate a digest of an object with a unique representation.
-//
-// In a perfect world, we should also require that this representation be
-// portable or made to be portable. Such a transformation could be done, for
-// example, by adopting a consistent byte ordering on all platforms.
-//
-// This function should only be invoked on a bare (sans qualifiers and
-// references) type for the sake of simplicity.
-//
-// Should not be used as a primitive for manually constructing a unique
-// representation. For such cases, use the byte-wise digest functions instead.
-//
-// Should not be used outside of the narrow use cases in this file.
-//
-// This implementation does not work for x86 extended precision floating point
-// numbers. These are 80-bits wide, but in practice includes 6 bytes of padding
-// in order to extend the size to 16 bytes. The extra bytes are uninitialized
-// and will not contribute a stable digest.
-template <typename T>
-constexpr int64_t DigestOfObjectRepresentation(T in)
-  requires(std::same_as<T, std::remove_cvref_t<T>> &&
-           std::is_trivially_copyable_v<T> &&
-           std::has_unique_object_representations_v<T> &&
-           sizeof(T) <= sizeof(int64_t))
-{
-  if constexpr (std::is_integral<T>::value &&
-                (std::is_signed<T>::value || sizeof(T) < sizeof(int64_t))) {
-    // If |in| is small enough, the digest is itself. There's no point hashing
-    // this value since the identity has all the properties we are looking for
-    // in a digest.
-    return in;
-  } else {
-    // Otherwise we treat the native byte representation as the digest. If the
-    // type is a structure containing non-byte-sized integers, this would
-    // produce a different absolute output on BE and LE machines (though BE
-    // machines are not supported by Chromium).
-    std::array<uint8_t, 8u> bytes = {};
-    base::span(bytes).template first<sizeof(T)>().copy_from(
-        base::byte_span_from_ref(in));
-    return static_cast<int64_t>(base::U64FromNativeEndian(bytes));
-  }
-}
-
-}  // namespace internal
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_INTERNAL_TEMPLATES_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_metrics.h b/third_party/blink/public/common/privacy_budget/identifiability_metrics.h
deleted file mode 100644
index 9da950b..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_metrics.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_METRICS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_METRICS_H_
-
-#include <cstdint>
-#include <cstring>
-#include <type_traits>
-
-#include "base/containers/span.h"
-#include "third_party/blink/public/common/common_export.h"
-
-namespace blink {
-
-// IdentifiabilityDigestOfBytes, which is NOT a cryptographic hash function,
-// takes a span of bytes as input and calculates a digest that can be used with
-// identifiability metric reporting functions.
-//
-// The returned digest ...:
-//
-// * Is Stable: The returned digest will be consistent across different versions
-//   of Chromium. Thus it can be persisted and meaningfully aggregated across
-//   browser versions.
-//
-// * Is approximately uniformly distributed when the input is uniformly
-//   distributed.
-//
-// * Is NOT optimized for any other distribution of input including narrow
-//   integral ranges.
-//
-// * Is NOT collision resistant: Callers should assume that it is easy to come
-//   up with collisions, and to come up with a pre-image given a digest.
-//
-// Note: This is NOT a cryptographic hash function.
-BLINK_COMMON_EXPORT uint64_t
-IdentifiabilityDigestOfBytes(base::span<const uint8_t> in);
-
-// The zero-length digest, i.e. the digest computed for no bytes.
-static constexpr uint64_t kIdentifiabilityDigestOfNoBytes =
-    UINT64_C(0x9ae16a3b2f90404f);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_METRICS_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_sample_test_utils.h b/third_party/blink/public/common/privacy_budget/identifiability_sample_test_utils.h
deleted file mode 100644
index 8802d40..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_sample_test_utils.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_SAMPLE_TEST_UTILS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_SAMPLE_TEST_UTILS_H_
-
-#include "base/component_export.h"
-#include "base/memory/raw_ptr.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-
-namespace blink {
-
-struct CallCounts {
-  bool response_for_is_meta_experiment_active = false;
-  bool response_for_is_active = false;
-  bool response_for_is_anything_blocked = false;
-  bool response_for_is_allowed = false;
-
-  int count_of_is_meta_experiment_active = 0;
-  int count_of_is_active = 0;
-  int count_of_is_any_type_or_surface_blocked = 0;
-  int count_of_is_surface_allowed = 0;
-  int count_of_is_type_allowed = 0;
-};
-
-class COMPONENT_EXPORT(PRIVACY_BUDGET_TEST_SUPPORT)
-    CountingSettingsProvider final
-    : public IdentifiabilityStudySettingsProvider {
- public:
-  explicit CountingSettingsProvider(CallCounts* state) : state_(state) {}
-
-  bool IsMetaExperimentActive() const override;
-
-  bool IsActive() const override;
-
-  bool IsAnyTypeOrSurfaceBlocked() const override;
-
-  bool IsSurfaceAllowed(IdentifiableSurface surface) const override;
-
-  bool IsTypeAllowed(IdentifiableSurface::Type type) const override;
-
- private:
-  raw_ptr<CallCounts> state_ = nullptr;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_SAMPLE_TEST_UTILS_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h b/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
deleted file mode 100644
index 56ab6471..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_study_settings.h
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_H_
-
-#include <memory>
-
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-forward.h"
-
-namespace blink {
-
-// Determines whether the identifiability study is active and if so whether a
-// given surface or surface type should be sampled.
-//
-// This class can used from multiple threads and does not require
-// synchronization.
-//
-// See documentation on individual methods for notes on thread safety.
-//
-// Guidelines for when and how to use it can be found in:
-//
-//     //docs/privacy_budget/privacy_budget_instrumentation.md#gating
-//
-class BLINK_COMMON_EXPORT IdentifiabilityStudySettings {
- public:
-  // Constructs a default IdentifiabilityStudySettings instance. By default the
-  // settings instance acts as if the study is disabled, and implicitly as if
-  // all surfaces and types are blocked.
-  IdentifiabilityStudySettings();
-
-  // Constructs a IdentifiabilityStudySettings instance which reflects the state
-  // specified by |provider|.
-  explicit IdentifiabilityStudySettings(
-      std::unique_ptr<IdentifiabilityStudySettingsProvider> provider);
-
-  ~IdentifiabilityStudySettings();
-
-  // Get a pointer to an instance of IdentifiabilityStudySettings for the
-  // process.
-  //
-  // This method and the returned object is safe to use from any thread and is
-  // never destroyed.
-  //
-  // On the browser process, the returned instance is authoritative. On all
-  // other processes the returned instance should be considered advisory. It's
-  // only meant as an optimization to avoid calculating things unnecessarily.
-  static const IdentifiabilityStudySettings* Get();
-
-  // Initialize the process-wide settings instance with the specified settings
-  // provider. Should only be called once per process and only from the main
-  // thread.
-  //
-  // For testing, you can use ResetStateForTesting().
-  static void SetGlobalProvider(
-      std::unique_ptr<IdentifiabilityStudySettingsProvider> provider);
-
-  // Returns true if the study is active for this client. Once if it returns
-  // true, it doesn't return false at any point after. The converse is not true.
-  // Note that metrics might still need to be sampled (because of tracing) even
-  // if this returns `false`. Use one of the `ShouldSample...` methods below for
-  // deciding whether a surface needs to be sampled.
-  bool IsActive() const;
-
-  // Returns true if |surface| should be sampled.
-  bool ShouldSampleSurface(IdentifiableSurface surface) const;
-
-  // Returns true if |type| should be sampled.
-  bool ShouldSampleType(IdentifiableSurface::Type type) const;
-
-  // Convenience method for determining whether the surface constructable from
-  // the type (|kWebFeature|) and the |feature| is allowed. See
-  // ShouldSampleSurface for more detail.
-  bool ShouldSampleWebFeature(mojom::WebFeature feature) const;
-
-  // Only used for testing. Resets internal state and violates API contracts
-  // made above about the lifetime of IdentifiabilityStudySettings*.
-  static void ResetStateForTesting();
-
-  IdentifiabilityStudySettings(IdentifiabilityStudySettings&&) = delete;
-  IdentifiabilityStudySettings(const IdentifiabilityStudySettings&) = delete;
-  IdentifiabilityStudySettings& operator=(const IdentifiabilityStudySettings&) =
-      delete;
-
- private:
-  // If this returns `false`, then nothing should be sampled.
-  bool ShouldSampleAnything() const;
-
-  const std::unique_ptr<IdentifiabilityStudySettingsProvider> provider_;
-  const bool is_enabled_ = false;
-  const bool is_any_surface_or_type_blocked_ = false;
-  const bool is_meta_experiment_active_ = false;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h b/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
deleted file mode 100644
index 58da1bd..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_study_settings_provider.h
+++ /dev/null
@@ -1,48 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_PROVIDER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_PROVIDER_H_
-
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace blink {
-
-class BLINK_COMMON_EXPORT IdentifiabilityStudySettingsProvider {
- public:
-  virtual ~IdentifiabilityStudySettingsProvider();
-
-  // Returns true if the meta experiment of the identifiability study is active
-  // (meaning that this client is selected for collecting meta surfaces). For
-  // any specific instance of IdentifiabilityStudySettings, this answer cannot
-  // change. It will only be queried once.
-  virtual bool IsMetaExperimentActive() const = 0;
-
-  // Returns true if the identifiability study is active. For any specific
-  // instance of IdentifiabilityStudySettings, this answer cannot change. It
-  // will only be queried once.
-  virtual bool IsActive() const = 0;
-
-  // Returns true if any specific surface or type is blocked. Otherwise it is
-  // assumed that neither IsSurfaceBlocked() nor IsTypeBlocked() will ever
-  // return true for anything.
-  //
-  // Only meaningful if IsActive() returns true.
-  virtual bool IsAnyTypeOrSurfaceBlocked() const = 0;
-
-  // Returns true if the given surface should be sampled.
-  //
-  // If IsActive() is false, this method will not be called.
-  virtual bool IsSurfaceAllowed(IdentifiableSurface surface) const = 0;
-
-  // Returns true if the given surface type should be sampled.
-  //
-  // If IsActive() is false, this method will not be called.
-  virtual bool IsTypeAllowed(IdentifiableSurface::Type type) const = 0;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_SETTINGS_PROVIDER_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiability_study_worker_client_added.h b/third_party/blink/public/common/privacy_budget/identifiability_study_worker_client_added.h
deleted file mode 100644
index 0348b6e..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiability_study_worker_client_added.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright 2022 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_WORKER_CLIENT_ADDED_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_WORKER_CLIENT_ADDED_H_
-
-#include "services/metrics/public/cpp/ukm_recorder.h"
-#include "services/metrics/public/cpp/ukm_source_id.h"
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-
-namespace blink {
-
-class BLINK_COMMON_EXPORT IdentifiabilityStudyWorkerClientAdded {
- public:
-  // Constructs an IdentifiabilityStudyWorkerClientAdded for the given SourceId.
-  explicit IdentifiabilityStudyWorkerClientAdded(ukm::SourceId source_id);
-
-  ~IdentifiabilityStudyWorkerClientAdded();
-
-  // Record collected metrics to `recorder`.
-  void Record(ukm::UkmRecorder* recorder);
-
-  IdentifiabilityStudyWorkerClientAdded& SetClientSourceId(
-      ukm::SourceId client_source_id);
-
-  IdentifiabilityStudyWorkerClientAdded& SetWorkerType(
-      blink::IdentifiableSurface::WorkerType worker_type);
-
- private:
-  const ukm::SourceId source_id_;
-  ukm::SourceId client_source_id_;
-  blink::IdentifiableSurface::WorkerType worker_type_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABILITY_STUDY_WORKER_CLIENT_ADDED_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_sample.h b/third_party/blink/public/common/privacy_budget/identifiable_sample.h
deleted file mode 100644
index f4d1f52..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiable_sample.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SAMPLE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SAMPLE_H_
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_surface.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-namespace blink {
-
-// Represents a single identifiable sample. It's basically an immutable
-// ⟨surface, value⟩tuple defined as a struct because it's useful in many
-// places.
-struct IdentifiableSample {
-  IdentifiableSample(IdentifiableSurface surface_param,
-                     IdentifiableToken value_param)
-      : surface(surface_param), value(value_param) {}
-
-  const IdentifiableSurface surface;
-  const IdentifiableToken value;
-
-  bool operator==(const IdentifiableSample& other) const {
-    return surface == other.surface && value == other.value;
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SAMPLE_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_surface.h b/third_party/blink/public/common/privacy_budget/identifiable_surface.h
deleted file mode 100644
index 822626c..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiable_surface.h
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <compare>
-#include <cstddef>
-#include <functional>
-#include <tuple>
-
-#include "services/metrics/public/cpp/ukm_builders.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-namespace blink {
-
-// An identifiable surface.
-//
-// See also: ../../../../../docs/privacy_budget/good_identifiable_surface.md
-//
-// This class intends to be a lightweight wrapper over a simple 64-bit integer.
-// It exhibits the following characteristics:
-//
-//   * All methods are constexpr.
-//   * Immutable.
-//   * Efficient enough to pass by value.
-//
-// Internally, an identifiable surface is represented as a 64-bit unsigned
-// integer that can be used as the metric hash for reporting metrics via UKM.
-//
-// The least-significant |kTypeBits| of the value is used to store
-// a IdentifiableSurface::Type value. The remainder stores the 56
-// least-significant bits of an `IdentifiableToken` as illustrated below:
-//              ✂
-//    ┌─────────┊────────────────────────────────────────┐ ┌──────────┐
-//    │(discard)✂           IdentifiableToken            │ │   Type   │
-//    └─────────┊───────────────────┬────────────────────┘ └────┬─────┘
-// Bit 64       ┊55                 ┊                   0   7   ┊    0
-//              ✂                   ↓                           ↓
-//              ┌────────────────────────────────────────┬──────────┐
-//              │                                        │          │
-//              └────────────────────────────────────────┴──────────┘
-//           Bit 64                                     8 7        0
-//              │←────────────── IdentifiableSurface ──────────────→│
-//
-// Only the lower 56 bits of `IdentifiableToken` contribute to an
-// `IdentifiableSurface`.
-//
-// See descriptions for the `Type` enum values for details on how the
-// `IdentifiableToken` is generated for each type. The descriptions use the
-// following notation to indicate how the value is recorded:
-//
-//     IdentifiableSurface = { IdentifiableToken value, Type value }
-//     Value = [description of how the value is constructed]
-class IdentifiableSurface {
- public:
-  // Number of bits used by Type.
-  static constexpr int kTypeBits = 8;
-
-  // Bitmask for extracting Type value from a surface hash.
-  static constexpr uint64_t kTypeMask = (1 << kTypeBits) - 1;
-
-  // Indicator for an uninitialized IdentifiableSurface. Maps to
-  // {Type::kReservedInternal, 0} which is not possible for a valid surface.
-  static constexpr uint64_t kInvalidHash = 0;
-
-  // Type of identifiable surface.
-  //
-  // Even though the data type is uint64_t, we can only use 8 bits due to how we
-  // pack the surface type and a digest of the input into a 64 bits.
-  //
-  // These values are used for aggregation across versions. Entries should not
-  // be renumbered and numeric values should never be reused.
-  enum class Type : uint64_t {
-    // This type is reserved for internal use and should not be used for
-    // reporting any identifiability metrics.
-    //
-    // All metrics defined under the Identifiability event in
-    // tools/metrics/ukm.xml fall into this type. Hence using
-    // `ukm::builders::Identifiability` results in metrics with this type.
-    kReservedInternal = 0,
-
-    // Represents a web feature whose output directly contributes to
-    // identifiability.
-    //
-    // These APIs are annotated with the `[HighEntropy=Direct]` extended WebIDL
-    // attribute in their respective IDL file. Each such API also has an
-    // associated `UseCounter` value specified directly via the
-    // `[MeasureAs=??]` attribute or indirectly via the `[Measure]` attribute.
-    // This `UseCounter` value is the key for recording the output of the API.
-    // `web_feature.mojom`[1] defines all the `UseCounter` values and is
-    // available as mojom::WebFeature.
-    //
-    //     IdentifiableSurface = { mojom::WebFeature, kWebFeature }
-    //     Value = IdentifiableToken( $(output of the attribute or method) )
-    //
-    // [1]: //blink/public/mojom/use_counter/metrics/web_feature.mojom
-    kWebFeature = 1,
-
-    // Reserved 2.
-
-    // Reserved 3.
-    // Was kLocalFontLookupByUniqueOrFamilyName.
-
-    // Reserved 4.
-    // Was kGenericFontLookup.
-
-    // Reserved 5.
-    // Was kExtensionFileAccess.
-
-    // Reserved 6.
-    // Was kExtensionContentScript.
-
-    // Represents making a measurement of one of the above surfacess. This
-    // metric is retained even if filtering discards the surface.
-    kMeasuredSurface = 7,
-
-    // WebGL parameter for WebGLRenderingContext.getParameter().
-    kWebGLParameter = 8,
-
-    // Represents a call to |MediaRecorder.isTypeSupported(mimeType)|. Input is
-    // the mime type supplied to the method.
-    kMediaRecorder_IsTypeSupported = 9,
-
-    // Represents a call to |MediaSource.isTypeSupported(mimeType)|. Input is
-    // the mime type supplied to the method.
-    kMediaSource_IsTypeSupported = 10,
-
-    // Represents a call to |HTMLMediaElement.canPlayType(mimeType)|. Input is
-    // the mime type supplied to the method.
-    kHTMLMediaElement_CanPlayType = 11,
-
-    // Reserved 12.
-    // Was kLocalFontLookupByUniqueNameOnly.
-
-    // Reserved 13.
-    // Was kLocalFontLookupByFallbackCharacter.
-
-    // Reserved 14.
-    // Was kLocalFontLookupAsLastResort.
-
-    // Reserved 15.
-    // Was kExtensionCancelRequest.
-
-    // WebGLRenderingContext.getShaderPrecisionFormat() is a high entropy API
-    // that leaks entropy about the underlying GL implementation.
-    // The output is keyed on two enums, but for the identifiability study we
-    // will key this type on a digest of both the enums' values.
-    kWebGLShaderPrecisionFormat = 16,
-
-    // Reserved 17.
-    // Was kScrollbarSize.
-
-    // WebGL2RenderingContext.getInternal
-    kWebGLInternalFormatParameter = 18,
-
-    // Represents a call to GPU.requestAdapter. Input is the options filter.
-    kGPU_RequestAdapter = 20,
-
-    // For instrumenting HTMLCanvas.getContext() fingerprinting. Some scripts
-    // will iterate through the different possible arguments and record whether
-    // each type of context is supported.
-    // The input should be an instance of CanvasRenderingContext::ContextType.
-    kCanvasRenderingContext = 21,
-
-    // Represents a call to MediaDevices.getUserMedia. Input is the set of
-    // constraints.
-    kMediaDevices_GetUserMedia = 22,
-
-    // NavigatorUAData.getHighEntropyValues() is, shockingly, a high entropy
-    // API to provide more detailed User-Agent data. The output is keyed on
-    // the hint parameter.
-    kNavigatorUAData_GetHighEntropyValues = 24,
-
-    // MediaCapabilities.decodingInfo() reveals information about whether
-    // media decoding will be supported, smooth and/or power efficient,
-    // according to its codec, size, and other parameters. It can further reveal
-    // details about encrypted decoding support according to the key system
-    // configuration provided.
-    kMediaCapabilities_DecodingInfo = 25,
-
-    // Reserved 26.
-    // Was kLocalFontExistenceByUniqueNameOnly.
-
-    // Represents a call to Navigator.getUserMedia. Input is the set of
-    // constraints.
-    kNavigator_GetUserMedia = 27,
-
-    // Represents a media query being tested. Input is combination of property
-    // name and the target value. Output is the result --- true or false.
-    kMediaQuery_DEPRECATED = 28,
-
-    // Reserved 29.
-    // Was kLocalFontLoadPostScriptName.
-
-    // Getting supported codecs, etc. for WebRTC sender -- key is hash of kind
-    // (audio or video).
-    kRtcRtpSenderGetCapabilities = 31,
-
-    // Getting supported codecs, etc. for WebRTC receiver -- key is hash of kind
-    // (audio or video).
-    kRtcRtpReceiverGetCapabilities = 32,
-
-    // Reserved 33.
-
-    // Metadata that is not reported by the client. Different from
-    // kReservedInternal in that the inputs are not required to be defined in
-    // `ukm.xml`.
-    //
-    // This surface type should not be used in the client (browser). It's meant
-    // to be a reservation for additional surfaces that are determined during
-    // analysis.
-    kReservedMetadata = 34,
-
-    // Reserved 35 (was kCanvasReadback).
-
-    // Represents a media feature being tested. Input is the feature name.
-    // Output is the feature value
-    kMediaFeature = 36,
-
-    // Type for synthetic surfaces used for reporting data with the goal of
-    // estimating the Reid score of set of surfaces. This type does not
-    // correspond to any Web APIs specifically.
-    kReidScoreEstimator = 37,
-
-    // Reserved 38.
-    // Was kFontFamilyAvailable.
-
-    // Represents determining that a local font exists or does not, based on a
-    // name lookup that is allowed to match either a unique name or a family
-    // name. This occurs when a font-family CSS rule doesn't match any
-    // @font-face rule. Input is the lookup name. Output is a bool.
-    kLocalFontExistenceByUniqueOrFamilyName = 39,
-
-    // Represents a readback of a canvas. Input is the
-    // CanvasRenderingContextType.
-    //
-    // Was 2 before change to paint op serialization, then 33 before removing
-    // paint op serialization and using only direct canvas2d instrumentation,
-    // then 35 before changing color hashing functions in
-    // BaseRenderingContext2D.
-    kCanvasReadback = 40,
-
-    // We can use values up to and including |kMax|.
-    kMax = (1 << kTypeBits) - 1
-  };
-
-  // These are metrics names of type 0 and are always reported when the study is
-  // enabled.
-  enum class ReservedSurfaceMetrics : uint64_t {
-    kDocumentCreated_IsCrossOriginFrame = 0,
-    kDocumentCreated_IsCrossSiteFrame = 1,
-    kDocumentCreated_IsMainFrame = 2,
-    kDocumentCreated_NavigationSourceId = 3,
-    kWorkerClientAdded_ClientSourceId = 4,
-    kWorkerClientAdded_WorkerType = 5,
-    kMaxValue = kWorkerClientAdded_WorkerType
-  };
-
-  enum class WorkerType : uint64_t {
-    kSharedWorker = 0,
-    kServiceWorker = 1,
-    kMaxValue = kServiceWorker,
-  };
-
-  // HTML canvas readback -- bits [0-3] of the 64-bit input are the context type
-  // (Type::kCanvasReadback), bits [4-6] are skipped ops, sensitive ops, and
-  // partial image ops bits, respectively. The remaining bits are for the canvas
-  // operations digest. If the digest wasn't calculated (there's no digest for
-  // WebGL, for instance), the digest field is 0.
-  enum CanvasTaintBit : uint64_t {
-    // At least one drawing operation didn't update the digest -- this is either
-    // due to performance or resource consumption reasons.
-    kSkipped = UINT64_C(0x10),
-
-    // At least one drawing operation operated on a sensitive string. Sensitive
-    // strings use a 16-bit hash digest.
-    kSensitive = UINT64_C(0x20),
-
-    // At least one drawing operation was only partially digested, for
-    // performance reasons.
-    kPartiallyDigested = UINT64_C(0x40)
-  };
-
-  // Possible inputs for Type::kMediaFeature.
-  enum class MediaFeatureName : uint64_t {
-    kAnyHover = 0,
-    kAnyPointer = 1,
-    kColorGamut = 2,
-    kForcedColors = 3,
-    kGrid = 4,
-    kHover = 5,
-    kOrientation = 6,
-    kDynamicRange = 7,
-    kDisplayMode = 8,
-    kNavigationControls = 9,
-    kPointer = 10,
-    kPrefersColorScheme = 11,
-    kPrefersContrast = 12,
-    kPrefersReducedMotion = 13,
-    kPrefersReducedData = 14,
-    kTransform3d = 15,
-    kScan = 16,
-    kDevicePosture = 17,
-    kColor = 18,
-    kColorIndex = 19,
-    kMonochrome = 20,
-    kAspectRatio_DEPRECATED = 21,
-    kResolution = 22,
-    kHorizontalViewportSegments = 23,
-    kVerticalViewportSegments = 24,
-    kAspectRatioNormalized = 25,
-    kPrefersReducedTransparency = 26,
-    kInvertedColors = 27,
-    kScripting = 28,
-    kDisplayState = 29,
-    kResizable = 30,
-    // We can use enum values up to and including 63, see static_assert below.
-    kMaxValue = kResizable
-  };
-  static_assert(static_cast<int>(MediaFeatureName::kMaxValue) < 64,
-                "MediaFeatureName only allows values < 64 since we use it in "
-                "a uint64_t bitfield inside document.h to track if a media "
-                "feature has already been sampled");
-
-  // Default constructor is invalid.
-  IdentifiableSurface() : IdentifiableSurface(kInvalidHash) {}
-
-  // Construct an IdentifiableSurface based on a precalculated metric hash. Can
-  // also be used as the first step in decoding an encoded metric hash.
-  static constexpr IdentifiableSurface FromMetricHash(uint64_t metric_hash) {
-    return IdentifiableSurface(metric_hash);
-  }
-
-  // Construct an IdentifiableSurface based on a surface type and an input
-  // token.
-  static constexpr IdentifiableSurface FromTypeAndToken(
-      Type type,
-      IdentifiableToken token) {
-    return IdentifiableSurface(KeyFromSurfaceTypeAndInput(type, token.value_));
-  }
-
-  // Construct an invalid identifiable surface.
-  static constexpr IdentifiableSurface Invalid() {
-    return IdentifiableSurface(kInvalidHash);
-  }
-
-  // Returns the UKM metric hash corresponding to this IdentifiableSurface.
-  constexpr uint64_t ToUkmMetricHash() const { return metric_hash_; }
-
-  // Returns the type of this IdentifiableSurface.
-  constexpr Type GetType() const {
-    return std::get<0>(SurfaceTypeAndInputFromMetricKey(metric_hash_));
-  }
-
-  // Returns the input hash for this IdentifiableSurface.
-  //
-  // The value that's returned can be different from what's used for
-  // constructing the IdentifiableSurface via FromTypeAndToken() if the input is
-  // >= 2^56.
-  constexpr uint64_t GetInputHash() const {
-    return std::get<1>(SurfaceTypeAndInputFromMetricKey(metric_hash_));
-  }
-
-  constexpr bool IsValid() const { return metric_hash_ != kInvalidHash; }
-
-  friend constexpr auto operator<=>(const IdentifiableSurface& lhs,
-                                    const IdentifiableSurface& rhs) = default;
-  friend constexpr bool operator==(const IdentifiableSurface& lhs,
-                                   const IdentifiableSurface& rhs) = default;
-
- private:
-  constexpr explicit IdentifiableSurface(uint64_t metric_hash)
-      : metric_hash_(metric_hash) {}
-
-  // Returns a 64-bit metric key given an IdentifiableSurfaceType and a 64 bit
-  // input digest.
-  //
-  // The returned key can be used as the metric hash when invoking
-  // UkmEntryBuilderBase::SetMetricInternal().
-  static constexpr uint64_t KeyFromSurfaceTypeAndInput(Type type,
-                                                       uint64_t input) {
-    uint64_t type_as_int = static_cast<uint64_t>(type);
-    return type_as_int | (input << kTypeBits);
-  }
-
-  // Returns the IdentifiableSurfaceType and the input hash given a metric key.
-  //
-  // This is approximately the inverse of MetricKeyFromSurfaceTypeAndInput().
-  // See caveat in GetInputHash() about cases where the input hash can differ
-  // from that used to construct this IdentifiableSurface.
-  static constexpr std::tuple<Type, uint64_t> SurfaceTypeAndInputFromMetricKey(
-      uint64_t metric) {
-    return std::make_tuple(static_cast<Type>(metric & kTypeMask),
-                           metric >> kTypeBits);
-  }
-
-  uint64_t metric_hash_;
-};
-
-// Hash function compatible with std::hash.
-struct IdentifiableSurfaceHash {
-  size_t operator()(const IdentifiableSurface& s) const {
-    return std::hash<uint64_t>{}(s.ToUkmMetricHash());
-  }
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_SURFACE_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_token.h b/third_party/blink/public/common/privacy_budget/identifiable_token.h
deleted file mode 100644
index 087b86d..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiable_token.h
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_
-
-#include <stdint.h>
-
-#include <concepts>
-#include <string_view>
-#include <type_traits>
-
-#include "base/bit_cast.h"
-#include "base/containers/span.h"
-#include "base/numerics/safe_conversions.h"
-#include "base/types/cxx23_to_underlying.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h"
-
-namespace blink {
-
-// Constructs a token that can be used for reporting a metric or constructing an
-// identifiable surface.
-//
-// The token construction is a single step conversion that takes one of several
-// constrained inputs and emits a value. The method by which the value is
-// constructed intentionally cannot be chained. If such behavior is required,
-// then this class should be modified to accommodate the new use case rather
-// than implementing custom chaining schemes at call sites.
-//
-// Once constructed, a token can only be consumed by
-// IdentifiabiltyMetricsBuilder and IdentifiableSurface. For all others, it is a
-// copyable, opaque token.
-//
-// Reliance on implicit conversion imposes limitations on how
-// IdentifiableToken class is to be used. For example the following works:
-//
-//     std::string foo = ....;
-//     IdentifiableToken sample(foo);
-//
-// .. due to the following implicit conversion:
-//
-//    1. std::string -> const std::string&
-//             : lvalue -> lvalue reference + cv-qualification
-//    2. const std::string& -> std::string_view
-//             : user-defined conversion via constructor
-//               std::string_view(const std::string&)
-//
-// However, when used within a builder expression, the user-defined conversion
-// doesn't occur due to there not being a single user defined conversion from
-// std::string -> IdentifiableToken. I.e. the following does not work:
-//
-//     std::string foo = ....;
-//     IdentifiabilityMetricBuilder(...).Set(surface, foo);
-//                                                    ^^^
-//      The compiler can't deduce a two step user-defined conversion for |foo|.
-//
-// All overrides of the constructor should ensure that there exists a unique
-// representation of the data type being sampled, and that the sample value is
-// constructed based on this unique representation.
-//
-// TODO(asanka): Also require that the representation be portable.
-//
-// Extending IdentifiableToken to support more data types:
-// -----------------------------------------------------------
-//
-// This class is intentionally placed in blink/public/common due to the
-// requirement that these primitives be made available to both the renderer and
-// the browser. However, it would be desirable to have renderer or browser
-// specific functions for mapping common types in either domain into a sample.
-//
-// The recommended methods to do so are (one-of):
-//
-//   1. Use an existing byte span representation.
-//
-//      E.g.: Assuming |v| is a blink::Vector
-//          IdentifiabilityMetricBuilder(...).Set(
-//              ..., base::as_byte_span(v.Data(), v.Size()));
-//
-//      Note again that serializing to a stream of bytes may not be sufficient
-//      if the underlying types don't have a unique representation.
-//
-//   2. Construct a byte-wise unique representation and invoke
-//      IdentifiableToken(ByteSpan) either explicitly or implicitly via
-//      user-defined conversions.
-//
-// Note: Avoid doing template magic. There's already too much here. Templates
-//       make it difficult to verify that the correct stable representation is
-//       the one getting ingested into the reporting workflow.
-//
-//       Instead, explicitly invoke some wrapper that emits a ByteSpan (a.k.a.
-//       base::span<const uint8_t>.
-class IdentifiableToken {
- public:
-  // Generic buffer of bytes.
-  using ByteSpan = base::span<const uint8_t>;
-
-  // Representation type of the sample.
-  using TokenType = int64_t;
-
-  // Required for use in certain data structures. Represents no bytes.
-  constexpr IdentifiableToken() : value_(kIdentifiabilityDigestOfNoBytes) {}
-
-  // A byte buffer specified as a span.
-  //
-  // This is essentially the base case. If it were the base case, then
-  // IdentifiableToken would be closer to a proper digest.
-  //
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  IdentifiableToken(ByteSpan span)
-      : value_(IdentifiabilityDigestOfBytes(span)) {}
-
-  // Integers, big and small. Includes char.
-  template <typename T,
-            typename U = std::remove_cvref_t<T>>
-    requires std::integral<U>
-  constexpr IdentifiableToken(T in)  // NOLINT(google-explicit-constructor)
-      : value_(base::IsValueInRangeForNumericType<TokenType, U>(in)
-                   ? in
-                   : internal::DigestOfObjectRepresentation<U>(in)) {}
-
-  // Enums. Punt to the underlying type.
-  template <typename T>
-    requires std::is_enum_v<std::remove_cvref_t<T>>
-  constexpr IdentifiableToken(T in)  // NOLINT(google-explicit-constructor)
-      : IdentifiableToken(base::to_underlying(in)) {}
-
-  // All floating point values get converted to double before encoding.
-  //
-  // Why? We'd like to minimize accidental divergence of values due to the data
-  // type that the callsite happened to be using at the time.
-  //
-  // On some platforms sizeof(long double) gives us 16 (i.e. 128 bits), while
-  // only 10 of those bytes are initialized. If the whole sizeof(long double)
-  // buffer were to be ingested, then the uninitialized memory will cause the
-  // resulting digest to be useless.
-  //
-  // Furthermore, `DigestOfObjectRepresentation()` requires
-  // `std::has_unique_object_representations_v<>`, which doesn't hold for
-  // floating-point values. Work around by reinterpreting as an integral type of
-  // the same size, without changing the underlying bit pattern.
-  static_assert(sizeof(double) == sizeof(int64_t));
-  template <typename T>
-    requires std::floating_point<std::remove_cvref_t<T>>
-  constexpr IdentifiableToken(T in)  // NOLINT(google-explicit-constructor)
-      : value_(internal::DigestOfObjectRepresentation(
-            base::bit_cast<int64_t>(static_cast<double>(in)))) {}
-
-  // StringPiece. Decays to base::span<> but requires an explicit constructor
-  // invocation.
-  //
-  // Care must be taken when using string types with IdentifiableToken() since
-  // there's not privacy expectation in the resulting token value. If the string
-  // used as an input is privacy sensitive, it should not be passed in as-is.
-  explicit IdentifiableToken(std::string_view s)
-      : IdentifiableToken(base::as_byte_span(s)) {
-    // The cart is before the horse, but it's a static_assert<>.
-    static_assert(
-        std::is_same<ByteSpan, decltype(base::as_byte_span(s))>::value,
-        "base::as_bytes() doesn't return ByteSpan");
-  }
-
-  // Span of known trivial types except for BytesSpan, which is the base case.
-  template <typename T, size_t Extent>
-    requires(!std::same_as<ByteSpan::element_type, T> &&
-             std::has_unique_object_representations_v<std::remove_cvref_t<T>>)
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  IdentifiableToken(base::span<T, Extent> span)
-      : IdentifiableToken(base::as_bytes(span)) {}
-
-  // A span of non-trivial things where each thing can be digested individually.
-  template <typename T, size_t Extent>
-    requires(!std::same_as<ByteSpan::element_type, T> &&
-             !std::has_unique_object_representations_v<std::remove_cvref_t<T>>)
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  IdentifiableToken(base::span<T, Extent> span) {
-    TokenType cur_digest = 0;
-    for (const auto& element : span) {
-      TokenType digests[2];
-      digests[0] = cur_digest;
-      digests[1] = IdentifiableToken(element).value_;
-      cur_digest = IdentifiabilityDigestOfBytes(base::as_byte_span(digests));
-    }
-    value_ = cur_digest;
-  }
-
-  // Parameter pack where each parameter can be digested individually. Requires
-  // at least two parameters.
-  template <typename T1, typename T2, typename... Trest>
-  constexpr IdentifiableToken(T1 first, T2 second, Trest... rest) {
-    TokenType samples[] = {IdentifiableToken(first).value_,
-                           IdentifiableToken(second).value_,
-                           (IdentifiableToken(rest).value_)...};
-    value_ = IdentifiableToken(base::span(samples)).value_;
-  }
-
-  constexpr bool operator<(const IdentifiableToken& that) const {
-    return value_ < that.value_;
-  }
-
-  constexpr bool operator<=(const IdentifiableToken& that) const {
-    return value_ <= that.value_;
-  }
-
-  constexpr bool operator>(const IdentifiableToken& that) const {
-    return value_ > that.value_;
-  }
-
-  constexpr bool operator>=(const IdentifiableToken& that) const {
-    return value_ >= that.value_;
-  }
-
-  constexpr bool operator==(const IdentifiableToken& that) const {
-    return value_ == that.value_;
-  }
-
-  // Returns a value that can be passed into the UKM metrics recording
-  // interfaces.
-  int64_t ToUkmMetricValue() const { return value_; }
-
- private:
-  friend class IdentifiabilityMetricBuilder;
-  friend class IdentifiableSurface;
-  friend class IdentifiableTokenBuilder;
-
-  // TODO(asanka): This should be const. Switch over once the incremental digest
-  // functions land.
-  TokenType value_ = 0;
-};
-
-}  // namespace blink
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_H_
diff --git a/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h b/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h
deleted file mode 100644
index 738a101a..0000000
--- a/third_party/blink/public/common/privacy_budget/identifiable_token_builder.h
+++ /dev/null
@@ -1,205 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_BUILDER_H_
-#define THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_BUILDER_H_
-
-#include <array>
-#include <concepts>
-#include <string_view>
-#include <type_traits>
-
-#include "base/containers/span.h"
-#include "third_party/blink/public/common/common_export.h"
-#include "third_party/blink/public/common/privacy_budget/identifiability_internal_templates.h"
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-
-namespace blink {
-
-// Builds an IdentifiableToken incrementally.
-//
-// Use this when the input to a sample is a bunch of disjoint objects, or the
-// sample needs to include objects that are incrementally encountered.
-//
-// Notes:
-//   * The digest returned by this class is *NOT* the same as the one
-//     IdentifiabilityDigestOfBytes for the same set of bytes. This is due to
-//     block based chaining of digests used by this class.
-//     IdentifiabilityDigestOfBytes and this class are *NOT* interchangeable.
-//
-//     TODO(asanka): IdentifiabilityDigestOfBytes() and this class should
-//     interop better. Perhaps by making the latter use the former.
-//
-//   * The digest returned by this class is *NOT* the same as what you would
-//     acquire by invoking IdentifiableToken() over the same object.
-//     IdentifiableToken() and this class are *NOT* interchangeable.
-//
-//   * The digest returned by this class only depends on the cumulative sequence
-//     of bytes that are fed to it. The partitioning thereof is irrelevant.
-//
-//   * This object never finalizes. Partial digests can be extracted at any
-//     point.
-class BLINK_COMMON_EXPORT IdentifiableTokenBuilder {
- public:
-  // Convenient alias for a span of const uint8_t.
-  using ByteSpan = IdentifiableToken::ByteSpan;
-
-  // Initializes an "empty" incremental digest for the purpose of constructing
-  // an identifiability sample.
-  IdentifiableTokenBuilder();
-
-  // Initializes an incremental digest and populates it with the data contained
-  // in |message|.
-  explicit IdentifiableTokenBuilder(ByteSpan message);
-
-  // Copies the intermediate state.
-  IdentifiableTokenBuilder(const IdentifiableTokenBuilder&);
-
-  // Feeds data contained in |buffer| to the digest.
-  IdentifiableTokenBuilder& AddBytes(ByteSpan buffer);
-
-  // Feeds data contained in |buffer| to the digest, but precedes the buffer
-  // contents with an integer indicating the length. Use this when:
-  //
-  //   * |buffer| is atomic. I.e. it will always be added as a single buffer.
-  //
-  //   * The boundary between |buffer| and adjacent objects cannot be uniquely
-  //     established based on content.
-  //
-  // E.g.: Ignoring NUL terminators, the pair of strings "abcd", "efgh" will be
-  //       assigned token as the strings "abcdefg", "h" if both are added
-  //       individually via AddBytes(). But they will have distinct digests if
-  //       added via AddAtomic().
-  //
-  // If the contents of the object cannot be specified in a contiguous span of
-  // memory, then consider adding a length directly via AddValue() prior to
-  // adding the contents of the buffer. Doing so will achieve the same ends as
-  // AddAtomic().
-  IdentifiableTokenBuilder& AddAtomic(ByteSpan buffer);
-  IdentifiableTokenBuilder& AddAtomic(std::string_view string) {
-    return AddAtomic(base::as_byte_span(string));
-  }
-
-  // Feeds the underlying value of the |token| itself to the digest. Use this
-  // when |token| is computed in parallel in order to preserve the ordering of
-  // values that were seen in a concurrent sequence that cannot be
-  // deterministically interleaved into the primary stream.
-  IdentifiableTokenBuilder& AddToken(IdentifiableToken token) {
-    return AddValue(token.value_);
-  }
-
-  // Helper for feeding primitive types by value efficiently. Anything more
-  // complicated than that should be passed in as a base::span<const uint8_t>.
-  //
-  // Adds eight bytes to the digest. If the type of the value doesn't consume
-  // all of the bytes, pads the remainder with NUL bytes.
-  template <typename T>
-    requires(std::same_as<T, std::remove_cvref_t<T>> &&
-             std::has_unique_object_representations_v<T> &&
-             sizeof(T) <= sizeof(uint64_t))
-  IdentifiableTokenBuilder& AddValue(T in) {
-    AlignPartialBuffer();
-    int64_t clean_buffer = internal::DigestOfObjectRepresentation(in);
-    return AddBytes(base::byte_span_from_ref(clean_buffer));
-  }
-
-  // Conversion operator captures an intermediate digest.
-  //
-  // The sample captures all the data that's been fed into the digest so far,
-  // but doesn't finalize the digest. It is valid to continue adding data after
-  // constructing an intermediate sample.
-  //
-  // (google-explicit-constructor also flags user-defined conversion operators.)
-  // NOLINTNEXTLINE(google-explicit-constructor)
-  operator IdentifiableToken() const;
-
-  // Captures an intermediate digest.
-  //
-  // The sample captures all the data that's been fed into the digest so far,
-  // but doesn't finalize the digest. It is valid to continue adding data after
-  // constructing an intermediate sample.
-  IdentifiableToken GetToken() const;
-
-  // No comparisons.
-  bool operator==(const IdentifiableTokenBuilder&) const = delete;
-  bool operator<(const IdentifiableTokenBuilder&) const = delete;
-
-  // A big random prime. It's also the digest returned for an empty block.
-  static constexpr uint64_t kChainingValueSeed = UINT64_C(6544625333304541877);
-
- private:
-  // Block size. Must be a multiple of 64. Higher block sizes consume more
-  // memory. The extra cost is unlikely to be worth it.
-  //
-  // Under the covers we use CityHash64. It can pretty efficiently digest
-  // 64-byte blocks.
-  static constexpr size_t kBlockSizeInBytes = 64;
-
-  // Target alignment for new buffers. This is set to 8 for all platforms and
-  // must always stay constant across platforms.
-  static constexpr size_t kBlockAlignment = 8;
-
-  // An array of exactly |kBlockSizeInBytes| bytes.
-  using BlockBuffer = std::array<uint8_t, kBlockSizeInBytes>;
-
-  // A view of a full block.
-  using ConstFullBlockSpan = base::span<const uint8_t, kBlockSizeInBytes>;
-
-  // Returns true if the partial buffer is aligned on |kBlockAlignment|
-  // boundary.
-  bool IsAligned() const;
-
-  // Appends enough NUL bytes to |partial_| until the next insertion point is
-  // aligned on a |kBlockAlignment| boundary.
-  //
-  // If the partial buffer is non-empty, its size is unlikely to be aligned at
-  // machine word boundary. This makes subsequent append operations slow for
-  // data types that are already aligned.
-  //
-  // This should only be called prior to adding an atomic buffer.
-  void AlignPartialBuffer();
-
-  // Captures the |kBlockSizeInBytes| bytes of data in |block| into the digest.
-  // |block| must be exactly this many bytes.
-  void DigestBlock(ConstFullBlockSpan block);
-
-  // Captures as many bytes as possible from |message| into the partial block in
-  // |partial_|. It captures a maximum of |kBlockSizeInBytes - 1| bytes.
-  //
-  // Returns a span covering the remainder of |message| that was not consumed.
-  ByteSpan SkimIntoPartial(ByteSpan message);
-
-  // Returns a span for the contents of the partial block.
-  //
-  // Can be called at any point. Does not change the state of the partial
-  // buffer.
-  ByteSpan GetPartialBlock() const;
-
-  // Returns a span that includes the contents of the partial block and backed
-  // by |partial_|.
-  //
-  // NOTE: Should only be called once |kBlockSizeInBytes| bytes have been
-  // accumulated. Resets |partial_size_| upon completion.
-  //
-  // NOTE: Any subsequent AddBytes(), AddValue(), AddAtomic() calls will
-  // invalidate the returned FullBlock.
-  ConstFullBlockSpan TakeCompletedBlock();
-
-  // Size of partially filled buffer.
-  size_t PartialSize() const;
-
-  // Accumulates smaller pieces of data until we have a full block.
-  alignas(int64_t) BlockBuffer partial_;
-
-  // Next available position in `partial_`. std::array iterators are never
-  // invalidated.
-  BlockBuffer::iterator position_ = partial_.begin();
-
-  // Merkle-Damgård chaining.
-  uint64_t chaining_value_;
-};
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_PRIVACY_BUDGET_IDENTIFIABLE_TOKEN_BUILDER_H_
diff --git a/third_party/blink/public/platform/web_image_generator.h b/third_party/blink/public/platform/web_image_generator.h
index 8b19afe..0729dc5 100644
--- a/third_party/blink/public/platform/web_image_generator.h
+++ b/third_party/blink/public/platform/web_image_generator.h
@@ -44,7 +44,7 @@
 class BLINK_PLATFORM_EXPORT WebImageGenerator {
  public:
   static std::unique_ptr<SkImageGenerator> CreateAsSkImageGenerator(
-      sk_sp<SkData>);
+      sk_sp<const SkData>);
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/BUILD.gn b/third_party/blink/renderer/core/BUILD.gn
index 0813930..c98d2bc 100644
--- a/third_party/blink/renderer/core/BUILD.gn
+++ b/third_party/blink/renderer/core/BUILD.gn
@@ -1563,10 +1563,8 @@
     "//skia:skcms",
     "//testing/gmock",
     "//testing/gtest",
-    "//third_party/blink/common/privacy_budget:test_support",
     "//third_party/blink/public:buildflags",
     "//third_party/blink/public:test_headers",
-    "//third_party/blink/public/common/privacy_budget:test_support",
     "//third_party/blink/public/strings:permission_element_generated_strings_grit",
     "//third_party/blink/public/strings:permission_element_strings_grit",
     "//third_party/blink/renderer/controller:blink_bindings_test_sources",
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index 5557d64..51e309d 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -8707,11 +8707,6 @@
   popover_pointerdown_target_ = popover;
 }
 
-void Document::SetPopoverPickerMousedownLocation(
-    std::optional<gfx::PointF> point) {
-  popover_picker_mousedown_location_ = point;
-}
-
 const HTMLDialogElement* Document::DialogPointerdownTarget() const {
   return dialog_pointerdown_target_.Get();
 }
@@ -8721,6 +8716,14 @@
   dialog_pointerdown_target_ = dialog;
 }
 
+HTMLDocument::PopoverPickerPointerdownInfo Document::PopoverPickerPointerdown()
+    const {
+  return popover_picker_pointerdown_info_;
+}
+void Document::SetPopoverPickerPointerdown(PopoverPickerPointerdownInfo info) {
+  popover_picker_pointerdown_info_ = std::move(info);
+}
+
 void Document::exitPointerLock() {
   if (!GetPage())
     return;
@@ -9461,6 +9464,7 @@
   visitor->Trace(popover_hint_stack_);
   visitor->Trace(popover_pointerdown_target_);
   visitor->Trace(dialog_pointerdown_target_);
+  visitor->Trace(popover_picker_pointerdown_info_);
   visitor->Trace(popovers_waiting_to_hide_);
   visitor->Trace(all_open_popovers_);
   visitor->Trace(all_open_dialogs_);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h
index 9aed2062..dbc8988 100644
--- a/third_party/blink/renderer/core/dom/document.h
+++ b/third_party/blink/renderer/core/dom/document.h
@@ -1738,16 +1738,27 @@
   HeapHashSet<Member<HTMLElement>>& PopoversWaitingToHide() {
     return popovers_waiting_to_hide_;
   }
+  // PopoverPointerdownTarget is used by the popover light dismiss system, to
+  // track pointer events that might light-dismiss popovers.
   const HTMLElement* PopoverPointerdownTarget() const {
     return popover_pointerdown_target_.Get();
   }
   void SetPopoverPointerdownTarget(const HTMLElement*);
-  std::optional<gfx::PointF> PopoverPickerMousedownLocation() const {
-    return popover_picker_mousedown_location_;
-  }
-  void SetPopoverPickerMousedownLocation(std::optional<gfx::PointF>);
+  // DialogPointerdownTarget is used by the dialog light dismiss (`closedby`)
+  // system, to track pointer events that might light-dismiss dialogs.
   const HTMLDialogElement* DialogPointerdownTarget() const;
   void SetDialogPointerdownTarget(const HTMLDialogElement*);
+  // PopoverPickerPointerdown* is used by both customizable-<select> and the
+  // <menuitem> element for mousedown-drag-mouseup type interactions. If the
+  // `target` member is nullptr, no pointerdown info is stored.
+  struct PopoverPickerPointerdownInfo {
+    DISALLOW_NEW();
+    Member<Node> target;
+    gfx::PointF location;
+    void Trace(Visitor* visitor) const { visitor->Trace(target); }
+  };
+  PopoverPickerPointerdownInfo PopoverPickerPointerdown() const;
+  void SetPopoverPickerPointerdown(PopoverPickerPointerdownInfo);
 
   HeapLinkedHashSet<Member<HTMLDialogElement>>& AllOpenDialogs() {
     return all_open_dialogs_;
@@ -3169,14 +3180,14 @@
   HeapVector<Member<HTMLElement>> popover_hint_stack_;
   // The popover (if any) that received the most recent pointerdown event.
   Member<const HTMLElement> popover_pointerdown_target_;
-  // The mouse location for the mousedown that opened the picker, if any.
-  std::optional<gfx::PointF> popover_picker_mousedown_location_;
   // The dialog (if any) that received the most recent pointerdown event. This
   // is distinct from popover_pointerdown_target_ because the same pointer
   // action could trigger light dismiss on a containing popover and not a
   // containing dialog, or vice versa. This will be nullptr for a click on
   // the ::backdrop pseudo-element for a dialog.
   Member<const HTMLDialogElement> dialog_pointerdown_target_;
+  // The mouse target information for the event that opened the picker, if any.
+  PopoverPickerPointerdownInfo popover_picker_pointerdown_info_;
   // A set of popovers for which hidePopover() has been called, but animations
   // are still running.
   HeapHashSet<Member<HTMLElement>> popovers_waiting_to_hide_;
diff --git a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
index 33c0d26..bac15363 100644
--- a/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
+++ b/third_party/blink/renderer/core/dom/events/event_dispatcher.cc
@@ -433,7 +433,7 @@
   }
 
   if (event_->IsMouseEvent() && event_->type() == event_type_names::kMouseup) {
-    node_->GetDocument().SetPopoverPickerMousedownLocation(std::nullopt);
+    node_->GetDocument().SetPopoverPickerPointerdown({.target = nullptr});
   }
 
   // Track the usage of sending a mousedown event to a select element to force
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
index 23ff30b..c5dd46c 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -2547,7 +2547,6 @@
   visitor->Trace(crash_report_storage_);
   visitor->Trace(closewatcher_stack_);
   visitor->Trace(soft_navigation_heuristics_);
-  visitor->Trace(global_cache_storage_impl_);
   visitor->Trace(global_cookie_store_impl_);
   visitor->Trace(global_performance_impl_);
   visitor->Trace(cached_permission_status_);
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
index 2f209b50..8dd5c90a 100644
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
@@ -143,8 +143,6 @@
 class WindowSharedStorageImpl;
 
 template <typename T>
-class GlobalCacheStorageImpl;
-template <typename T>
 class GlobalCookieStoreImpl;
 template <typename T, typename P>
 class GlobalPerformanceImpl;
@@ -613,16 +611,6 @@
 
   void requestResize(ExceptionState&);
 
-  ForwardDeclaredMember<GlobalCacheStorageImpl<LocalDOMWindow>>
-  GetGlobalCacheStorageImpl() const {
-    return global_cache_storage_impl_;
-  }
-  void SetGlobalCacheStorageImpl(
-      ForwardDeclaredMember<GlobalCacheStorageImpl<LocalDOMWindow>>
-          global_cache_storage_impl) {
-    global_cache_storage_impl_ = global_cache_storage_impl;
-  }
-
   ForwardDeclaredMember<GlobalCookieStoreImpl<LocalDOMWindow>>
   GetGlobalCookieStoreImpl() const {
     return global_cookie_store_impl_;
@@ -1117,8 +1105,6 @@
 
   Member<SoftNavigationHeuristics> soft_navigation_heuristics_;
 
-  ForwardDeclaredMember<GlobalCacheStorageImpl<LocalDOMWindow>>
-      global_cache_storage_impl_;
   ForwardDeclaredMember<GlobalCookieStoreImpl<LocalDOMWindow>>
       global_cookie_store_impl_;
   ForwardDeclaredMember<
diff --git a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
index e27d289f..747816a 100644
--- a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
+++ b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.cc
@@ -64,6 +64,7 @@
 }
 
 void WindowOrWorkerGlobalScope::Trace(Visitor* visitor) const {
+  visitor->Trace(global_cache_storage_);
   visitor->Trace(global_crypto_);
   visitor->Trace(global_fetch_impl_);
 }
diff --git a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
index 2c29f77..42a7b3c 100644
--- a/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
+++ b/third_party/blink/renderer/core/frame/window_or_worker_global_scope.h
@@ -42,6 +42,7 @@
 
 namespace blink {
 
+class GlobalCacheStorage;
 class GlobalCrypto;
 
 template <typename T>
@@ -52,6 +53,14 @@
   bool crossOriginIsolated();
   String crossOriginEmbedderPolicy();
 
+  ForwardDeclaredMember<GlobalCacheStorage> GetGlobalCacheStorage() const {
+    return global_cache_storage_;
+  }
+  void SetGlobalCacheStorage(
+      ForwardDeclaredMember<GlobalCacheStorage> global_cache_storage) {
+    global_cache_storage_ = global_cache_storage;
+  }
+
   ForwardDeclaredMember<GlobalCrypto> GetGlobalCrypto() const {
     return global_crypto_;
   }
@@ -74,6 +83,7 @@
   virtual ExecutionContext* GetExecutionContext() const = 0;
 
  private:
+  ForwardDeclaredMember<GlobalCacheStorage> global_cache_storage_;
   ForwardDeclaredMember<GlobalCrypto> global_crypto_;
   ForwardDeclaredMember<GlobalFetchImpl<WindowOrWorkerGlobalScope>>
       global_fetch_impl_;
diff --git a/third_party/blink/renderer/core/html/forms/html_option_element.cc b/third_party/blink/renderer/core/html/forms/html_option_element.cc
index f262977c1..2ac4c0b 100644
--- a/third_party/blink/renderer/core/html/forms/html_option_element.cc
+++ b/third_party/blink/renderer/core/html/forms/html_option_element.cc
@@ -601,19 +601,18 @@
       //  2. The mouseup on this <option> was within kEpsilon layout units
       //     (post zoom, page-relative) of the location of the mousedown. I.e.
       //     the mouse was not dragged between mousedown and mouseup.
-      std::optional<gfx::PointF> mouse_down_loc =
-          GetDocument().PopoverPickerMousedownLocation();
+      auto mouse_down_info = GetDocument().PopoverPickerPointerdown();
       constexpr float kEpsilon = 5;  // 5 pixels in any direction
-      bool mouse_moved = !mouse_down_loc.has_value() ||
-                         !mouse_down_loc->IsWithinDistance(
+      bool mouse_moved = !mouse_down_info.target ||
+                         !mouse_down_info.location.IsWithinDistance(
                              mouse_event->AbsoluteLocation(), kEpsilon);
       if (mouse_moved) {
         ChooseOption(event);
       }
-      GetDocument().SetPopoverPickerMousedownLocation(std::nullopt);
+      GetDocument().SetPopoverPickerPointerdown({.target = nullptr});
       return;
     } else if (event.type() == event_type_names::kMousedown) {
-      GetDocument().SetPopoverPickerMousedownLocation(std::nullopt);
+      GetDocument().SetPopoverPickerPointerdown({.target = nullptr});
     }
   }
 
diff --git a/third_party/blink/renderer/core/html/forms/select_type.cc b/third_party/blink/renderer/core/html/forms/select_type.cc
index b354adb..f4bf9d2 100644
--- a/third_party/blink/renderer/core/html/forms/select_type.cc
+++ b/third_party/blink/renderer/core/html/forms/select_type.cc
@@ -493,8 +493,8 @@
           // Keep track of the mouse pixel location, so that when the mouseup
           // happens, we can see whether there was a mouse drag to pick an
           // option.
-          select_->GetDocument().SetPopoverPickerMousedownLocation(
-              mouse_event->AbsoluteLocation());
+          select_->GetDocument().SetPopoverPickerPointerdown(
+              {.target = select_, .location = mouse_event->AbsoluteLocation()});
         }
         ShowPopup(mouse_event->FromTouch() ? PopupMenu::kTouch
                                            : PopupMenu::kOther);
@@ -506,7 +506,7 @@
       mouse_event->button() ==
           static_cast<int16_t>(WebPointerProperties::Button::kLeft) &&
       PickerIsPopover() && !mouse_event->FromTouch()) {
-    select_->GetDocument().SetPopoverPickerMousedownLocation(std::nullopt);
+    select_->GetDocument().SetPopoverPickerPointerdown({.target = nullptr});
   }
   return false;
 }
diff --git a/third_party/blink/renderer/core/html/html_attribute_names.json5 b/third_party/blink/renderer/core/html/html_attribute_names.json5
index 9de23c3..ccb3732a 100644
--- a/third_party/blink/renderer/core/html/html_attribute_names.json5
+++ b/third_party/blink/renderer/core/html/html_attribute_names.json5
@@ -81,6 +81,7 @@
     "declare",
     "decoding",
     "default",
+    "defaultchecked",
     "defer",
     "delegatesfocus",
     "dir",
diff --git a/third_party/blink/renderer/core/html/html_element.h b/third_party/blink/renderer/core/html/html_element.h
index e988094..e14ab34 100644
--- a/third_party/blink/renderer/core/html/html_element.h
+++ b/third_party/blink/renderer/core/html/html_element.h
@@ -370,7 +370,7 @@
   virtual bool CanBeCommandInvoker() const;
   CommandEventType GetCommandEventType(const AtomicString& type,
                                        ExecutionContext*) const;
-  bool HandleCommandForActivation();
+  virtual bool HandleCommandForActivation();
   Element* commandForElement() const;
   AtomicString command() const;
   void setCommand(const AtomicString& type);
diff --git a/third_party/blink/renderer/core/html/html_geolocation_element.cc b/third_party/blink/renderer/core/html/html_geolocation_element.cc
index e513034..8cb672f 100644
--- a/third_party/blink/renderer/core/html/html_geolocation_element.cc
+++ b/third_party/blink/renderer/core/html/html_geolocation_element.cc
@@ -100,9 +100,9 @@
     if (!params.new_value) {
       ClearWatch();
     }
-  } else if (params.name == html_names::kAccuracymodeAttr &&
-             EqualIgnoringASCIICase(params.new_value, kAccuracyModePrecise)) {
-    SetPreciseLocation();
+  } else if (params.name == html_names::kAccuracymodeAttr) {
+    SetPreciseLocation(
+        EqualIgnoringASCIICase(params.new_value, kAccuracyModePrecise));
   }
 
   // If it's not a geolocation element specific attribute, the base class
diff --git a/third_party/blink/renderer/core/html/html_menu_item_element.cc b/third_party/blink/renderer/core/html/html_menu_item_element.cc
index 58d0fd5b..75853328 100644
--- a/third_party/blink/renderer/core/html/html_menu_item_element.cc
+++ b/third_party/blink/renderer/core/html/html_menu_item_element.cc
@@ -8,6 +8,7 @@
 #include "third_party/blink/renderer/core/css/selector_checker.h"
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
+#include "third_party/blink/renderer/core/dom/flat_tree_traversal.h"
 #include "third_party/blink/renderer/core/dom/popover_data.h"
 #include "third_party/blink/renderer/core/event_type_names.h"
 #include "third_party/blink/renderer/core/events/command_event.h"
@@ -36,9 +37,7 @@
 }
 
 bool HTMLMenuItemElement::MatchesDefaultPseudoClass() const {
-  // TODO(406566432): This should consider the `defaultchecked` when
-  // implemented.
-  return false;
+  return FastHasAttribute(html_names::kDefaultcheckedAttr);
 }
 
 bool HTMLMenuItemElement::MatchesEnabledPseudoClass() const {
@@ -53,6 +52,20 @@
       PseudoStateChanged(CSSSelector::kPseudoDisabled);
       PseudoStateChanged(CSSSelector::kPseudoEnabled);
     }
+  } else if (name == html_names::kDefaultcheckedAttr) {
+    // If the default value has not been overridden yet, then allow setting the
+    // `defaultchecked` attribute to influence the checkedness.
+    //
+    // Keep this logic in sync with the logic at the bottom of `InsertedInto()`.
+    if (!is_default_checkedness_overridden_) {
+      setChecked(!params.new_value.IsNull());
+      // Re-unset this flag, since `SetChecked()` set it to true by default.
+      is_default_checkedness_overridden_ = false;
+    }
+    // The `:default` pseudo-class should match the default checkedness,
+    // regardless of whether the default checkedness controls the underlying
+    // checked state anymore.
+    PseudoStateChanged(CSSSelector::kPseudoDefault);
   } else {
     HTMLElement::ParseAttribute(params);
   }
@@ -66,7 +79,8 @@
 bool HTMLMenuItemElement::IsCheckable() const {
   return HasOwnerMenuList() && nearest_ancestor_field_set_ &&
          nearest_ancestor_field_set_->FastGetAttribute(
-             html_names::kCheckableAttr);
+             html_names::kCheckableAttr) &&
+         !InvokesSubmenu();
 }
 
 bool HTMLMenuItemElement::checked() const {
@@ -96,10 +110,6 @@
 }
 
 int HTMLMenuItemElement::DefaultTabIndex() const {
-  // Menuitems in menulist should be traversed using arrow keys and not tabbing.
-  if (HasOwnerMenuList()) {
-    return -1;
-  }
   return 0;
 }
 
@@ -107,17 +117,14 @@
   return SelectorChecker::MatchesFocusVisiblePseudoClass(*this);
 }
 
-HTMLElement* HTMLMenuItemElement::InvokesSubmenuOrPopover() const {
-  HTMLElement* invoked_element = DynamicTo<HTMLElement>(commandForElement());
+HTMLMenuListElement* HTMLMenuItemElement::InvokesSubmenu() const {
+  auto* invoked_element = DynamicTo<HTMLMenuListElement>(commandForElement());
   if (!invoked_element || !invoked_element->IsPopover()) {
     return nullptr;
   }
   CommandEventType type = GetCommandEventType(
       FastGetAttribute(html_names::kCommandAttr), GetExecutionContext());
-  if (type != CommandEventType::kTogglePopover &&
-      type != CommandEventType::kShowPopover &&
-      type != CommandEventType::kHidePopover &&
-      type != CommandEventType::kToggleMenu &&
+  if (type != CommandEventType::kToggleMenu &&
       type != CommandEventType::kShowMenu &&
       type != CommandEventType::kHideMenu) {
     return nullptr;
@@ -125,10 +132,6 @@
   return invoked_element;
 }
 
-HTMLMenuListElement* HTMLMenuItemElement::InvokesSubmenu() const {
-  return DynamicTo<HTMLMenuListElement>(InvokesSubmenuOrPopover());
-}
-
 bool HTMLMenuItemElement::CanBeCommandInvoker() const {
   return !FastHasAttribute(html_names::kDisabledAttr);
 }
@@ -140,9 +143,12 @@
 
   if (!checkable) {
     // Not checkable - close the containing menulist unless this item invokes
-    // a sub-menu or a popover.
-    return !InvokesSubmenuOrPopover();
+    // a sub-menu.
+    return !InvokesSubmenu();
   }
+  DCHECK(!InvokesSubmenu());
+
+  is_default_checkedness_overridden_ = true;
 
   // Only update the exclusivity of all other menu items rooted under the same
   // fieldset *if* `this` is becoming checked under a fieldset that enforces
@@ -176,7 +182,8 @@
     DCHECK(IsCheckable() || !InvokesSubmenu());
     CloseOutermostContainingMenuList();
   }
-  if (!IsCheckable() && InvokesSubmenuOrPopover()) {
+  if (InvokesSubmenu()) {
+    DCHECK(!IsCheckable());
     HandleCommandForActivation();
   }
 }
@@ -217,11 +224,6 @@
 
   FocusParams focus_params(FocusTrigger::kUserGesture);
   const AtomicString key(keyboard_event->key());
-  if ((key == " " || key == keywords::kCapitalEnter)) {
-    // TODO(crbug.com/425682465): implement chooseItem(event).
-    // TODO: Do we need this?
-    return;
-  }
 
   // Nothing else below does anything if we're not inside an owner menu that has
   // at least one menu item.
@@ -390,78 +392,95 @@
   }
 }
 
-bool HTMLMenuItemElement::HandleMenuPointerEvents(Event& event) {
+void HTMLMenuItemElement::HandleMenuPointerEvents(Event& event) {
   // This implements the special "mouse down, drag to menu item, mouse up"
-  // behavior. This is a mouse-only behavior - it should not apply to pointer
-  // events for touchscreens. Touch events will be handled by the normal input
-  // system behavior of sending a DOMActivate event. This also does not apply
-  // to checkable menu items, which also rely on DOMActivate.
+  // behavior, which is mouse-only and does not apply to touchscreens. The
+  // remainder of normal mouse/touch behavior is handled by the normal
+  // DOMActivate event system.
   const auto* mouse_event = DynamicTo<MouseEvent>(event);
   if (!mouse_event || mouse_event->FromTouch() ||
       mouse_event->button() !=
           static_cast<int16_t>(WebPointerProperties::Button::kLeft) ||
       (event.type() != event_type_names::kMouseup &&
        event.type() != event_type_names::kMousedown)) {
-    return false;
+    return;
   }
 
   if (event.type() == event_type_names::kMouseup) {
-    // We leave the picker open, and do not "pick" a menu item, iff:
-    //  1. The mousedown was on a <menuitem> that triggers a sub-menu via
-    //     `commandfor`, so we have a mousedown location stored, and
-    //  2. The mouseup on this <menuitem> was within kEpsilon layout units
-    //     (post zoom, page-relative) of the location of the mousedown. I.e.
-    //     the mouse was not dragged between mousedown and mouseup. I.e. this
-    //     was just a "click" to open the menuitem's sub-menu - it shouldn't
-    //     pick anything yet.
-    std::optional<gfx::PointF> mouse_down_loc =
-        GetDocument().PopoverPickerMousedownLocation();
-    GetDocument().SetPopoverPickerMousedownLocation(std::nullopt);
+    auto mouse_down_info = GetDocument().PopoverPickerPointerdown();
+    GetDocument().SetPopoverPickerPointerdown({.target = nullptr});
+    HTMLMenuItemElement* mouse_down_menuitem = nullptr;
+    for (Node* node = mouse_down_info.target; node;
+         node = FlatTreeTraversal::Parent(*node)) {
+      if (auto* item = DynamicTo<HTMLMenuItemElement>(node)) {
+        mouse_down_menuitem = item;
+        break;
+      }
+    }
+    bool same_element = this == mouse_down_menuitem;
     // TODO(masonf) This kEpsilon should be combined with the one in
     // html_option_element.cc.
     constexpr float kEpsilon = 5;  // 5 pixels in any direction
-    bool activate_menu_item = !mouse_down_loc.has_value() ||
-                              !mouse_down_loc->IsWithinDistance(
-                                  mouse_event->AbsoluteLocation(), kEpsilon);
-    if (activate_menu_item) {
-      // The mouse moved, so select this menu item.
-      ActivateMenuItem();
+    bool mouse_moved = !mouse_down_info.location.IsWithinDistance(
+        mouse_event->AbsoluteLocation(), kEpsilon);
+    // We "pick" a menu item here, iff:
+    //  1. This was a mouse, not touchscreen, interaction,
+    //  2. The mousedown was on a <menuitem> that triggers a sub-menu via
+    //     `commandfor`, so we have a mousedown location stored,
+    //  3. The mouseup is on a different menuitem than the mouseup, and
+    //  4. The mouseup on this <menuitem> is *not* within kEpsilon layout units
+    //  (post zoom, page-relative) of the location of the mousedown. I.e. the
+    //  mouse was dragged at least a little bit between mousedown and mouseup.
+    //  This ensures that if the new sub-menu is rendered over the top of the
+    //  triggering menuitem, and the user is just "clicking" to activate the
+    //  sub-menu, the menuitem under the cursor isn't selected.
+
+    bool activate_menu_item =
+        mouse_down_menuitem && !same_element && mouse_moved;
+    if (!activate_menu_item) {
+      return;
     }
-    // TODO(crbug.com/406566432): This is a hack, and isn't strictly correct.
-    // We need a better way to ignore the synthetic `click` that triggers the
-    // `DOMActivate` that would double-trigger the menu in this case.
-    ignore_next_dom_activate_ = true;
+    ActivateMenuItem();
+    // This activation came from a mouse-down on a submenu invoker, so we need
+    // to clear the ignore_next_command_ flag for that menuitem.
+    mouse_down_menuitem->ignore_next_command_ = false;
   } else {
     DCHECK_EQ(event.type(), event_type_names::kMousedown);
+    GetDocument().SetPopoverPickerPointerdown(
+        {.target = this, .location = mouse_event->AbsoluteLocation()});
     if (!InvokesSubmenu()) {
-      return false;
+      return;
     }
-    GetDocument().SetPopoverPickerMousedownLocation(
-        mouse_event->FromTouch()
-            ? std::nullopt
-            : std::optional(mouse_event->AbsoluteLocation()));
-    // Activate sub-menus on mouse *down*, so that the user can drag and release
-    // to choose a sub-menu item.
+    // Activate sub-menus on mouse *down*, so that the user can drag and
+    // release to choose a sub-menu item.
     ActivateMenuItem();
+    // Because we're activating this menu item here, in mousedown, we want to
+    // avoid re-triggering the same menu again in the synthetic
+    // click/DOMActivate triggered command invocation.
+    ignore_next_command_ = true;
   }
-  return true;
+}
+
+bool HTMLMenuItemElement::HandleCommandForActivation() {
+  if (ignore_next_command_) {
+    DCHECK(InvokesSubmenu());
+    ignore_next_command_ = false;
+    return false;
+  }
+  return HTMLElement::HandleCommandForActivation();
 }
 
 void HTMLMenuItemElement::DefaultEventHandler(Event& event) {
+  if (event.type() == event_type_names::kDOMActivate && !InvokesSubmenu()) {
+    // If this isn't a submenu invoker, activate it now. If it is a command
+    // invoker of any kind, HTMLElement::DefaultEventHandler() will take care of
+    // it, so we can't early-return here.
+    ActivateMenuItem();
+  }
   if (HandleKeyboardActivation(event)) {
     return;
   }
-  if (event.type() == event_type_names::kDOMActivate) {
-    if (ignore_next_dom_activate_) {
-      ignore_next_dom_activate_ = false;
-    } else {
-      ActivateMenuItem();
-    }
-    return;
-  }
-  if (HandleMenuPointerEvents(event)) {
-    return;
-  }
+  HandleMenuPointerEvents(event);
   HandleMenuKeyboardEvents(event);
   HTMLElement::DefaultEventHandler(event);
 }
@@ -493,6 +512,15 @@
 
   // Run various ancestor/state resets.
   ResetAncestorElementCache();
+
+  // Keep this logic in sync with the checkedness logic in `ParseAttribute()`.
+  if (!is_default_checkedness_overridden_) {
+    const bool default_checked =
+        FastHasAttribute(html_names::kDefaultcheckedAttr);
+    setChecked(default_checked);
+    // Re-unset this flag, since `SetChecked()` set it to true by default.
+    is_default_checkedness_overridden_ = false;
+  }
   return return_value;
 }
 
diff --git a/third_party/blink/renderer/core/html/html_menu_item_element.h b/third_party/blink/renderer/core/html/html_menu_item_element.h
index 6ae5000b..49275e6d 100644
--- a/third_party/blink/renderer/core/html/html_menu_item_element.h
+++ b/third_party/blink/renderer/core/html/html_menu_item_element.h
@@ -44,6 +44,7 @@
       UpdateBehavior update_behavior =
           UpdateBehavior::kStyleAndLayout) const override;
 
+  bool HandleCommandForActivation() override;
   void DefaultEventHandler(Event&) override;
 
  private:
@@ -55,7 +56,6 @@
   FocusableState SupportsFocus(UpdateBehavior update_behavior) const override;
   bool ShouldHaveFocusAppearance() const override;
 
-  HTMLElement* InvokesSubmenuOrPopover() const;
   HTMLMenuListElement* InvokesSubmenu() const;
   // This is generally used when a menuitem has been selected, and the "tree" of
   // menus should now close. It finds the innermost (nearest ancestor) menulist
@@ -64,7 +64,7 @@
   // such menulist, which (via popover close behavior) closes the tree.
   Element* CloseOutermostContainingMenuList();
   void ActivateMenuItem();
-  bool HandleMenuPointerEvents(Event&);
+  void HandleMenuPointerEvents(Event&);
   void HandleMenuKeyboardEvents(Event&);
   bool HasOwnerMenuList() const;
 
@@ -79,8 +79,16 @@
 
   // Represents 'checkedness'.
   bool is_checked_;
-  // This is used to avoid double-invoking target menus and popovers.
-  bool ignore_next_dom_activate_ = false;
+  // This is used to avoid double-invoking target menus, due to custom logic
+  // that invokes sub-menus on mousedown.
+  bool ignore_next_command_ = false;
+  // This is similar to the input element's `dirty_checkedness_` flag, but
+  // better named. When only the default checkedness is set or unset, this will
+  // remain true. When checkedness finally gets set in any other way after the
+  // default checkedness has been processed, this becomes true. Then, future
+  // changes to the `defaultchecked` content attribute and `defaultChecked` IDL
+  // attribute will do nothing.
+  bool is_default_checkedness_overridden_;
 
   friend class HTMLMenuItemElementTest;
 };
diff --git a/third_party/blink/renderer/core/html/html_menu_item_element.idl b/third_party/blink/renderer/core/html/html_menu_item_element.idl
index c69007d..e360fa67 100644
--- a/third_party/blink/renderer/core/html/html_menu_item_element.idl
+++ b/third_party/blink/renderer/core/html/html_menu_item_element.idl
@@ -8,7 +8,14 @@
 ] interface HTMLMenuItemElement : HTMLElement {
     [HTMLConstructor] constructor();
     [CEReactions, Reflect] attribute boolean disabled;
+    // This is used to track live checked-ness.
     [CEReactions] attribute boolean checked;
+    // This is used to track only *default* checked-ness. It reflects a content
+    // attribute with the same name; the `defaultchecked` content attribute
+    // exists so that JavaScript is not required to set the initial checkedness
+    // of a menu element, and its reflected IDL attribute exists here for
+    // developer convenience.
+    [CEReactions, Reflect] attribute boolean defaultChecked;
 
     // Command Invokers
     [CEReactions, Reflect=commandfor] attribute Element? commandForElement;
diff --git a/third_party/blink/renderer/core/html/html_permission_element.cc b/third_party/blink/renderer/core/html/html_permission_element.cc
index bd4f122..bc6d160 100644
--- a/third_party/blink/renderer/core/html/html_permission_element.cc
+++ b/third_party/blink/renderer/core/html/html_permission_element.cc
@@ -63,6 +63,7 @@
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/text/platform_locale.h"
+#include "third_party/blink/renderer/platform/web_test_support.h"
 #include "third_party/blink/renderer/platform/wtf/functional.h"
 #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -638,13 +639,13 @@
   UpdateAppearance();
 }
 
-void HTMLPermissionElement::SetPreciseLocation() {
-  // This attribute can only be set once, and can not be modified afterwards.
-  if (is_precise_location_) {
+void HTMLPermissionElement::SetPreciseLocation(bool is_precise_location) {
+  if (is_precise_location_ == is_precise_location) {
     return;
   }
-
-  is_precise_location_ = true;
+  DisableClickingTemporarily(DisableReason::kAttributeChanged,
+                             kDefaultDisableTimeout);
+  is_precise_location_ = is_precise_location;
   UpdateAppearance();
 }
 
@@ -694,6 +695,8 @@
       return "intersection occluded or distorted";
     case DisableReason::kInvalidStyle:
       return "invalid style";
+    case DisableReason::kAttributeChanged:
+      return "an attribute changed";
     case DisableReason::kUnknown:
       NOTREACHED();
   }
@@ -716,6 +719,8 @@
           kIntersectionVisibilityOccludedOrDistorted;
     case DisableReason::kInvalidStyle:
       return UserInteractionDeniedReason::kInvalidStyle;
+    case DisableReason::kAttributeChanged:
+      return UserInteractionDeniedReason::kAttributeChanged;
     case DisableReason::kUnknown:
       NOTREACHED();
   }
@@ -735,6 +740,8 @@
       return AtomicString("intersection_occluded_or_distorted");
     case DisableReason::kInvalidStyle:
       return AtomicString("style_invalid");
+    case DisableReason::kAttributeChanged:
+      return AtomicString("attribute_changed");
     case DisableReason::kUnknown:
       NOTREACHED();
   }
@@ -839,7 +846,7 @@
   MaybeRegisterPageEmbeddedPermissionControl();
 
   if (params.name == html_names::kPreciselocationAttr) {
-    SetPreciseLocation();
+    SetPreciseLocation(params.new_value != nullptr);
   }
 
   HTMLElement::AttributeChanged(params);
diff --git a/third_party/blink/renderer/core/html/html_permission_element.h b/third_party/blink/renderer/core/html/html_permission_element.h
index 14fb8b28..759f2b92 100644
--- a/third_party/blink/renderer/core/html/html_permission_element.h
+++ b/third_party/blink/renderer/core/html/html_permission_element.h
@@ -142,7 +142,7 @@
     return permission_text_span_.Get();
   }
 
-  void SetPreciseLocation();
+  void SetPreciseLocation(bool);
 
   bool is_precise_location() const { return is_precise_location_; }
 
@@ -268,6 +268,9 @@
 
     // This element is disabled because of the element's style.
     kInvalidStyle,
+
+    // The element's attribute changed.
+    kAttributeChanged,
   };
 
   // These values are used for histograms. Entries should not be renumbered and
@@ -284,8 +287,8 @@
     kIntersectionWithViewportChanged = 6,
     kIntersectionVisibilityOutOfViewPortOrClipped = 7,
     kIntersectionVisibilityOccludedOrDistorted = 8,
-
-    kMaxValue = kIntersectionVisibilityOccludedOrDistorted,
+    kAttributeChanged = 9,
+    kMaxValue = kAttributeChanged,
   };
   // LINT.ThenChange(//tools/metrics/histograms/metadata/blink/enums.xml:PermissionElementUserInteractionDeniedReason)
 
diff --git a/third_party/blink/renderer/core/html/html_permission_element_test.cc b/third_party/blink/renderer/core/html/html_permission_element_test.cc
index 287b31f0..9e47e4b 100644
--- a/third_party/blink/renderer/core/html/html_permission_element_test.cc
+++ b/third_party/blink/renderer/core/html/html_permission_element_test.cc
@@ -226,7 +226,7 @@
   EXPECT_TRUE(permission_element->is_precise_location_);
 
   permission_element->removeAttribute(html_names::kPreciselocationAttr);
-  EXPECT_TRUE(permission_element->is_precise_location_);
+  EXPECT_FALSE(permission_element->is_precise_location_);
 }
 
 TEST_F(HTMLPermissionElementTestBase, ParsePermissionDescriptorsFromType) {
diff --git a/third_party/blink/renderer/core/style/build.gni b/third_party/blink/renderer/core/style/build.gni
index cfa243cd..43a3a3d 100644
--- a/third_party/blink/renderer/core/style/build.gni
+++ b/third_party/blink/renderer/core/style/build.gni
@@ -23,7 +23,6 @@
   "content_data.cc",
   "content_data.h",
   "coord_box_offset_path_operation.h",
-  "counter_directives.cc",
   "counter_directives.h",
   "cursor_data.h",
   "cursor_list.h",
diff --git a/third_party/blink/renderer/core/style/counter_directives.cc b/third_party/blink/renderer/core/style/counter_directives.cc
deleted file mode 100644
index 4bd3de8..0000000
--- a/third_party/blink/renderer/core/style/counter_directives.cc
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
- * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public License
- * along with this library; see the file COPYING.LIB.  If not, write to
- * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
- * Boston, MA 02110-1301, USA.
- *
- */
-
-#include "third_party/blink/renderer/core/style/counter_directives.h"
-
-#include <memory>
-
-namespace blink {
-
-bool operator==(const CounterDirectives& a, const CounterDirectives& b) {
-  return a.reset_value_ == b.reset_value_ &&
-         a.is_reset_reversed_ == b.is_reset_reversed_ &&
-         a.increment_value_ == b.increment_value_ &&
-         a.set_value_ == b.set_value_;
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/core/style/counter_directives.h b/third_party/blink/renderer/core/style/counter_directives.h
index 94a5662..670a814 100644
--- a/third_party/blink/renderer/core/style/counter_directives.h
+++ b/third_party/blink/renderer/core/style/counter_directives.h
@@ -118,7 +118,7 @@
         .ValueOrDefault(reset_value_.value_or(0));
   }
 
-  friend bool operator==(const CounterDirectives&, const CounterDirectives&);
+  bool operator==(const CounterDirectives&) const = default;
 
  private:
   std::optional<int> reset_value_;
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.cc b/third_party/blink/renderer/core/workers/worker_global_scope.cc
index 020f2f1..a38b26bf 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.cc
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.cc
@@ -834,8 +834,6 @@
   visitor->Trace(trusted_types_);
   visitor->Trace(worker_script_);
   visitor->Trace(browser_interface_broker_proxy_);
-  visitor->Trace(global_cache_storage_impl_);
-  visitor->Trace(global_cookie_store_impl_);
   visitor->Trace(global_performance_impl_);
   visitor->Trace(font_face_set_worker_);
   ExecutionContext::Trace(visitor);
diff --git a/third_party/blink/renderer/core/workers/worker_global_scope.h b/third_party/blink/renderer/core/workers/worker_global_scope.h
index b295b34..71ebb0a 100644
--- a/third_party/blink/renderer/core/workers/worker_global_scope.h
+++ b/third_party/blink/renderer/core/workers/worker_global_scope.h
@@ -80,10 +80,6 @@
 class WorkerPerformance;
 class FontFaceSetWorker;
 
-template <typename T>
-class GlobalCacheStorageImpl;
-template <typename T>
-class GlobalCookieStoreImpl;
 template <typename T, typename P>
 class GlobalPerformanceImpl;
 
@@ -283,26 +279,6 @@
     return top_level_frame_security_origin_.get();
   }
 
-  ForwardDeclaredMember<GlobalCacheStorageImpl<WorkerGlobalScope>>
-  GetGlobalCacheStorageImpl() const {
-    return global_cache_storage_impl_;
-  }
-  void SetGlobalCacheStorageImpl(
-      ForwardDeclaredMember<GlobalCacheStorageImpl<WorkerGlobalScope>>
-          global_cache_storage_impl) {
-    global_cache_storage_impl_ = global_cache_storage_impl;
-  }
-
-  ForwardDeclaredMember<GlobalCookieStoreImpl<WorkerGlobalScope>>
-  GetGlobalCookieStoreImpl() const {
-    return global_cookie_store_impl_;
-  }
-  void SetGlobalCookieStoreImpl(
-      ForwardDeclaredMember<GlobalCookieStoreImpl<WorkerGlobalScope>>
-          global_cookie_store_impl) {
-    global_cookie_store_impl_ = global_cookie_store_impl;
-  }
-
   ForwardDeclaredMember<
       GlobalPerformanceImpl<WorkerGlobalScope, WorkerPerformance>>
   GetGlobalPerformanceImpl() const {
@@ -445,10 +421,6 @@
   // origin.
   scoped_refptr<const SecurityOrigin> top_level_frame_security_origin_;
 
-  ForwardDeclaredMember<GlobalCacheStorageImpl<WorkerGlobalScope>>
-      global_cache_storage_impl_;
-  ForwardDeclaredMember<GlobalCookieStoreImpl<WorkerGlobalScope>>
-      global_cookie_store_impl_;
   ForwardDeclaredMember<
       GlobalPerformanceImpl<WorkerGlobalScope, WorkerPerformance>>
       global_performance_impl_;
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
index d8978c5..e7b55d7 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.cc
@@ -372,6 +372,7 @@
 void XMLDocumentParser::ClearCurrentNodeStack() {
   current_node_ = nullptr;
   leaf_text_node_ = nullptr;
+  ancestor_resetting_namespace_ = nullptr;
 
   if (current_node_stack_.size()) {  // Aborted parsing.
     current_node_stack_.clear();
@@ -914,6 +915,7 @@
 void XMLDocumentParser::Trace(Visitor* visitor) const {
   visitor->Trace(current_node_);
   visitor->Trace(current_node_stack_);
+  visitor->Trace(ancestor_resetting_namespace_);
   visitor->Trace(leaf_text_node_);
   visitor->Trace(xml_errors_);
   visitor->Trace(document_);
@@ -959,6 +961,7 @@
 static inline bool HandleNamespaceAttributes(
     Vector<Attribute, kAttributePrealloc>& prefixed_attributes,
     base::span<const xmlSAX2Namespace> namespaces,
+    bool& encountered_namespace_reset,
     ExceptionState& exception_state) {
   for (const auto& ns : namespaces) {
     AtomicString namespace_q_name = g_xmlns_atom;
@@ -973,6 +976,9 @@
       DCHECK(exception_state.HadException());
       return false;
     }
+    if (parsed_name->LocalName() == g_xmlns_atom) {
+      encountered_namespace_reset = namespace_uri.empty();
+    }
     prefixed_attributes.push_back(Attribute(*parsed_name, namespace_uri));
   }
   return true;
@@ -1046,6 +1052,18 @@
   if (!UpdateLeafTextNode())
     return;
 
+  bool is_first_element = !saw_first_element_;
+  saw_first_element_ = true;
+
+  Vector<Attribute, kAttributePrealloc> prefixed_attributes;
+  bool encountered_namespace_reset = false;
+  if (!HandleNamespaceAttributes(prefixed_attributes, namespaces,
+                                 encountered_namespace_reset,
+                                 IGNORE_EXCEPTION)) {
+    StopParsing();
+    return;
+  }
+
   // Needed for fragment parsing. If the parser library reports an empty NS url,
   // resolve it against the initially preserved namespace hierarchy that is
   // built when creating an XMLDocumentParser with the fragment-parsing
@@ -1057,20 +1075,13 @@
       if (it != prefix_to_namespace_map_.end())
         adjusted_uri = it->value;
     } else {
-      adjusted_uri = default_namespace_uri_;
+      adjusted_uri =
+          encountered_namespace_reset || ancestor_resetting_namespace_
+              ? g_null_atom
+              : default_namespace_uri_;
     }
   }
 
-  bool is_first_element = !saw_first_element_;
-  saw_first_element_ = true;
-
-  Vector<Attribute, kAttributePrealloc> prefixed_attributes;
-  if (!HandleNamespaceAttributes(prefixed_attributes, namespaces,
-                                 IGNORE_EXCEPTION)) {
-    StopParsing();
-    return;
-  }
-
   v8::Isolate* isolate = document_->GetAgent().isolate();
   v8::TryCatch try_catch(isolate);
   if (!HandleElementAttributes(prefixed_attributes, attributes,
@@ -1134,6 +1145,10 @@
 
   SetAttributes(new_element, prefixed_attributes, GetParserContentPolicy());
 
+  if (parsing_fragment_ && encountered_namespace_reset) {
+    ancestor_resetting_namespace_ = new_element;
+  }
+
   new_element->BeginParsingChildren();
 
   if (new_element->IsScriptElement())
@@ -1185,6 +1200,10 @@
     return;
   }
 
+  if (ancestor_resetting_namespace_ == n) {
+    ancestor_resetting_namespace_ = nullptr;
+  }
+
   element->FinishParsingChildren();
 
   CheckIfBlockingStyleSheetAdded();
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser.h b/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
index 447a53eb..c53a1a6 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser.h
@@ -208,6 +208,10 @@
   Vector<xmlChar> buffered_text_;
 
   Member<ContainerNode> current_node_;
+  // In fragment parsing, track a parent element that has reset the default
+  // namespace, in order not to apply the surrounding element's default
+  // namespace when fixing-up fragment element's namespace information.
+  Member<ContainerNode> ancestor_resetting_namespace_ = nullptr;
   HeapVector<Member<ContainerNode>> current_node_stack_;
 
   Member<Text> leaf_text_node_;
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.cc b/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.cc
index 8238b11..6de4265a 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.cc
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.cc
@@ -89,11 +89,12 @@
 bool HandleNamespaceAttributes(
     Vector<Attribute, kAttributePrealloc>& prefixed_attributes,
     xml_ffi::NamespacesIterator& namespaces,
+    bool& encountered_namespace_reset,
     ExceptionState& exception_state) {
   rust::String prefix;
   rust::String uri;
 
-  while (namespaces_next(namespaces, prefix, uri) && uri.length()) {
+  while (namespaces_next(namespaces, prefix, uri)) {
     AtomicString namespace_q_name = g_xmlns_atom;
     if (prefix.length()) {
       namespace_q_name = AtomicString(
@@ -105,6 +106,9 @@
       DCHECK(exception_state.HadException());
       return false;
     }
+    if (parsed_name->LocalName() == g_xmlns_atom) {
+      encountered_namespace_reset = uri.empty();
+    }
     prefixed_attributes.push_back(
         Attribute(std::move(*parsed_name), RustStrToAtomicString(uri)));
   }
@@ -263,6 +267,7 @@
 void XMLDocumentParserRs::ClearCurrentNodeStack() {
   current_node_ = nullptr;
   leaf_text_node_ = nullptr;
+  ancestor_resetting_namespace_ = nullptr;
 
   if (current_node_stack_.size()) {  // Aborted parsing.
     current_node_stack_.clear();
@@ -272,6 +277,7 @@
 void XMLDocumentParserRs::Trace(Visitor* visitor) const {
   visitor->Trace(current_node_);
   visitor->Trace(current_node_stack_);
+  visitor->Trace(ancestor_resetting_namespace_);
   visitor->Trace(leaf_text_node_);
   visitor->Trace(xml_errors_);
   visitor->Trace(document_);
@@ -357,6 +363,17 @@
     return;
   }
 
+  bool is_first_element = !saw_first_element_;
+  saw_first_element_ = true;
+
+  Vector<Attribute, kAttributePrealloc> prefixed_attributes;
+  bool encountered_namespace_reset = false;
+  if (!HandleNamespaceAttributes(prefixed_attributes, namespaces,
+                                 encountered_namespace_reset,
+                                 IGNORE_EXCEPTION)) {
+    StopParsing();
+    return;
+  }
   // In fragment parsing, adjust namespace URI. If the parser library reports an
   // empty NS url, resolve it against the initially preserved namespace
   // hierarchy that is built when creating an XMLDocumentParser with the
@@ -371,20 +388,13 @@
         adjusted_ns_uri = it->value;
       }
     } else {
-      adjusted_ns_uri = default_namespace_uri_;
+      adjusted_ns_uri =
+          encountered_namespace_reset || ancestor_resetting_namespace_
+              ? g_null_atom
+              : default_namespace_uri_;
     }
   }
 
-  bool is_first_element = !saw_first_element_;
-  saw_first_element_ = true;
-  Vector<Attribute, kAttributePrealloc> prefixed_attributes;
-
-  if (!HandleNamespaceAttributes(prefixed_attributes, namespaces,
-                                 IGNORE_EXCEPTION)) {
-    StopParsing();
-    return;
-  }
-
   v8::Isolate* isolate = document_->GetAgent().isolate();
   v8::TryCatch try_catch(isolate);
   if (!CollectElementAttributes(prefixed_attributes, attributes,
@@ -449,6 +459,10 @@
 
   SetAttributes(new_element, prefixed_attributes, GetParserContentPolicy());
 
+  if (parsing_fragment_ && encountered_namespace_reset) {
+    ancestor_resetting_namespace_ = new_element;
+  }
+
   new_element->BeginParsingChildren();
 
   if (new_element->IsScriptElement()) {
@@ -496,6 +510,10 @@
     return;
   }
 
+  if (ancestor_resetting_namespace_ == n) {
+    ancestor_resetting_namespace_ = nullptr;
+  }
+
   element->FinishParsingChildren();
 
   CheckIfBlockingStyleSheetAdded();
diff --git a/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.h b/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.h
index b5de0b8c..b82329a8 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.h
+++ b/third_party/blink/renderer/core/xml/parser/xml_document_parser_rs.h
@@ -120,6 +120,10 @@
   StringBuilder buffered_text_;
 
   Member<ContainerNode> current_node_;
+  // In fragment parsing, track a parent element that has reset the default
+  // namespace, in order not to apply the surrounding element's default
+  // namespace when fixing-up fragment element's namespace information.
+  Member<ContainerNode> ancestor_resetting_namespace_ = nullptr;
   HeapVector<Member<ContainerNode>> current_node_stack_;
   Member<Text> leaf_text_node_;
 
diff --git a/third_party/blink/renderer/core/xml/parser/xml_ffi.rs b/third_party/blink/renderer/core/xml/parser/xml_ffi.rs
index 30394f7..9489363 100644
--- a/third_party/blink/renderer/core/xml/parser/xml_ffi.rs
+++ b/third_party/blink/renderer/core/xml/parser/xml_ffi.rs
@@ -275,11 +275,13 @@
             // TODO(drott): Why do we see an empty namespace here for
             // fast/dom/attribute-namespaces-get-set.html and XML like:
             // <root xmlns:foo=\"http://www.example.com\" attr=\"test2\" foo:attr=\"test\" />
+            // and virtual/rust-xml/fast/xmlhttprequest/xmlhttprequest-get.xhtml
             // Filed as: https://github.com/kornelski/xml-rs/issues/50
 
+            // Letting the empty namespace and empty URL pass through here
+            // is important to reset the default namespace to none.
             if (namespace.0 == "xml" && namespace.1 == NS_XML_URI)
                 || (namespace.0 == "xmlns" && namespace.1 == NS_XMLNS_URI)
-                || (namespace.0 == "" && namespace.1 == "")
             {
                 continue;
             }
diff --git a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
index 6673593..83a5ece 100644
--- a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
+++ b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
@@ -4,63 +4,25 @@
 
 #include "third_party/blink/renderer/modules/cache_storage/global_cache_storage.h"
 
+#include "third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom-blink.h"
+#include "third_party/blink/public/platform/browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/web_security_origin.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
-#include "third_party/blink/renderer/core/frame/local_dom_window.h"
-#include "third_party/blink/renderer/core/workers/worker_global_scope.h"
+#include "third_party/blink/renderer/core/frame/window_or_worker_global_scope.h"
 #include "third_party/blink/renderer/modules/cache_storage/cache_storage.h"
-#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
 
 namespace blink {
 
-template <typename T>
-class GlobalCacheStorageImpl final
-    : public GarbageCollected<GlobalCacheStorageImpl<T>>,
-      public GarbageCollectedMixin {
- public:
-  static GlobalCacheStorageImpl& From(T& supplementable) {
-    GlobalCacheStorageImpl* supplement =
-        supplementable.GetGlobalCacheStorageImpl();
-    if (!supplement) {
-      supplement = MakeGarbageCollected<GlobalCacheStorageImpl>();
-      supplementable.SetGlobalCacheStorageImpl(supplement);
-    }
-    return *supplement;
+GlobalCacheStorage& GlobalCacheStorage::From(
+    WindowOrWorkerGlobalScope& supplementable) {
+  GlobalCacheStorage* supplement = supplementable.GetGlobalCacheStorage();
+  if (!supplement) {
+    supplement = MakeGarbageCollected<GlobalCacheStorage>();
+    supplementable.SetGlobalCacheStorage(supplement);
   }
-
-  GlobalCacheStorageImpl() = default;
-  ~GlobalCacheStorageImpl() = default;
-
-  CacheStorage* Caches(T& fetching_scope, ExceptionState& exception_state) {
-    ExecutionContext* context = fetching_scope.GetExecutionContext();
-    if (!GlobalCacheStorage::CanCreateCacheStorage(context, exception_state)) {
-      return nullptr;
-    }
-
-    if (context->GetSecurityOrigin()->IsLocal()) {
-      UseCounter::Count(context, WebFeature::kFileAccessedCache);
-    }
-
-    if (!caches_) {
-      if (&context->GetBrowserInterfaceBroker() ==
-          &GetEmptyBrowserInterfaceBroker()) {
-        exception_state.ThrowSecurityError(
-            "Cache storage isn't available on detached context. No browser "
-            "interface broker.");
-        return nullptr;
-      }
-      caches_ = MakeGarbageCollected<CacheStorage>(
-          context, GlobalFetch::ScopedFetcher::From(fetching_scope));
-    }
-    return caches_.Get();
-  }
-
-  void Trace(Visitor* visitor) const override { visitor->Trace(caches_); }
-
- private:
-  Member<CacheStorage> caches_;
-};
+  return *supplement;
+}
 
 bool GlobalCacheStorage::CanCreateCacheStorage(
     ExecutionContext* context,
@@ -82,16 +44,41 @@
   return false;
 }
 
-CacheStorage* GlobalCacheStorage::caches(LocalDOMWindow& window,
-                                         ExceptionState& exception_state) {
-  return GlobalCacheStorageImpl<LocalDOMWindow>::From(window).Caches(
-      window, exception_state);
+CacheStorage* GlobalCacheStorage::Caches(
+    WindowOrWorkerGlobalScope& window_or_worker,
+    ExceptionState& exception_state) {
+  ExecutionContext* context = window_or_worker.GetExecutionContext();
+  if (!GlobalCacheStorage::CanCreateCacheStorage(context, exception_state)) {
+    return nullptr;
+  }
+
+  if (context->GetSecurityOrigin()->IsLocal()) {
+    UseCounter::Count(context, WebFeature::kFileAccessedCache);
+  }
+
+  if (!caches_) {
+    if (&context->GetBrowserInterfaceBroker() ==
+        &GetEmptyBrowserInterfaceBroker()) {
+      exception_state.ThrowSecurityError(
+          "Cache storage isn't available on detached context. No browser "
+          "interface broker.");
+      return nullptr;
+    }
+    caches_ = MakeGarbageCollected<CacheStorage>(
+        context, GlobalFetch::ScopedFetcher::From(window_or_worker));
+  }
+  return caches_.Get();
 }
 
-CacheStorage* GlobalCacheStorage::caches(WorkerGlobalScope& worker,
-                                         ExceptionState& exception_state) {
-  return GlobalCacheStorageImpl<WorkerGlobalScope>::From(worker).Caches(
-      worker, exception_state);
+void GlobalCacheStorage::Trace(Visitor* visitor) const {
+  visitor->Trace(caches_);
+}
+
+CacheStorage* GlobalCacheStorage::caches(
+    WindowOrWorkerGlobalScope& window_or_worker,
+    ExceptionState& exception_state) {
+  return GlobalCacheStorage::From(window_or_worker)
+      .Caches(window_or_worker, exception_state);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.h b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.h
index 0e3fd5b..228d81f 100644
--- a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.h
+++ b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.h
@@ -5,24 +5,32 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_GLOBAL_CACHE_STORAGE_H_
 #define THIRD_PARTY_BLINK_RENDERER_MODULES_CACHE_STORAGE_GLOBAL_CACHE_STORAGE_H_
 
-#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
 
 namespace blink {
 
 class CacheStorage;
 class ExceptionState;
 class ExecutionContext;
-class LocalDOMWindow;
-class WorkerGlobalScope;
+class WindowOrWorkerGlobalScope;
 
-class GlobalCacheStorage {
-  STATIC_ONLY(GlobalCacheStorage);
-
+class GlobalCacheStorage final : public GarbageCollected<GlobalCacheStorage>,
+                                 public GarbageCollectedMixin {
  public:
+  GlobalCacheStorage() = default;
+
   static bool CanCreateCacheStorage(ExecutionContext*, ExceptionState&);
 
-  static CacheStorage* caches(LocalDOMWindow&, ExceptionState&);
-  static CacheStorage* caches(WorkerGlobalScope&, ExceptionState&);
+  static CacheStorage* caches(WindowOrWorkerGlobalScope&, ExceptionState&);
+
+  void Trace(Visitor* visitor) const override;
+
+ private:
+  static GlobalCacheStorage& From(WindowOrWorkerGlobalScope&);
+  CacheStorage* Caches(WindowOrWorkerGlobalScope&, ExceptionState&);
+
+  Member<CacheStorage> caches_;
 };
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc b/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc
index 84a25a9..4cd2eef 100644
--- a/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc
+++ b/third_party/blink/renderer/modules/cookie_store/global_cookie_store.cc
@@ -68,9 +68,10 @@
 }
 
 // static
-CookieStore* GlobalCookieStore::cookieStore(ServiceWorkerGlobalScope& worker) {
-  return GlobalCookieStoreImpl<WorkerGlobalScope>::From(worker).GetCookieStore(
-      worker);
+CookieStore* GlobalCookieStore::cookieStore(
+    ServiceWorkerGlobalScope& service_worker) {
+  return GlobalCookieStoreImpl<ServiceWorkerGlobalScope>::From(service_worker)
+      .GetCookieStore(service_worker);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
index f8329c5..1d34659 100644
--- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
+++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -42,7 +42,6 @@
 #include "third_party/blink/renderer/modules/gamepad/gamepad_event.h"
 #include "third_party/blink/renderer/modules/gamepad/gamepad_raw_input_change_event.h"
 #include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
-#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
 #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
 
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
index 9ea3423..c67cb146 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
@@ -801,6 +801,7 @@
   visitor->Trace(can_make_payment_result_callbacks_);
   visitor->Trace(payment_response_callbacks_);
   visitor->Trace(fetch_response_callbacks_);
+  visitor->Trace(global_cookie_store_impl_);
   visitor->Trace(pending_preload_fetch_events_);
   visitor->Trace(pending_streaming_upload_fetch_events_);
   visitor->Trace(controller_receivers_);
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
index 97c569a..bf924852 100644
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.h
@@ -53,6 +53,7 @@
 #include "third_party/blink/renderer/modules/service_worker/cross_origin_resource_policy_checker.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker_event_queue.h"
 #include "third_party/blink/renderer/modules/service_worker/service_worker_installed_scripts_manager.h"
+#include "third_party/blink/renderer/platform/forward_declared_member.h"
 #include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_map.h"
 #include "third_party/blink/renderer/platform/heap/disallow_new_wrapper.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
@@ -85,6 +86,9 @@
 struct WebServiceWorkerError;
 struct WebServiceWorkerObjectInfo;
 
+template <typename T>
+class GlobalCookieStoreImpl;
+
 class MODULES_EXPORT ServiceWorkerGlobalScope final
     : public WorkerGlobalScope,
       public mojom::blink::ControllerServiceWorker,
@@ -369,6 +373,16 @@
 
   bool did_evaluate_script() { return did_evaluate_script_; }
 
+  ForwardDeclaredMember<GlobalCookieStoreImpl<ServiceWorkerGlobalScope>>
+  GetGlobalCookieStoreImpl() const {
+    return global_cookie_store_impl_;
+  }
+  void SetGlobalCookieStoreImpl(
+      ForwardDeclaredMember<GlobalCookieStoreImpl<ServiceWorkerGlobalScope>>
+          global_cookie_store_impl) {
+    global_cookie_store_impl_ = global_cookie_store_impl;
+  }
+
  protected:
   // EventTarget
   bool AddEventListenerInternal(
@@ -826,6 +840,9 @@
                              ServiceWorkerGlobalScope>
       associated_interfaces_receiver_{this, this};
   AssociatedInterfaceRegistry associated_inteface_registy_;
+
+  ForwardDeclaredMember<GlobalCookieStoreImpl<ServiceWorkerGlobalScope>>
+      global_cookie_store_impl_;
 };
 
 template <>
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
index ff39cd1..57abaa98 100644
--- a/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
+++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_external.cc
@@ -87,7 +87,7 @@
   base::span<const uint8_t> GetSomeData(size_t position) const override {
     return segment_reader_->GetSomeData(position);
   }
-  sk_sp<SkData> GetAsSkData() const override {
+  sk_sp<const SkData> GetAsSkData() const override {
     return segment_reader_->GetAsSkData();
   }
 
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 49d07b1..c1f8706 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -1461,8 +1461,6 @@
     "peerconnection/webrtc_util.h",
     "peerconnection/webrtc_video_track_source.cc",
     "peerconnection/webrtc_video_track_source.h",
-    "privacy_budget/identifiability_digest_helpers.cc",
-    "privacy_budget/identifiability_digest_helpers.h",
     "region_capture_crop_id.cc",
     "region_capture_crop_id.h",
     "resolution_units.h",
diff --git a/third_party/blink/renderer/platform/exported/web_image_generator.cc b/third_party/blink/renderer/platform/exported/web_image_generator.cc
index d1668dbc..780408e 100644
--- a/third_party/blink/renderer/platform/exported/web_image_generator.cc
+++ b/third_party/blink/renderer/platform/exported/web_image_generator.cc
@@ -36,7 +36,7 @@
 namespace blink {
 
 std::unique_ptr<SkImageGenerator> WebImageGenerator::CreateAsSkImageGenerator(
-    sk_sp<SkData> data) {
+    sk_sp<const SkData> data) {
   return DecodingImageGenerator::CreateAsSkImageGenerator(std::move(data));
 }
 
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
index accd17e..357d7ed4 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.cc
@@ -61,7 +61,7 @@
 
 // static
 std::unique_ptr<SkImageGenerator>
-DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<SkData> data) {
+DecodingImageGenerator::CreateAsSkImageGenerator(sk_sp<const SkData> data) {
   // This image generator is used only by code in Skia, which in practice means
   // out of process printing deserialization (MSKP) and a few odds and ends.
   // Blink side code uses DecodingImageGenerator::Create directly instead.
@@ -134,7 +134,7 @@
 
 DecodingImageGenerator::~DecodingImageGenerator() = default;
 
-sk_sp<SkData> DecodingImageGenerator::GetEncodedData() const {
+sk_sp<const SkData> DecodingImageGenerator::GetEncodedData() const {
   TRACE_EVENT0("blink", "DecodingImageGenerator::refEncodedData");
 
   // getAsSkData() may require copying, but the clients of this function are
diff --git a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
index 8227f67..6810d85 100644
--- a/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
+++ b/third_party/blink/renderer/platform/graphics/decoding_image_generator.h
@@ -54,7 +54,7 @@
   // (exported via WebImageGenerator and set via
   // SkGraphics::SetImageGeneratorFromEncodedDataFactory)
   static std::unique_ptr<SkImageGenerator> CreateAsSkImageGenerator(
-      sk_sp<SkData>);
+      sk_sp<const SkData>);
 
   static sk_sp<DecodingImageGenerator> Create(
       scoped_refptr<ImageFrameGenerator>,
@@ -71,7 +71,7 @@
   ~DecodingImageGenerator() override;
 
   // PaintImageGenerator implementation.
-  sk_sp<SkData> GetEncodedData() const override;
+  sk_sp<const SkData> GetEncodedData() const override;
   bool GetPixels(SkPixmap,
                  size_t frame_index,
                  PaintImage::GeneratorClientId client_id,
diff --git a/third_party/blink/renderer/platform/graphics/parkable_image.cc b/third_party/blink/renderer/platform/graphics/parkable_image.cc
index 4f2ef62..fe38f193 100644
--- a/third_party/blink/renderer/platform/graphics/parkable_image.cc
+++ b/third_party/blink/renderer/platform/graphics/parkable_image.cc
@@ -107,7 +107,7 @@
   explicit ParkableImageSegmentReader(scoped_refptr<ParkableImage> image);
   size_t size() const override;
   base::span<const uint8_t> GetSomeData(size_t position) const override;
-  sk_sp<SkData> GetAsSkData() const override;
+  sk_sp<const SkData> GetAsSkData() const override;
   void LockData() override;
   void UnlockData() override;
 
@@ -139,7 +139,7 @@
   return RWBufferGetSomeData(iter, position_of_block, position);
 }
 
-sk_sp<SkData> ParkableImageSegmentReader::GetAsSkData() const {
+sk_sp<const SkData> ParkableImageSegmentReader::GetAsSkData() const {
   if (!parkable_image_) {
     return nullptr;
   }
diff --git a/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader_test.cc b/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader_test.cc
index 110eb9a560..575e16b9 100644
--- a/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader_test.cc
+++ b/third_party/blink/renderer/platform/image-decoders/fast_shared_buffer_reader_test.cc
@@ -164,7 +164,7 @@
   }
   SegmentReaders reader_struct(data);
   for (auto segment_reader : reader_struct.segment_readers) {
-    sk_sp<SkData> skdata = segment_reader->GetAsSkData();
+    sk_sp<const SkData> skdata = segment_reader->GetAsSkData();
     EXPECT_EQ(data->size(), skdata->size());
     auto skdata_span = skia::as_byte_span(*skdata);
 
diff --git a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
index 8f53cc0..031e883 100644
--- a/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/jpeg/jpeg_image_decoder.cc
@@ -864,18 +864,18 @@
   // multi-picture format, also known as CIPA DC-007). This is in contrast with
   // other decoders (e.g AVIF), which are aware of gainmap metadata.
   if (data && aux_image_ == cc::AuxImage::kGainmap) {
-    sk_sp<SkData> base_image_data = data->GetAsSkData();
+    auto base_image_data = data->GetAsSkData();
     DCHECK(base_image_data);
-    SkGainmapInfo gainmap_info;
-    sk_sp<SkData> gainmap_image_data;
     auto base_metadata_decoder = SkJpegMetadataDecoder::Make(base_image_data);
-    if (!base_metadata_decoder->findGainmapImage(
-            base_image_data, gainmap_image_data, gainmap_info)) {
+    if (auto [gainmap_image_data, _] =
+            base_metadata_decoder->findGainmapImage(base_image_data);
+        gainmap_image_data) {
+      data = SegmentReader::CreateFromSkData(std::move(gainmap_image_data));
+      data_ = data;
+    } else {
       SetFailed();
       return;
     }
-    data = SegmentReader::CreateFromSkData(std::move(gainmap_image_data));
-    data_ = data;
   }
 
   if (reader_) {
@@ -1007,17 +1007,16 @@
   // TODO(crbug.com/356827770): This function will be removed once all decoders
   // rely on ImageDecoder::aux_image_ to decode the gainmap, instead of
   // extracting gainmap data.
-  sk_sp<SkData> base_image_data = data_->GetAsSkData();
+  auto base_image_data = data_->GetAsSkData();
   DCHECK(base_image_data);
-  sk_sp<SkData> gainmap_image_data;
-  SkGainmapInfo gainmap_info;
-  if (!metadata_decoder->findGainmapImage(base_image_data, gainmap_image_data,
-                                          gainmap_info)) {
-    return false;
+  if (auto [ok, gainmap_info] =
+          metadata_decoder->findGainmapImage(base_image_data);
+      ok) {
+    out_gainmap_info = gainmap_info;
+    out_gainmap_data = data_;
+    return true;
   }
-  out_gainmap_info = gainmap_info;
-  out_gainmap_data = data_;
-  return true;
+  return false;
 }
 
 bool JPEGImageDecoder::HasC2PAManifest() const {
diff --git a/third_party/blink/renderer/platform/image-decoders/segment_reader.cc b/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
index b72385c..0f0887a1 100644
--- a/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
+++ b/third_party/blink/renderer/platform/image-decoders/segment_reader.cc
@@ -69,7 +69,7 @@
       delete;
   size_t size() const override;
   base::span<const uint8_t> GetSomeData(size_t position) const override;
-  sk_sp<SkData> GetAsSkData() const override;
+  sk_sp<const SkData> GetAsSkData() const override;
 
  private:
   ~SharedBufferSegmentReader() override = default;
@@ -93,7 +93,7 @@
   return base::as_byte_span(*it);
 }
 
-sk_sp<SkData> SharedBufferSegmentReader::GetAsSkData() const {
+sk_sp<const SkData> SharedBufferSegmentReader::GetAsSkData() const {
   sk_sp<SkData> data = SkData::MakeUninitialized(shared_buffer_->size());
   auto buffer = skia::as_writable_byte_span(*data);
   for (const auto& span : *shared_buffer_) {
@@ -107,19 +107,19 @@
 // Interface for ImageDecoder to read an SkData.
 class DataSegmentReader final : public SegmentReader {
  public:
-  explicit DataSegmentReader(sk_sp<SkData>);
+  explicit DataSegmentReader(sk_sp<const SkData>);
   DataSegmentReader(const DataSegmentReader&) = delete;
   DataSegmentReader& operator=(const DataSegmentReader&) = delete;
   size_t size() const override;
   base::span<const uint8_t> GetSomeData(size_t position) const override;
-  sk_sp<SkData> GetAsSkData() const override;
+  sk_sp<const SkData> GetAsSkData() const override;
 
  private:
   ~DataSegmentReader() override = default;
-  sk_sp<SkData> data_;
+  sk_sp<const SkData> data_;
 };
 
-DataSegmentReader::DataSegmentReader(sk_sp<SkData> data)
+DataSegmentReader::DataSegmentReader(sk_sp<const SkData> data)
     : data_(std::move(data)) {}
 
 size_t DataSegmentReader::size() const {
@@ -134,7 +134,7 @@
   return skia::as_byte_span(*data_).subspan(position);
 }
 
-sk_sp<SkData> DataSegmentReader::GetAsSkData() const {
+sk_sp<const SkData> DataSegmentReader::GetAsSkData() const {
   return data_;
 }
 
@@ -148,7 +148,7 @@
 
   size_t size() const override;
   base::span<const uint8_t> GetSomeData(size_t position) const override;
-  sk_sp<SkData> GetAsSkData() const override;
+  sk_sp<const SkData> GetAsSkData() const override;
 
  private:
   ~ROBufferSegmentReader() override = default;
@@ -197,7 +197,7 @@
   static_cast<ROBuffer*>(context)->Release();
 }
 
-sk_sp<SkData> ROBufferSegmentReader::GetAsSkData() const {
+sk_sp<const SkData> ROBufferSegmentReader::GetAsSkData() const {
   if (!ro_buffer_) {
     return nullptr;
   }
@@ -226,7 +226,7 @@
 }
 
 scoped_refptr<SegmentReader> SegmentReader::CreateFromSkData(
-    sk_sp<SkData> data) {
+    sk_sp<const SkData> data) {
   return base::AdoptRef(new DataSegmentReader(std::move(data)));
 }
 
diff --git a/third_party/blink/renderer/platform/image-decoders/segment_reader.h b/third_party/blink/renderer/platform/image-decoders/segment_reader.h
index 329d408..d717d8a5 100644
--- a/third_party/blink/renderer/platform/image-decoders/segment_reader.h
+++ b/third_party/blink/renderer/platform/image-decoders/segment_reader.h
@@ -41,7 +41,7 @@
       scoped_refptr<const SharedBuffer>);
 
   // These versions use thread-safe input, so they are always thread-safe.
-  static scoped_refptr<SegmentReader> CreateFromSkData(sk_sp<SkData>);
+  static scoped_refptr<SegmentReader> CreateFromSkData(sk_sp<const SkData>);
   static scoped_refptr<SegmentReader> CreateFromROBuffer(
       scoped_refptr<ROBuffer>);
 
@@ -53,7 +53,7 @@
   // `position`. If there's no data at the specified `position`, an empty span
   // is returned.
   virtual base::span<const uint8_t> GetSomeData(size_t position) const = 0;
-  virtual sk_sp<SkData> GetAsSkData() const = 0;
+  virtual sk_sp<const SkData> GetAsSkData() const = 0;
   virtual void LockData() {}
   virtual void UnlockData() {}
 
diff --git a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
index 6c07320..d6f6c23 100644
--- a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
+++ b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.cc
@@ -111,7 +111,7 @@
 //
 // TODO(crbug.com/1009237): consider combining this with the logic to detect
 // WebPs that can be decoded to YUV.
-bool IsSimpleLossyWebPImage(const sk_sp<SkData>& blob) {
+bool IsSimpleLossyWebPImage(const sk_sp<const SkData>& blob) {
   if (blob->size() < 20UL) {
     return false;
   }
@@ -122,7 +122,7 @@
 
 // This method parses |blob|'s header and emits a UMA with the file format, as
 // defined by WebP, see WebPFileFormat.
-void UpdateWebPFileFormatUMA(const sk_sp<SkData>& blob) {
+void UpdateWebPFileFormatUMA(const sk_sp<const SkData>& blob) {
   if (!blink::IsMainThread()) {
     return;
   }
diff --git a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
index a73f706..c7541de 100644
--- a/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
+++ b/third_party/blink/renderer/platform/image-decoders/webp/webp_image_decoder.h
@@ -122,7 +122,7 @@
   // - the SegmentReader's data, if contiguous.
   // - its own copy, if not, and all data was received initially.
   // - |buffer_|, if streaming.
-  sk_sp<SkData> consolidated_data_;
+  sk_sp<const SkData> consolidated_data_;
   Vector<char> buffer_;
 };
 
diff --git a/third_party/blink/renderer/platform/privacy_budget/DEPS b/third_party/blink/renderer/platform/privacy_budget/DEPS
deleted file mode 100644
index 1ab27ec..0000000
--- a/third_party/blink/renderer/platform/privacy_budget/DEPS
+++ /dev/null
@@ -1,12 +0,0 @@
-include_rules = [
-    # Don't depend on platform/.
-    "-third_party/blink/renderer/platform",
-
-    # Module.
-    "+third_party/blink/renderer/platform/privacy_budget",
-
-    # Dependencies.
-    "+third_party/blink/public/common/privacy_budget",
-    "+third_party/blink/renderer/platform/platform_export.h",
-    "+third_party/blink/renderer/platform/wtf",
-]
diff --git a/third_party/blink/renderer/platform/privacy_budget/DIR_METADATA b/third_party/blink/renderer/platform/privacy_budget/DIR_METADATA
deleted file mode 100644
index 6d362b2..0000000
--- a/third_party/blink/renderer/platform/privacy_budget/DIR_METADATA
+++ /dev/null
@@ -1 +0,0 @@
-mixins: "//third_party/blink/public/common/privacy_budget/COMMON_METADATA"
diff --git a/third_party/blink/renderer/platform/privacy_budget/OWNERS b/third_party/blink/renderer/platform/privacy_budget/OWNERS
deleted file mode 100644
index dc54869..0000000
--- a/third_party/blink/renderer/platform/privacy_budget/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://third_party/blink/public/common/privacy_budget/OWNERS
diff --git a/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc b/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc
deleted file mode 100644
index e16b75f7..0000000
--- a/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.cc
+++ /dev/null
@@ -1,68 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h"
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h"
-#include "third_party/blink/renderer/platform/wtf/shared_buffer.h"
-#include "third_party/blink/renderer/platform/wtf/text/case_folding_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/string_hash.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-
-namespace blink {
-
-// Arbitrary value chosen to represent null strings.
-constexpr uint64_t kNullStringDigest = 6554271438612835841L;
-
-IdentifiableToken IdentifiabilityBenignStringToken(const String& in) {
-  if (in.IsNull())
-    return kNullStringDigest;
-
-  // Return the precomputed hash for the string. This makes this method O(1)
-  // instead of O(n), at the cost of only using the lower 32 bits of the hash.
-  return IdentifiableToken(GetHash(in));
-}
-
-IdentifiableToken IdentifiabilitySensitiveStringToken(const String& in) {
-  if (in.IsNull())
-    return IdentifiableToken(kNullStringDigest);
-
-  // Take the precomputed 32-bit hash, and xor the top and bottom halves to
-  // produce a 16-bit hash.
-  const uint32_t original_hash = GetHash(in);
-  return IdentifiableToken(((original_hash & 0xFFFF0000) >> 16) ^
-                           (original_hash & 0xFFFF));
-}
-
-IdentifiableToken IdentifiabilityBenignCaseFoldingStringToken(
-    const String& in) {
-  if (in.IsNull())
-    return kNullStringDigest;
-
-  return IdentifiableToken(CaseFoldingHash::GetHash(in));
-}
-
-IdentifiableToken IdentifiabilitySensitiveCaseFoldingStringToken(
-    const String& in) {
-  if (in.IsNull())
-    return IdentifiableToken(kNullStringDigest);
-
-  // Take the 32-bit hash, and xor the top and bottom halves to produce a 16-bit
-  // hash.
-  const uint32_t original_hash = CaseFoldingHash::GetHash(in);
-  return IdentifiableToken(((original_hash & 0xFFFF0000) >> 16) ^
-                           (original_hash & 0xFFFF));
-}
-
-IdentifiableToken IdentifiabilityBenignStringVectorToken(
-    const Vector<String>& in) {
-  IdentifiableTokenBuilder builder;
-  builder.AddValue(in.size());
-  for (const String& elem : in) {
-    builder.AddToken(IdentifiabilityBenignStringToken(elem));
-  }
-  return builder.GetToken();
-}
-
-}  // namespace blink
diff --git a/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h b/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h
deleted file mode 100644
index f687c82..0000000
--- a/third_party/blink/renderer/platform/privacy_budget/identifiability_digest_helpers.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRIVACY_BUDGET_IDENTIFIABILITY_DIGEST_HELPERS_H_
-#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRIVACY_BUDGET_IDENTIFIABILITY_DIGEST_HELPERS_H_
-
-#include "third_party/blink/public/common/privacy_budget/identifiable_token.h"
-#include "third_party/blink/renderer/platform/platform_export.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
-#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
-#include "third_party/blink/renderer/platform/wtf/vector.h"
-
-// Provide helpers for blink-internal types to use with IdentifiabilityToken()
-
-namespace blink {
-
-// For benign strings only (i.e. those where the string is not sensitive).
-PLATFORM_EXPORT IdentifiableToken
-IdentifiabilityBenignStringToken(const String&);
-
-// For sensitive strings, this function narrows the hash width to 16 bits.
-PLATFORM_EXPORT IdentifiableToken
-IdentifiabilitySensitiveStringToken(const String&);
-
-// For benign strings only (i.e. those where the string is not sensitive). Token
-// construction is additionally case-insensitive (using Unicode CaseFolding).
-PLATFORM_EXPORT IdentifiableToken
-IdentifiabilityBenignCaseFoldingStringToken(const String&);
-
-// For sensitive strings, this function narrows the hash width to 16 bits. Token
-// construction is additionally case-insensitive (using Unicode CaseFolding).
-PLATFORM_EXPORT IdentifiableToken
-IdentifiabilitySensitiveCaseFoldingStringToken(const String&);
-
-// For vectors of benign strings only (i.e. those where the string is not
-// sensitive).
-PLATFORM_EXPORT IdentifiableToken
-IdentifiabilityBenignStringVectorToken(const Vector<String>&);
-
-}  // namespace blink
-
-#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_PRIVACY_BUDGET_IDENTIFIABILITY_DIGEST_HELPERS_H_
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 1692e2c..5017ca03 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -5018,7 +5018,7 @@
     },
     {
       name: "SvgPartitionSVGDocumentResourcesInMemoryCache",
-      status: "stable",
+      status: "experimental",
     },
     {
       name: "SvgScriptElementAsyncAttribute",
diff --git a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
index c9fdbe5..fb2dffdb 100644
--- a/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
+++ b/third_party/blink/renderer/platform/webrtc/webrtc_video_frame_adapter.cc
@@ -383,8 +383,17 @@
     {
       // Blocking is necessary to create the GpuMemoryBuffer from this thread.
       base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
+      gfx::ColorSpace color_space = frame->ColorSpace();
+      // RGB formats will be converted to YUV, so original color space
+      // can't be used for scaled frame.
+      if (frame->format() == media::PIXEL_FORMAT_ARGB ||
+          frame->format() == media::PIXEL_FORMAT_ABGR ||
+          frame->format() == media::PIXEL_FORMAT_XRGB ||
+          frame->format() == media::PIXEL_FORMAT_XBGR) {
+        color_space = gfx::ColorSpace::CreateREC601();
+      }
       dst_frame = accelerated_frame_pool_->MaybeCreateVideoFrame(
-          frame->natural_size(), gfx::ColorSpace::CreateREC709());
+          frame->natural_size(), color_space);
     }
 
     if (dst_frame) {
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites
index 4960acd..75c94e8 100644
--- a/third_party/blink/web_tests/VirtualTestSuites
+++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -6034,6 +6034,7 @@
     "prefix": "xml-no-ext-entities",
     "platforms": ["Linux"],
     "bases": [
+      "external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces.svg",
       "fast/parser/external-entities-in-xslt.xml",
       "fast/xsl/dtd-in-source-document.xml",
       "fast/xsl/xslt-second-level-import.xml",
diff --git a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/border-shape/border-shape-overflow-solid-background.html b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/border-shape/border-shape-overflow-solid-background.html
index fe9539e..56ca775 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/border-shape/border-shape-overflow-solid-background.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-borders/tentative/border-shape/border-shape-overflow-solid-background.html
@@ -2,7 +2,7 @@
 <title>CSS Borders Shape: border-shape overscroll with solid background</title>
 <link rel="help" href="https://drafts.csswg.org/css-borders-4/#border-shape">
 <link rel="match" href="border-shape-overflow-solid-background-ref.html">
-<meta name=fuzzy content="0-200;0-300">
+<meta name=fuzzy content="0-200;0-360">
 <style>
   .bs-target {
     overflow-y: scroll;
diff --git a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml/the-canvas-state.yaml b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml/the-canvas-state.yaml
index ecd11b3..74e4a4a2 100644
--- a/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml/the-canvas-state.yaml
+++ b/third_party/blink/web_tests/external/wpt/html/canvas/tools/yaml/the-canvas-state.yaml
@@ -112,7 +112,7 @@
     ctx.save();
     ctx.{{ variant_names[1] }} = {{ value }};
     ctx.restore();
-    _assertSame(ctx.{{ variant_names[1] }}, old, "ctx.{{ variant_names[1] }}", "old");
+    @assert ctx.{{ variant_names[1] }} === old;
 
     // Also test that save() doesn't modify the values.
     ctx.{{ variant_names[1] }} = {{ value }};
@@ -120,7 +120,7 @@
     // We're not interested in failures caused by get(set(x)) != x (e.g.
     // from rounding), so compare against `old` instead of against {{ value }}.
     ctx.save();
-    _assertSame(ctx.{{ variant_names[1] }}, old, "ctx.{{ variant_names[1] }}", "old");
+    @assert ctx.{{ variant_names[1] }} === old;
     ctx.restore();
   variants_layout: [single_file, multi_files]
   variants:
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/checkable.html b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/checkable.html
index d801fa1b..e811c9e 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/checkable.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/checkable.html
@@ -26,6 +26,9 @@
     <menuitem id=multiple2></menuitem>
     <menuitem id=multiple3></menuitem>
   </fieldset>
+  <fieldset checkable=multiple>
+    <menuitem defaultchecked id=defaultCheckedItem>Default checked</menuitem>
+  </fieldset>
 </menulist>
 
 <script>
@@ -185,7 +188,7 @@
   single1.checked = true;
   assert_true(single1.checked, true);
   fieldset.removeAttribute('checkable');
-  assert_false(single1.checked, false,
+  assert_false(single1.checked,
       "menuitem gets unchecked after fieldset becomes uncheckable");
   single1.checked = true;
   assert_false(single1.checked,
@@ -206,4 +209,54 @@
   assert_false(single2.checked, "second menuitem becomes unchecked");
 }, "fieldset multiple => single; all but the first checked menuitem gets " +
    "reset");
+
+// Testing the `defaultchecked` content attribute and `defaultChecked` IDL
+// attribute.
+test(() => {
+  assert_true(defaultCheckedItem.checked,
+      "defaultchecked makes the menu item checked by default");
+  assert_true(defaultCheckedItem.matches(":default"),
+      ":default matches when the defaultchecked attribute is present");
+
+  // Unset the default while checkedness is still clean.
+  defaultCheckedItem.removeAttribute('defaultchecked');
+  assert_false(defaultCheckedItem.defaultChecked,
+      "defaultChecked IDL attribute reflects the content attribute");
+  assert_false(defaultCheckedItem.checked,
+      "Unsetting defaultchecked when checkedness is clean unchecks the item");
+  assert_false(defaultCheckedItem.matches(":default"),
+      ":default does not match when defaultchecked attribute is missing or false (1/2)");
+
+  // Toggle it again while checkedness is clean, but this time with the IDL
+  // attribute, which should reflect the content attribute.
+  defaultCheckedItem.defaultChecked = true;
+  assert_true(defaultCheckedItem.checked,
+      "Setting defaultChecked to true when checkedness is clean checks the item");
+  assert_true(defaultCheckedItem.matches(":default"),
+      ":default matches when the defaultchecked attribute is set, even via IDL");
+
+  // Unset checkedness, dirtying the default checkedness.
+  defaultCheckedItem.checked = false;
+  assert_true(defaultCheckedItem.defaultChecked,
+      "Default checkedness is still true");
+  assert_false(defaultCheckedItem.checked, "checked becomes false");
+  assert_true(defaultCheckedItem.matches(":default"),
+      "still matches the default checkedness");
+
+  // Unset default checkedness. This will only have the effect of changing the
+  // :default pseudo-class matching.
+  defaultCheckedItem.defaultChecked = false;
+  assert_false(defaultCheckedItem.matches(":default"),
+      ":default no longer matches");
+
+  // Set default checkedness back to true. Since the checkedness is now dirty,
+  // this won't change the actual checked state anymore, as the menu item has
+  // had its default checkedness overridden.
+  defaultCheckedItem.defaultChecked = true;
+  assert_false(defaultCheckedItem.checked,
+      "checked state is no longer dictated by default checkedness any");
+  assert_true(defaultCheckedItem.matches(":default"),
+      ":default matches again, following the default checkedness, even " +
+      "though the checkedness is dirty");
+}, "Default checkedness and checkedness dirtying are wired up correctly");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html
index 4476806..e58c7ad 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/focus-menu-elements-arrowoperations.html
@@ -7,7 +7,7 @@
 <link rel=help href=https://open-ui.org/components/menu.explainer>
 
 <menubar>
- <menuitem id=btn commandfor="list" command="toggle-popover">Open</menuitem>
+ <menuitem id=btn commandfor="list" command="toggle-menu">Open</menuitem>
 </menubar>
 
 <menulist id="list">
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menubar-invoke-menulist.html b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menubar-invoke-menulist.html
index 4797be5..893b98c8 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menubar-invoke-menulist.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menubar-invoke-menulist.html
@@ -7,7 +7,7 @@
 <menubar>
   <menuitem id="menubaritem">More commands</menuitem>
   <menuitem>Command 2</menuitem>
-  <menuitem>Command 3</menuitem>
+  <menuitem id="opencheckable" commandfor="checkable" command="show-menu">Open checkable menu</menuitem>
 </menubar>
 
 <menulist id="more">
@@ -15,7 +15,7 @@
  <menuitem>Command 2</menuitem>
 </menulist>
 
-<menulist>
+<menulist id="checkable">
   <fieldset checkable>
     <menuitem id="checkable-menuitem">Show menu</menuitem>
   </fieldset>
@@ -130,6 +130,7 @@
 test(() => {
   assert_equals(checkableMenuitem.commandForElement,null,
    "To start, checkable item shouldn't be an invoker")
+  opencheckable.click(); // Open the menu
   checkableMenuitem.click();
   assert_true(checkableMenuitem.checked,
       "checkable menu item becomes checked");
@@ -143,15 +144,15 @@
   assert_false(menulist.matches(":popover-open"),
       "menulist no longer matches :popover-open");
 
-   // Being checkable causes sub-menu functionality to stop.
+   // Being a sub-menu invoker makes the item non-checkable.
   checkableMenuitem.command = "toggle-menu";
   checkableMenuitem.commandForElement = menulist;
   checkableMenuitem.click();
-  assert_true(checkableMenuitem.checked,
-      "checkable menu item that invokes a menu becomes checked");
-  assert_false(menulist.matches(":popover-open"), "menulist is not open");
+  assert_false(checkableMenuitem.checked,
+      "checkable menu item that invokes a menu is not checkable");
+  assert_true(menulist.matches(":popover-open"), "menulist is open");
   checkableMenuitem.click();
-  assert_false(checkableMenuitem.checked, "checkable menu item unchecks");
-  assert_false(menulist.matches(":popover-open"), "menulist still not open");
-}, "Checkable menuitems can still invoke menulist popovers");
+  assert_false(checkableMenuitem.checked, "still not checked");
+  assert_false(menulist.matches(":popover-open"), "menulist closes");
+}, "menuitems that invoke menulists cannot be checkable");
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menuitem-activate.html b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menuitem-activate.html
index 818ea9a1..5c8cb2d 100644
--- a/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menuitem-activate.html
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/menu/tentative/menuitem-activate.html
@@ -72,11 +72,14 @@
   assert_false(popover.matches(":popover-open"), "div popover starts closed");
   await test_driver.click(mainmenuitem2);
   assert_true(popover.matches(":popover-open"), "div popover opens");
+  assert_false(mainmenu.matches(":popover-open"), "mainmenu popover closes");
 
   // Close the popover.
-  await test_driver.click(mainmenuitem2);
+  await test_driver.click(menubarmenuitem);
   assert_false(popover.matches(":popover-open"), "div popover gets closed");
-  assert_true(mainmenu.matches(":popover-open"), "mainmenu still open");
+  assert_true(mainmenu.matches(":popover-open"), "mainmenu gets opened");
+  await test_driver.click(menubarmenuitem);
+  assert_false(mainmenu.matches(":popover-open"), "mainmenu gets closed");
 }, 'User menuitem activation works with show-popover command');
 
 promise_test(async (t) => {
@@ -121,51 +124,71 @@
 }, 'Menulist inside a popover works correctly; does not get accidentally ' +
    'dismissed by opening submenus');
 
+async function getCoords(invoker, invokee) {
+  // test_driver isn't suited to mousedown-drag-mouseup interactions when the
+  // mousedown triggers visibility of one of the elements.
+  await clickOn(invoker);
+  const menulist = invokee.parentElement;
+  assert_true(menulist.matches(":popover-open"), "menulist popover opens when clicked");
+  let rect = invokee.getBoundingClientRect();
+  let coords = {x: Math.round(rect.x + rect.width / 2),
+      y: Math.round(rect.y + rect.height / 2)};
+  await test_driver.click(invoker);
+  assert_false(menulist.matches(":popover-open"), "menulist popover closes when clicked");
+  return coords;
+}
+
 promise_test(async (t) => {
   assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed");
-  let clickCount = 0;
-  normalmenuitem.addEventListener('click',() => (++clickCount));
+  const normal_menu_coords = await getCoords(menubarmenuitem, normalmenuitem);
+  let invokerClicks = 0;
+  let itemClicks = 0;
+  menubarmenuitem.addEventListener('click',() => (++invokerClicks));
+  normalmenuitem.addEventListener('click',() => (++itemClicks));
+  let openStateAfterPointerdown = "none";
+  menubarmenuitem.addEventListener('pointermove',() => {
+    // There will be two move events, one before the pointerdown and one after.
+    // Just capture the one after.
+    if (openStateAfterPointerdown === "none") {
+      openStateAfterPointerdown = "first-move";
+    } else if (openStateAfterPointerdown === "first-move") {
+      openStateAfterPointerdown = mainmenu.matches(":popover-open") ? "open" : "closed";
+    }
+  },{signal: t.get_signal()});
   await new test_driver.Actions()
     .addPointer('mouse', 'mouse')
     .pointerMove(0, 0, {origin: menubarmenuitem})
     .pointerDown()
-    .send();
-  await waitForRender();
-  assert_true(mainmenu.matches(":popover-open"), "mainmenu popover should be open while mouse is down");
-  assert_equals(clickCount,0, "no clicks yet");
-  await new test_driver.Actions()
-    .addPointer('mouse', 'mouse')
-    .pointerMove(0, 0, {origin: normalmenuitem})
+    // Extra move to trigger event on menubarmenuitem:
+    .pointerMove(2, 2, {origin: menubarmenuitem})
+    // This is the center of normalmenuitem:
+    .pointerMove(normal_menu_coords.x, normal_menu_coords.y, {})
     .pointerUp()
     .send();
   await waitForRender();
-  assert_false(mainmenu.matches(":popover-open"), "mainmenu popover should be closed");
-  // TODO: Menu items should fire an event when they are selected.
-  // The `click` event is not enough, because one won't be fired here.
-  // assert_equals(clickCount,1, "the sub-menu item should have been clicked");
+  assert_equals(openStateAfterPointerdown,"open", "mainmenu popover should open after pointer down");
+  assert_false(mainmenu.matches(":popover-open"), "mainmenu popover should be closed after interaction");
+  assert_equals(invokerClicks,0, "the invoking menu didn't get a click");
+  // TODO: Menu items should fire a click event when they are selected.
+  // assert_equals(itemClicks,1, "the invoked menu did get a click");
 }, 'A mousedown-drag-mouseup gesture on a normal menuitem picks the item');
 
 promise_test(async (t) => {
   assert_false(mainmenu.matches(":popover-open"), "mainmenu popover starts closed");
   assert_false(submenu.matches(":popover-open"), "submenu popover starts closed");
+  const main_menu_coords = await getCoords(menubarmenuitem, mainmenuitem);
   await new test_driver.Actions()
     .addPointer('mouse', 'mouse')
     .pointerMove(0, 0, {origin: menubarmenuitem})
     .pointerDown()
-    .send();
-  await waitForRender();
-  assert_true(mainmenu.matches(":popover-open"), "mainmenu popover should be open while mouse is down");
-  assert_false(submenu.matches(":popover-open"), "submenu shouldn't be open yet");
-  await new test_driver.Actions()
-    .addPointer('mouse', 'mouse')
-    .pointerMove(0, 0, {origin: mainmenuitem})
+    // This is the center of mainmenuitem:
+    .pointerMove(main_menu_coords.x, main_menu_coords.y, {})
     .pointerUp()
     .send();
   await waitForRender();
   assert_true(mainmenu.matches(":popover-open"), "mainmenu popover should remain open, because submenu chosen");
   assert_true(submenu.matches(":popover-open"), "submenu popover should be open");
-  menubarmenuitem.click(); // Cleanup.
-  await waitForRender();
+  await clickOn(menubarmenuitem); // Cleanup.
   assert_false(mainmenu.matches(":popover-open"), "mainmenu popover should be closed");
   assert_false(submenu.matches(":popover-open"), "submenu popover should be closed");
 }, 'A mousedown-drag-mouseup gesture on a submenu item leaves both menus open');
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/precise-attribute-changed.html b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/precise-attribute-changed.html
new file mode 100644
index 0000000..883fb4b
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/permission-element/precise-attribute-changed.html
@@ -0,0 +1,53 @@
+<!doctype html>
+<html>
+  <head>
+    <meta charset="utf-8" />
+    <title>Permission Element: invalid if precise attribute is changed</title>
+    <link rel="help" href="https://github.com/WICG/PEPC/blob/main/explainer.md" />
+    <script src="/resources/testharness.js"></script>
+    <script src="/resources/testharnessreport.js"></script>
+  </head>
+  <body>
+    <script>
+      promise_test(async (t) => {
+        let is_element_valid = false;
+        const element = document.createElement("permission");
+        element.setAttribute("type", "geolocation");
+        element.onvalidationstatuschange = t.step_func(() => {
+          if (element.invalidReason == "") {
+            is_element_valid = true;
+          }
+          if ( element.invalidReason == "attribute_changed" ||
+              element.invalidReason == "intersection_changed") {
+            is_element_valid = false;
+          }
+        });
+        document.body.appendChild(element);
+
+        await t.step_wait(() => is_element_valid === true, "Wait for the element to be ready.");
+
+        // setting the preciselocation attribute should temporarily disable the element.
+        element.setAttribute("preciselocation", "");
+        await t.step_wait(
+          () => is_element_valid === false,
+          "Element should become invalid after preciselocation is set.",
+        );
+        await t.step_wait(
+          () => is_element_valid === true,
+          "Element should automatically become valid again after 500ms after the attribute is set.",
+        );
+
+        // uusetting the preciselocation attribute should temporarily disable the element.
+        element.removeAttribute("preciselocation");
+        await t.step_wait(
+          () => is_element_valid === false,
+          "Element should become invalid after preciselocation is unset.",
+        );
+        await t.step_wait(
+          () => is_element_valid === true,
+          "Element should automatically become valid again after 500ms after the attribute is unset.",
+        );
+      }, "Permission element is invalid temporarily if the precise attribute is changed.");
+    </script>
+  </body>
+</html>
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces-expected.txt b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces-expected.txt
deleted file mode 100644
index bae1c55..0000000
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces-expected.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-This is a testharness.js-based test.
-[FAIL] unsetting default namespace works inside parse of fragment (on element)
-  assert_equals: expected (object) null but got (string) "http://www.w3.org/2000/svg"
-[FAIL] unsetting default namespace works inside parse of fragment (on child of element)
-  assert_equals: expected (object) null but got (string) "http://www.w3.org/2000/svg"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces.svg b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces.svg
index fb1a086..2317ddc20 100644
--- a/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces.svg
+++ b/third_party/blink/web_tests/external/wpt/html/webappapis/dynamic-markup-insertion/the-innerhtml-property/innerhtml-and-xml-namespaces.svg
@@ -80,6 +80,12 @@
       }, "unsetting default namespace works inside parse of fragment (on child of element)");
 
       test(() => {
+        prefixedContainer.innerHTML = "<e><f xmlns=''><g></g></f><h/></e>";
+        assert_equals(prefixedContainer.firstChild.firstChild.firstChild.namespaceURI, null);
+        assert_equals(prefixedContainer.firstChild.lastChild.namespaceURI, SVG_NS);
+      }, "default namespace applied to sibling of namespace-resetting element in parse of fragment.");
+
+      test(() => {
         prefixedContainer.innerHTML = "<e><h:f xmlns:h='https://example.com/new-h'><g><h:d></h:d></g></h:f></e>";
         assert_equals(prefixedContainer.firstChild.firstChild.namespaceURI, "https://example.com/new-h");
         assert_equals(prefixedContainer.firstChild.firstChild.firstChild.namespaceURI, SVG_NS);
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context-expected.txt
new file mode 100644
index 0000000..cadeb5f
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context-expected.txt
@@ -0,0 +1,4 @@
+Verify that Target.exposeDevToolsProtocol scoped to the default execution context.
+Protocol exposed to foo. Expected: false. Actual: false.
+Protocol exposed to default execution context. Expected: true. Actual: true.
+
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context.js
new file mode 100644
index 0000000..5a1362ae
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-expose-devtools-protocol-execution-context.js
@@ -0,0 +1,24 @@
+(async function(/** @type {import('test_runner').TestRunner} */ testRunner) {
+  const {page, session, dp} = await testRunner.startBlank(
+      'Verify that Target.exposeDevToolsProtocol scoped to the default execution context.');
+  await dp.Target.exposeDevToolsProtocol(
+      {targetId: page._targetId, bindingName: 'cdp'});
+
+  await dp.Runtime.enable();
+  dp.Page.createIsolatedWorld({frameId: page._targetId, worldName: 'foo'});
+  const contextFoo =
+      (await dp.Runtime.onceExecutionContextCreated()).params.context.id;
+
+  const isCdpExposedToFoo = await dp.Runtime.evaluate(
+      {expression: 'window.cdp!==undefined', contextId: contextFoo});
+  testRunner.log(`Protocol exposed to foo. Expected: false. Actual: ${
+      isCdpExposedToFoo.result.result.value}.`);
+
+  const isCdpExposedToDefault =
+      await dp.Runtime.evaluate({expression: 'window.cdp!==undefined'});
+  testRunner.log(
+      `Protocol exposed to default execution context. Expected: true. Actual: ${
+          isCdpExposedToDefault.result.result.value}.`);
+
+  testRunner.completeTest();
+})
diff --git a/third_party/blink/web_tests/virtual/rust-xml/fast/xmlhttprequest/xmlhttprequest-get-expected.txt b/third_party/blink/web_tests/virtual/rust-xml/fast/xmlhttprequest/xmlhttprequest-get-expected.txt
new file mode 100644
index 0000000..d050a89
--- /dev/null
+++ b/third_party/blink/web_tests/virtual/rust-xml/fast/xmlhttprequest/xmlhttprequest-get-expected.txt
@@ -0,0 +1,55 @@
+GET test
+responseText
+<?xml version="1.0"?>
+<!DOCTYPE doc [
+<!ATTLIST d id ID #IMPLIED>
+]>
+<doc>
+  <foo xmlns="foobar">One</foo> <x:bar xmlns:x="barfoo">Two</x:bar>
+  <d id="id3">Three</d>
+</doc>
+
+responseXML serialized
+<?xml version="1.0"?><!DOCTYPE doc><doc xmlns="">
+  <foo xmlns="foobar">One</foo> <x:bar xmlns:x="barfoo">Two</x:bar>
+  <d id="id3">Three</d>
+</doc>
+getAllResponseHeaders()
+content-type: text/xml
+last-modified: (date)
+
+status
+200
+statusText
+OK
+readyState
+4
+Event information
+Event object: [object ProgressEvent]
+Event properties:
+AT_TARGET : '2'
+BUBBLING_PHASE : '3'
+CAPTURING_PHASE : '1'
+NONE : '0'
+bubbles : 'false'
+cancelBubble : 'false'
+cancelable : 'false'
+composed : 'false'
+composedPath : 'function composedPath() { [native code] }'
+currentTarget : '[object XMLHttpRequest]'
+defaultPrevented : 'false'
+eventPhase : '2'
+initEvent : 'function initEvent() { [native code] }'
+isTrusted : 'true'
+lengthComputable : 'true'
+loaded : '0'
+preventDefault : 'function preventDefault() { [native code] }'
+pseudoTarget : 'null'
+returnValue : 'true'
+srcElement : '[object XMLHttpRequest]'
+stopImmediatePropagation : 'function stopImmediatePropagation() { [native code] }'
+stopPropagation : 'function stopPropagation() { [native code] }'
+target : '[object XMLHttpRequest]'
+total : '0'
+type : 'load'
+
diff --git a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
index c590d0d..0a2e1c5 100644
--- a/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/element-instance-property-listing-expected.txt
@@ -923,6 +923,7 @@
     property checked
     property command
     property commandForElement
+    property defaultChecked
     property disabled
 html element menulist
 html element meta
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 48a7181..e676bb54 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -4774,11 +4774,13 @@
     getter checked
     getter command
     getter commandForElement
+    getter defaultChecked
     getter disabled
     method constructor
     setter checked
     setter command
     setter commandForElement
+    setter defaultChecked
     setter disabled
 interface HTMLMenuListElement : HTMLElement
     attribute @@toStringTag
diff --git a/third_party/dawn b/third_party/dawn
index 518caee..fa54d1e 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 518caee86914cb4346f7f82a90c3ab99b7f84532
+Subproject commit fa54d1eaf3f0184b44aa243972dbbc2aac6ee02d
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 7d26bdd..6c0aaac 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 7d26bddc0d06cd6a294663fd23d0918e6ad33475
+Subproject commit 6c0aaacf6c509885ab267e5f7adb78252c2a386b
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium
index a6d90e3f..e630d618d8 100644
--- a/third_party/freetype/README.chromium
+++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@
 Name: FreeType
 URL: http://www.freetype.org/
-Version: VER-2-14-1-25-g32fc0af22
-Revision: 32fc0af22206327ffd06e1d025f13b11fd8d1a46
+Version: VER-2-14-1-27-g85161d762
+Revision: 85161d762262ce7a5bec3763e316d58f75c0b06e
 Update Mechanism: Manual
 CPEPrefix: cpe:/a:freetype:freetype:2.14.1
 License: FTL
diff --git a/third_party/freetype/src b/third_party/freetype/src
index 32fc0af..85161d7 160000
--- a/third_party/freetype/src
+++ b/third_party/freetype/src
@@ -1 +1 @@
-Subproject commit 32fc0af22206327ffd06e1d025f13b11fd8d1a46
+Subproject commit 85161d762262ce7a5bec3763e316d58f75c0b06e
diff --git a/third_party/perfetto b/third_party/perfetto
index f67fc0e..26c9830 160000
--- a/third_party/perfetto
+++ b/third_party/perfetto
@@ -1 +1 @@
-Subproject commit f67fc0ed0a168a0d80b35d07215c8fed2735d7d3
+Subproject commit 26c98304146c6bcbda4f96066dfecdd28040777d
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index d96e068..5775577 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit d96e0682f2c04a2e4b1d847c125d561a1a74e763
+Subproject commit 577557704db92682fbcb2d972d7bef783bf890f8
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index e1c92ec..b464a46 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit e1c92ec6cd2be77ef1fc2a0a0dabd432a1bccca7
+Subproject commit b464a4655348cba4b168f7da993633d57d300692
diff --git a/third_party/webrtc b/third_party/webrtc
index f680c18..b1e92cb 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit f680c1893f3b166b370439da52ae82d02f54969c
+Subproject commit b1e92cbead156841b29177be818b5aabbe194853
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml
index 37833ce0..acb7274 100644
--- a/tools/metrics/histograms/metadata/accessibility/histograms.xml
+++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -137,7 +137,7 @@
 
 <histogram name="Accessibility.Android.Cache.MaxNodesInCache" units="count"
     expires_after="2026-06-01">
-  <owner>mschillaci@google.com</owner>
+  <owner>aaronmoss@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
     Tracks the maximum number of AccessibilityNodeInfo objects that were stored
@@ -145,9 +145,21 @@
   </summary>
 </histogram>
 
+<histogram name="Accessibility.Android.Cache.PercentageFreshInCache" units="%"
+    expires_after="2026-06-01">
+  <owner>aaronmoss@google.com</owner>
+  <owner>chrome-a11y-core@google.com</owner>
+  <summary>
+    Tracks the percentage of calls from the Android framework serviced from
+    cache during a single session where the cached AccessibilityNodeInfo object
+    was still fresh. Only produced in the
+    AccessibilityCheckJavaNodeCacheFreshness experiment.
+  </summary>
+</histogram>
+
 <histogram name="Accessibility.Android.Cache.PercentageRetrievedFromCache"
     units="%" expires_after="2026-06-01">
-  <owner>mschillaci@google.com</owner>
+  <owner>aaronmoss@google.com</owner>
   <owner>chrome-a11y-core@google.com</owner>
   <summary>
     Tracks the percentage of calls from the Android framework to create a new
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 6b7dc74..df264ea 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -9054,52 +9054,59 @@
 
 <histogram name="Android.WebView.SupervisedUser.UrlCheckResult"
     enum="AndroidWebViewSupervisedUserUrlCheckResult"
-    expires_after="2025-08-01">
+    expires_after="2026-05-01">
   <owner>jdeabreu@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
   <summary>
     Records whether a given URL is allowed to be loaded by the current device
     user. This is based on a call to GMS Core, which checks if the url is
     allowed. This is recorded during each URL load, however only for the
-    resource types which undergo this type of URL check.
+    resource types which undergo this type of URL check. Note: This histogram
+    was expired between 2025-08-01 and 2025-12-02, data may be missing.
   </summary>
 </histogram>
 
 <histogram name="Android.WebView.SupervisedUser.UrlCheckTime" units="ms"
-    expires_after="2025-08-01">
+    expires_after="2026-05-01">
   <owner>jdeabreu@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
+  <improvement direction="LOWER_IS_BETTER"/>
   <summary>
     Records the time taken to return from the call to GMS Core that checks if a
     given URL is allowed to be loaded by the current device user. This is
     recorded during each URL load, however only for the resource types which
-    undergo this type of URL check.
+    undergo this type of URL check. Note: This histogram was expired between
+    2025-08-01 and 2025-12-02, data may be missing.
   </summary>
 </histogram>
 
 <histogram name="Android.WebView.SupervisedUser.UrlCheckTime.FirstRequest"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2026-05-01">
   <owner>jdeabreu@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
+  <improvement direction="LOWER_IS_BETTER"/>
   <summary>
     Records the time taken to return from the call to GMS Core that checks if a
     given URL is allowed to be loaded by the current device user. This metric is
     only recorded on the first call to GMS Core. This is recorded only for the
     first URL load, and only for the resource types which undergo this type of
-    URL check.
+    URL check. Note: This histogram was expired between 2025-08-01 and
+    2025-12-02, data may be missing.
   </summary>
 </histogram>
 
 <histogram name="Android.WebView.SupervisedUser.UrlCheckTime.SubsequentRequest"
-    units="ms" expires_after="2025-08-01">
+    units="ms" expires_after="2026-05-01">
   <owner>jdeabreu@chromium.org</owner>
   <owner>src/android_webview/OWNERS</owner>
+  <improvement direction="LOWER_IS_BETTER"/>
   <summary>
     Records the time taken to return from the call to GMS Core that checks if a
     given URL is allowed to be loaded by the current device user. This metric is
     not recorded on the first call, only on subsequent ones. This is recorded
     during each URL load after the initial load, however only for the resource
-    types which undergo this type of URL check.
+    types which undergo this type of URL check. Note: This histogram was expired
+    between 2025-08-01 and 2025-12-02, data may be missing.
   </summary>
 </histogram>
 
diff --git a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
index f31fe82b..090a5fed 100644
--- a/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
+++ b/tools/metrics/histograms/metadata/attribution_reporting/histograms.xml
@@ -217,7 +217,7 @@
 </histogram>
 
 <histogram name="Conversions.AggregatableReport.{ContextType}ExtraReportDelay"
-    units="ms" expires_after="2026-01-11">
+    units="ms" expires_after="2026-06-01">
   <owner>linnan@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
   <summary>
@@ -1051,7 +1051,7 @@
 </histogram>
 
 <histogram name="Conversions.ValidReportsInDatabase" units="Reports"
-    expires_after="2026-01-04">
+    expires_after="2026-06-01">
   <owner>tquintanilla@chromium.org</owner>
   <owner>apaseltiner@chromium.org</owner>
   <owner>measurement-api-dev+metrics@google.com</owner>
@@ -1087,21 +1087,6 @@
       variants="AttributionReportingAggregatableContextType"/>
 </histogram>
 
-<histogram name="Conversions.{ReportType}.ReportBodySize" units="bytes"
-    expires_after="2026-01-11">
-  <owner>linnan@chromium.org</owner>
-  <owner>measurement-api-dev+metrics@google.com</owner>
-  <summary>
-    Records the uncompressed size of non-debug attribution report request
-    bodies. Recorded for each sent event-level and aggregatable attribution
-    report.
-  </summary>
-  <token key="ReportType">
-    <variant name="AggregatableReport"/>
-    <variant name="EventLevelReport"/>
-  </token>
-</histogram>
-
 <histogram name="Conversions.{ReportType}.ReportRetriesTillSuccessOrFailure2"
     enum="ConversionReportSendRetryCount" expires_after="2026-04-26">
   <owner>tquintanilla@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml
index 1288281f..763f6d4 100644
--- a/tools/metrics/histograms/metadata/blink/enums.xml
+++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -8218,6 +8218,7 @@
   <int value="6" label="Intersection with viewport changed"/>
   <int value="7" label="Intersection visiblity out of viewport or clipped"/>
   <int value="8" label="Intersection visiblity occluded or distorted"/>
+  <int value="9" label="An attribute changed"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/renderer/core/html/html_permission_element.h:UserInteractionDeniedReason) -->
diff --git a/tools/metrics/histograms/metadata/kiosk/histograms.xml b/tools/metrics/histograms/metadata/kiosk/histograms.xml
index 1c4bc126..37b0db4 100644
--- a/tools/metrics/histograms/metadata/kiosk/histograms.xml
+++ b/tools/metrics/histograms/metadata/kiosk/histograms.xml
@@ -53,16 +53,6 @@
   </summary>
 </histogram>
 
-<histogram name="Kiosk.ChromeApp.PrimaryAppInSessionUpdate" units="times"
-    expires_after="2025-06-15">
-  <owner>yixie@chromium.org</owner>
-  <owner>chromeos-kiosk-eng@google.com</owner>
-  <summary>
-    ChromeOS only. Records count of in-session updates of primary Kiosk Chrome
-    app. A forced restart is scheduled in 24 hours.
-  </summary>
-</histogram>
-
 <histogram name="Kiosk.ChromeApp.PrimaryAppUpdateResult"
     enum="KioskPrimaryAppDownloadResult" expires_after="2026-02-22">
   <owner>yixie@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/net/enums.xml b/tools/metrics/histograms/metadata/net/enums.xml
index 5f643d41..ae649dfc 100644
--- a/tools/metrics/histograms/metadata/net/enums.xml
+++ b/tools/metrics/histograms/metadata/net/enums.xml
@@ -2956,6 +2956,16 @@
   <int value="9" label="TooBigDictionary"/>
 </enum>
 
+<!-- LINT.IfChange(SharedDictionaryTransactionOutcome) -->
+
+<enum name="SharedDictionaryTransactionOutcome">
+  <int value="0" label="Dictionary Used (Brotli)"/>
+  <int value="1" label="Dictionary Used (Zstandard)"/>
+  <int value="2" label="Dictionary Not Used"/>
+</enum>
+
+<!-- LINT.ThenChange(//net/shared_dictionary/shared_dictionary_transaction_outcome.h:SharedDictionaryTransactionOutcome) -->
+
 <enum name="SkipCompletionPortOnSuccessOutcome">
   <int value="0"
       label="Not all available transport protocols return Installable File
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml
index 2df88ce..6972c1f 100644
--- a/tools/metrics/histograms/metadata/net/histograms.xml
+++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -7233,6 +7233,20 @@
   <token key="HostType" variants="HostType"/>
 </histogram>
 
+<histogram name="Net.SharedDictionary.Transaction.Outcome"
+    enum="SharedDictionaryTransactionOutcome" expires_after="2026-11-11">
+  <owner>wbjacksonjr@chromium.org</owner>
+  <owner>src/net/extras/shared_dictionary/OWNERS</owner>
+  <summary>
+    Tracks the outcome of a network transaction only when a matching shared
+    dictionary was found and advertised to the server in the request headers. It
+    is emitted after the server's response headers have been received. The
+    metric records whether the server actually used the dictionary for
+    compression, which type of compression was used, or whether it chose not to
+    use the dictionary.
+  </summary>
+</histogram>
+
 <histogram name="Net.SharedDictionaryManagerOnDisk.CacheMaxSize" units="MB"
     expires_after="2026-07-01">
   <owner>pmeenan@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml
index fc2c5a9..8623dab4 100644
--- a/tools/metrics/histograms/metadata/password/histograms.xml
+++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -3218,7 +3218,7 @@
 
 <histogram name="PasswordManager.PasswordSharingDesktop.UserAction"
     enum="PasswordManager.PasswordSharingDesktopActions"
-    expires_after="2026-01-11">
+    expires_after="2026-08-11">
   <owner>natiahlyi@google.com</owner>
   <owner>mamir@chromium.org</owner>
   <owner>rgod@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/signin/enums.xml b/tools/metrics/histograms/metadata/signin/enums.xml
index e172d4e1..3df3b72 100644
--- a/tools/metrics/histograms/metadata/signin/enums.xml
+++ b/tools/metrics/histograms/metadata/signin/enums.xml
@@ -791,6 +791,7 @@
   <int value="76" label="Auth Service (Tasks Client)"/>
   <int value="77" label="YouTube Music"/>
   <int value="78" label="Contextual Tasks"/>
+  <int value="79" label="Enterprise Plus Address"/>
 </enum>
 
 <!-- LINT.ThenChange(//components/signin/public/base/oauth_consumer_id.h:OAuthConsumerId) -->
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml
index 530568b..949c5dd 100644
--- a/tools/metrics/histograms/metadata/webauthn/histograms.xml
+++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -72,7 +72,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.Android.CredManPrepareRequestDuration"
-    units="ms" expires_after="2026-01-12">
+    units="ms" expires_after="2026-07-12">
   <owner>derinel@google.com</owner>
   <owner>kenrb@chromium.org</owner>
   <summary>
@@ -216,7 +216,7 @@
 </histogram>
 
 <histogram name="WebAuthentication.Enclave.ChangePinEvents"
-    enum="ChangePinEvent" expires_after="2026-01-12">
+    enum="ChangePinEvent" expires_after="2026-07-12">
   <owner>derinel@google.com</owner>
   <owner>chrome-webauthn@google.com</owner>
   <summary>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 96c14d4..734ad6f 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@
         },
         "win": {
             "hash": "1ec53a0007bae76d4740a9cc5f2ab095540110cd",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/fca800884a32a9d79d299fd493d753301c6aeaf6/trace_processor_shell.exe"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/3149025ad5daae50463d5d19bb114eec4cd4fbb7/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "46d798c1864490cbb2ee053d6eda436184470e69",
@@ -22,7 +22,7 @@
         },
         "linux": {
             "hash": "c0ba75442d2cf6c53954b6d39145734521621c85",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/fca800884a32a9d79d299fd493d753301c6aeaf6/trace_processor_shell"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/3149025ad5daae50463d5d19bb114eec4cd4fbb7/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/display/ios/screen_ios.mm b/ui/display/ios/screen_ios.mm
index 9a4923f..ab9f46a5e 100644
--- a/ui/display/ios/screen_ios.mm
+++ b/ui/display/ios/screen_ios.mm
@@ -67,6 +67,24 @@
 namespace display {
 namespace {
 
+// Return all screens associated with scenes of the application.
+NSArray<UIScreen*>* GetAllActiveScreens() {
+#if BUILDFLAG(IS_IOS_APP_EXTENSION)
+  return [NSArray<UIScreen*> array];
+#else
+  NSMutableSet<UIScreen*>* screens = [NSMutableSet set];
+  for (UIScene* scene in UIApplication.sharedApplication.connectedScenes) {
+    auto* window_scene = base::apple::ObjCCastStrict<UIWindowScene>(scene);
+    for (UIWindow* window in window_scene.windows) {
+      if (UIScreen* screen = window.screen) {
+        [screens addObject:screen];
+      }
+    }
+  }
+  return [screens allObjects];
+#endif
+}
+
 class ScreenIos : public ScreenBase, public ScreenNotification {
  public:
   ScreenIos() {
@@ -140,24 +158,6 @@
   }
 
  private:
-  // Return all screens associated with scenes of the application.
-  NSArray<UIScreen*>* GetAllActiveScreens() const {
-#if BUILDFLAG(IS_IOS_APP_EXTENSION)
-    return [NSArray<UIScreen*> array];
-#else
-    NSMutableSet<UIScreen*>* screens = [NSMutableSet set];
-    for (UIScene* scene in UIApplication.sharedApplication.connectedScenes) {
-      UIWindowScene* windowScene =
-          base::apple::ObjCCastStrict<UIWindowScene>(scene);
-      UIScreen* screen = windowScene.keyWindow.screen;
-      if (screen) {
-        [screens addObject:screen];
-      }
-    }
-    return [screens allObjects];
-#endif
-  }
-
   ScreenObserver* __strong observer_;
 };
 
@@ -176,15 +176,8 @@
 #if BUILDFLAG(IS_IOS_APP_EXTENSION)
   return 1.0f;
 #else
-  for (UIScene* scene in UIApplication.sharedApplication.connectedScenes) {
-    UIWindowScene* windowScene =
-        base::apple::ObjCCastStrict<UIWindowScene>(scene);
-    UIScreen* screen = windowScene.keyWindow.screen;
-    if (screen) {
-      return [screen scale];
-    }
-  }
-  return 1.0f;
+  UIScreen* screen = GetAllActiveScreens().firstObject;
+  return screen ? screen.scale : 1.0f;
 #endif
 }
 
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index 4e54b04..701863c 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -921,6 +921,24 @@
   return platform_window()->GetBoundsInDIP();
 }
 
+void DesktopWindowTreeHostPlatform::OnVideoCaptureLockCreated() {
+  WindowTreeHostPlatform::OnVideoCaptureLockCreated();
+  has_video_capture_ = true;
+
+  if (GetWidget() && GetWidget()->IsMinimized()) {
+    SetVisible(true);
+  }
+}
+
+void DesktopWindowTreeHostPlatform::OnVideoCaptureLockDestroyed() {
+  WindowTreeHostPlatform::OnVideoCaptureLockDestroyed();
+  has_video_capture_ = false;
+
+  if (GetWidget() && GetWidget()->IsMinimized()) {
+    SetVisible(false);
+  }
+}
+
 void DesktopWindowTreeHostPlatform::OnCompositorVisibilityChanging(
     ui::Compositor* compositor,
     bool visible) {
@@ -975,7 +993,7 @@
   if (!aura::NativeWindowOcclusionTracker::
           IsNativeWindowOcclusionTrackingAlwaysEnabled(this) &&
       is_minimized != was_minimized) {
-    if (is_minimized) {
+    if (!has_video_capture_ && is_minimized) {
       SetVisible(false);
     } else {
       SetVisible(true);
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index 2e4802e..1a4bbb7 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -148,6 +148,9 @@
   gfx::Rect CalculateRootWindowBounds() const override;
   gfx::Rect GetBoundsInDIP() const override;
 
+  void OnVideoCaptureLockCreated() override;
+  void OnVideoCaptureLockDestroyed() override;
+
   // CompositorObserver:
   void OnCompositorVisibilityChanging(ui::Compositor* compositor,
                                       bool visible) override;
@@ -246,6 +249,8 @@
 
   bool is_active_ = false;
 
+  bool has_video_capture_ = false;
+
   std::u16string window_title_;
 
   // We can optionally have a parent which can order us to close, or own
diff --git a/v8 b/v8
index 80acc26..e858bb3 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit 80acc26727d5a34e77dabeebe7c9213ec1bd4768
+Subproject commit e858bb3a89e0b1e8f5fd701c5687a60de6b4964f