diff --git a/AUTHORS b/AUTHORS
index 38bed14..b5dae31 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -167,6 +167,7 @@
 Arun Kulkarni <kulkarni.a@samsung.com>
 Arun Kumar <arun87.kumar@samsung.com>
 Arun Mankuzhi <arun.m@samsung.com>
+Arunachalam G <arunachalam93g@gmail.com>
 Arunoday Sarkar <a.sarkar.arun@gmail.com>
 Arunprasad Rajkumar <ararunprasad@gmail.com>
 Arunprasad Rajkumar <arurajku@cisco.com>
@@ -1037,6 +1038,7 @@
 Minjeong Kim <deoxyribonucleicacid150@gmail.com>
 Minjeong Lee <apenr1234@gmail.com>
 Minseok Koo <kei98301@gmail.com>
+Minseop Choi <minsubb13@gmail.com>
 Minsoo Max Koo <msu.koo@samsung.com>
 Minsung Jin <m4ushold@gmail.com>
 Miran Karic <miran.karic@imgtec.com>
diff --git a/DEPS b/DEPS
index 38f105b..a447ace 100644
--- a/DEPS
+++ b/DEPS
@@ -299,15 +299,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '0d16b74f74a5018c20fdaa753b41103bb08d08fd',
+  'skia_revision': '84e461a91558ab09fa70d1c8076d08ac5348bb86',
   # 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': 'a46966388bbd892ee59d5d2688287704d1844302',
+  'v8_revision': '66ae14d8c1caeae3b2b64da4822d4f647b2d5cc7',
   # 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': 'b729fb74e68bb2b3db6c95067f4ffc1e0c25bc07',
+  'angle_revision': 'af4c3f9add49b4477ab429e8e5492930bca15877',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -319,7 +319,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling BoringSSL
   # and whatever else without interference from each other.
-  'boringssl_revision': 'f371c85a8d58bf911cba6073bcca6d497af81dc9',
+  'boringssl_revision': '45cab558a838e1a546391406e7cbe1eec9b6e643',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Fuchsia sdk
   # and whatever else without interference from each other.
@@ -371,7 +371,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '74f545d009ceef464f840938ae079ffbc112a102',
+  'catapult_revision': '168822b896c38f7d0079a2483c81f3d5cbc1d933',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling CrossBench
   # and whatever else without interference from each other.
@@ -391,7 +391,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': '6d3155a3c0b50687e4f417e19d4491e66d56ef3c',
+  'devtools_frontend_revision': 'a35ef623edc69b2863da7b1fd596b64160ff73f9',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -415,7 +415,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '19a7153574fe7506f098586a12ac21edf0944849',
+  'dawn_revision': '52a8b5a67e5c425a174cd6874a13b8b11fe190af',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -499,7 +499,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.
-  'libunwind_revision':    '81e2cb40a70de2b6978e6d8658891ded9a77f7e3',
+  'libunwind_revision':    '4acde988c52e6a325e3ce2ac761284f295f2ab39',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -519,7 +519,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'llvm_libc_revision':    'e3e030ec6ee1674bf2195d0cfd0a4bf5fee16537',
+  'llvm_libc_revision':    '61d7ed30110f97d6842304bc9035ee9cdae6b5e5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
@@ -1486,7 +1486,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '86901d8e9a33f78ccf07acfa57b63439e7cfa5f8',
+    '183abddd96aaf0dbb5b0c1e4e41a0f3999176462',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1645,7 +1645,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': '3f6bb_ds1Ab_INPp6lc8i778IRbWZSwVm2QBzfQFTMoC',
+          'version': '6oMBB-fWfNxprryb8ZyOcOKsrHEOYQzxe7DaKSjHx7cC',
       },
     ],
     'condition': 'checkout_android and non_git_source',
@@ -2840,7 +2840,7 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@9d021471f38e15ccd4d7087f4cf05292e6e671b0',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@72604f04b9576fcda814d388673d7530d95a9a5a',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@963588074b26326ff0426c8953c1235213309bdb',
   '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@6d0784e9f1ab92c17eeea94821b2465c14a52be9',
@@ -2849,7 +2849,7 @@
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@fefd7ed96ef9994f0080dbd078822b07d8637918',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@ba13d38d06830f714a93c5bb159e6e4bacacf0bc',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@be40e67892c83d4752ccfbee7ce690ea88087d2b',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@17cf8188d8b49bafb6c2f8ecede238f8d2dec5bf',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@6ae58a2b17b2bcebdc5377995007391b85ffa10f',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21',
@@ -2940,7 +2940,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': 'KN2IwZqaE82rq6fqVp3hdruYYJ84LUBLgOVTQRAGtOgC',
+          'version': 'XvA_7L7EBxuteX50DCEOF09vFmi3j5JjHZllbUAhrH0C',
         },
       ],
       'dep_type': 'cipd',
@@ -2950,7 +2950,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'LLNTOh1PJ9ZXVrdmwgWAf0KYOgZgQhfgaldCTjmg1c0C',
+          'version': 'sIE9gbPbfWS2wFcKfjLYZuqk2QbRwaQetYWH8FlaHWkC',
         },
       ],
       'dep_type': 'cipd',
@@ -2961,7 +2961,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': 'xo66yxZ-zTgqRnY5597wSJpk-3BX2OpElqzYg032slAC',
+          'version': 'B4z1WT_C_-NfLkHKjxtinLyNC_b3B7r9N_OvGVWhrdsC',
         },
       ],
       'dep_type': 'cipd',
@@ -2972,7 +2972,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-arm64',
-          'version': 'ujgOeYoS5cTXHy9h7j_PSg7YsGl9q9TmvkhaM22_Uh4C',
+          'version': 'Nflk7_lewYF5S6u_5uI4QONIXSORkjmS_JxwgEX9mFEC',
         },
       ],
       'dep_type': 'cipd',
@@ -3016,7 +3016,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/boca_app/app',
-        'version': 'N1iPTYt5ijzkWmHZWIguGMVPVXU1jBWJLdMHT6fvAj0C',
+        'version': 'sRBJTTmwZylqoIAy7UWy24wqp8cJ1FiE285X8AJs380C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -4662,7 +4662,7 @@
 
   'src/components/vector_icons/google_chrome': {
       'url': Var('chrome_git') + '/chrome/vector_icons/google_chrome.git' + '@' +
-        'ecad7931572c1f673bf582b785838daadbaadfab',
+        '61cf8b1548363c9573e5f3c5c5c4170e110edf81',
       'condition': 'checkout_src_internal',
   },
 
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 d8bce7d5..1cb7a05d 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
@@ -5540,6 +5540,7 @@
     getter onquotaoverflow
     getter temperature
     getter topK
+    method append
     method clone
     method constructor
     method destroy
diff --git a/build/toolchain/cros/get_resource_dir.py b/build/toolchain/cros/get_resource_dir.py
index 17acdbc8..ba74aa1 100755
--- a/build/toolchain/cros/get_resource_dir.py
+++ b/build/toolchain/cros/get_resource_dir.py
@@ -5,6 +5,7 @@
 """Script to get Clang's resource dir from `cros_target_cc`."""
 
 import argparse
+import os
 import subprocess
 import sys
 from typing import List
@@ -18,6 +19,9 @@
   parser.add_argument("cros_target_cc", help="The value of 'cros_target_cc'.")
   opts = parser.parse_args(argv)
 
+  # crbug.com/397463803: Add these so the compiler wrapper doesn't error
+  # out. Should be removable around Q4 2025.
+  os.environ["CROSTC_IS_AWARE_OF_THIS_USECASE"] = "1"
   sys.exit(
       subprocess.run(
           (opts.cros_target_cc, "--print-resource-dir"),
diff --git a/chrome/VERSION b/chrome/VERSION
index 7daacc8e..67626f5 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=138
 MINOR=0
-BUILD=7170
+BUILD=7171
 PATCH=0
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
index cba224e..62164ffc 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageService.java
@@ -213,8 +213,11 @@
                         Snackbar.UMA_INCOGNITO_REAUTH_ENABLED_FROM_PROMO);
         // TODO(crbug.com/40056462):  Confirm with UX to see how the background color of the
         // snackbar needs to be revised.
-        snackbar.setBackgroundColor(
-                mContext.getColor(R.color.snackbar_background_color_baseline_dark));
+        int snackbarBackgroundColor =
+                SnackbarManager.isFloatingSnackbarEnabled()
+                        ? mContext.getColor(R.color.floating_snackbar_background_incognito)
+                        : mContext.getColor(R.color.snackbar_background_color_baseline_dark);
+        snackbar.setBackgroundColor(snackbarBackgroundColor);
         snackbar.setTextAppearance(R.style.TextAppearance_TextMedium_Secondary_Baseline_Light);
         snackbar.setSingleLine(false);
         mSnackBarManager.showSnackbar(snackbar);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
index ebf0f719..f17f8de 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoReauthPromoMessageServiceUnitTest.java
@@ -342,8 +342,8 @@
         final String snackBarTestString = "This is written inside the snackbar.";
         when(mContextMock.getString(R.string.incognito_reauth_snackbar_text))
                 .thenReturn(snackBarTestString);
-        when(mContextMock.getColor(R.color.snackbar_background_color_baseline_dark))
-                .thenReturn(R.color.snackbar_background_color_baseline_dark);
+        when(mContextMock.getColor(R.color.floating_snackbar_background_incognito))
+                .thenReturn(R.color.floating_snackbar_background_incognito);
         doNothing().when(mSnackbarManagerMock).showSnackbar(mSnackbarArgumentCaptor.capture());
 
         IncognitoReauthPromoMessageService.setIsPromoEnabledForTesting(true);
@@ -357,7 +357,7 @@
         verify(mMessageObserverMock, times(1)).messageInvalidate(MessageType.FOR_TESTING);
 
         verify(mContextMock, times(1)).getString(R.string.incognito_reauth_snackbar_text);
-        verify(mContextMock, times(1)).getColor(R.color.snackbar_background_color_baseline_dark);
+        verify(mContextMock, times(1)).getColor(R.color.floating_snackbar_background_incognito);
         verify(mSnackbarManagerMock, times(1)).showSnackbar(mSnackbarArgumentCaptor.getValue());
 
         assertFalse(
diff --git a/chrome/android/java/res/layout/history_clear_browsing_data_header.xml b/chrome/android/java/res/layout/history_clear_browsing_data_header.xml
index eb9e37b2..7a52c07c3 100644
--- a/chrome/android/java/res/layout/history_clear_browsing_data_header.xml
+++ b/chrome/android/java/res/layout/history_clear_browsing_data_header.xml
@@ -25,9 +25,10 @@
             android:paddingEnd="@dimen/list_item_default_margin"
             android:gravity="center_vertical|start"
             android:text="@string/open_clear_browsing_data_dialog_button"
+            android:contentDescription="@string/open_clear_browsing_data_dialog_button_accessibility_description"
             app:verticalInset="0dp"
             style="@style/TextButton" />
 
         <View style="@style/HorizontalDivider" />
 
-</LinearLayout>
\ No newline at end of file
+</LinearLayout>
diff --git a/chrome/app/BUILD.gn b/chrome/app/BUILD.gn
index 9b4b553d..d9d9849 100644
--- a/chrome/app/BUILD.gn
+++ b/chrome/app/BUILD.gn
@@ -157,7 +157,7 @@
     "//ui/base",
     "//v8:v8_headers",
   ]
-  public_deps = []
+  public_deps = [ "//ui/lottie" ]
 
   if (is_android) {
     deps += [
@@ -191,7 +191,6 @@
       "//chromeos/ash/experiences/arc:arc_base_utils",
       "//chromeos/dbus/constants",
     ]
-    public_deps += [ "//ui/lottie" ]
   }
 
   if (use_ozone) {
diff --git a/chrome/app/chrome_main_delegate.cc b/chrome/app/chrome_main_delegate.cc
index 7cc74f59..bc71df65 100644
--- a/chrome/app/chrome_main_delegate.cc
+++ b/chrome/app/chrome_main_delegate.cc
@@ -106,6 +106,7 @@
 #include "ui/base/resource/resource_bundle.h"
 #include "ui/base/resource/scoped_startup_resource_bundle.h"
 #include "ui/base/ui_base_switches.h"
+#include "ui/lottie/resource.h"
 
 #if BUILDFLAG(IS_WIN)
 #include <malloc.h>
@@ -165,7 +166,6 @@
 #include "chromeos/ash/experiences/arc/arc_util.h"
 #include "chromeos/dbus/constants/dbus_paths.h"
 #include "content/public/common/content_features.h"
-#include "ui/lottie/resource.h"  // nogncheck
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
@@ -749,7 +749,7 @@
   const auto* invoked_in_browser =
       std::get_if<InvokedInBrowserProcess>(&invoked_in);
   if (!invoked_in_browser) {
-    CommonEarlyInitialization(invoked_in);
+    CommonEarlyInitialization();
     return std::nullopt;
   }
 
@@ -849,7 +849,7 @@
       ->ChromeProcessSingleton::InitializeFeatures();
 #endif
 
-  CommonEarlyInitialization(invoked_in);
+  CommonEarlyInitialization();
 
   // Initializes the resource bundle and determines the locale.
   std::string actual_locale = LoadLocalState(
@@ -930,7 +930,7 @@
 #endif
 }
 
-void ChromeMainDelegate::CommonEarlyInitialization(InvokedIn invoked_in) {
+void ChromeMainDelegate::CommonEarlyInitialization() {
   const base::CommandLine* const command_line =
       base::CommandLine::ForCurrentProcess();
   std::string process_type =
diff --git a/chrome/app/chrome_main_delegate.h b/chrome/app/chrome_main_delegate.h
index 18b33015..fa692d8f 100644
--- a/chrome/app/chrome_main_delegate.h
+++ b/chrome/app/chrome_main_delegate.h
@@ -81,7 +81,7 @@
   content::ContentUtilityClient* CreateContentUtilityClient() override;
 
   // Initialization that happens in all process types.
-  void CommonEarlyInitialization(InvokedIn invoked_in);
+  void CommonEarlyInitialization();
 
   // Initializes |tracing_sampler_profiler_|. Deletes any existing
   // |tracing_sampler_profiler_| as well.
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp
index ac6616bb..3b37407 100644
--- a/chrome/app/os_settings_strings.grdp
+++ b/chrome/app/os_settings_strings.grdp
@@ -785,6 +785,15 @@
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_CLEAR_PERSONALIZATION_DATA" desc="Label for a heading/button to clear persionalized data from the Japanese IME">
    Clear personalization data
   </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY" desc="Label for a dialog for users to confirm deletion of a user dictionary">
+   Delete this dictionary
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_DETAIL" desc="More detail confirming that the user wants to delete a particular user dictionary">
+   <ph name="dictionary">$1</ph> will be permanently deleted. This action can't be undone.
+  </message>
+  <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_BUTTON" desc="Button that will confirm deletion of user dictionary in Japanese IME">
+   Delete
+  </message>
   <message name="IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_ITEMS" desc="Label for a form for users to select the type of personalized data they wany to Delete">
    Delete the following items:
   </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY.png.sha1
new file mode 100644
index 0000000..b3a5326
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY.png.sha1
@@ -0,0 +1 @@
+45e8e9bd5c6eea5bf26017aab4d1be1a81a6c4da
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_BUTTON.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_BUTTON.png.sha1
new file mode 100644
index 0000000..b3a5326
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_BUTTON.png.sha1
@@ -0,0 +1 @@
+45e8e9bd5c6eea5bf26017aab4d1be1a81a6c4da
\ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_DETAIL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_DETAIL.png.sha1
new file mode 100644
index 0000000..b3a5326
--- /dev/null
+++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_DETAIL.png.sha1
@@ -0,0 +1 @@
+45e8e9bd5c6eea5bf26017aab4d1be1a81a6c4da
\ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index be7189c..32e6eb8 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -8438,6 +8438,7 @@
     "//services/network/public/mojom",
     "//services/screen_ai/buildflags",
     "//sql",
+    "//ui/lottie",
   ]
   if (is_android) {
     public_deps += [
@@ -8481,7 +8482,6 @@
       "//third_party/lens_server_proto:lens_overlay_proto",
       "//third_party/nearby:encrypted_metadata_proto",
       "//third_party/nearby:rpc_resources_proto",
-      "//ui/lottie",
     ]
   }
   if (is_win) {
diff --git a/chrome/browser/ai/ai_language_model.cc b/chrome/browser/ai/ai_language_model.cc
index a35d442..f32d6a9 100644
--- a/chrome/browser/ai/ai_language_model.cc
+++ b/chrome/browser/ai/ai_language_model.cc
@@ -347,6 +347,66 @@
   }
 }
 
+void AILanguageModel::AppendItemGetInputSizeCompletion(
+    std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+    mojo::Remote<blink::mojom::AILanguageModelAppendClient> client_remote,
+    std::optional<uint32_t> result) {
+  if (!client_remote.is_connected()) {
+    return;
+  }
+  if (!session_) {
+    // If the session is destroyed before this callback is invoked, we should
+    // not do anything further.
+    client_remote->OnError(
+        blink::mojom::ModelStreamingResponseStatus::kErrorSessionDestroyed);
+    return;
+  }
+
+  if (!result.has_value()) {
+    client_remote->OnError(
+        blink::mojom::ModelStreamingResponseStatus::kErrorRetryableError);
+    return;
+  }
+
+  Context::ContextItem item;
+  item.prompts = std::move(prompts);
+  item.tokens = result.value();
+  switch (context_->ReserveSpace(item.tokens)) {
+    case Context::SpaceReservationResult::kSufficientSpace:
+      context_->AddContextItem(std::move(item));
+      break;
+    case Context::SpaceReservationResult::kSpaceMadeAvailable:
+      client_remote->OnQuotaOverflow();
+      context_->AddContextItem(std::move(item));
+      break;
+    case Context::SpaceReservationResult::kInsufficientSpace:
+      client_remote->OnError(
+          blink::mojom::ModelStreamingResponseStatus::kErrorInputTooLarge);
+      return;
+  }
+
+  // TODO(crbug.com/409355678): currently the append cannot be aborted once it's
+  // sent to the `session_`, we should improve this so the `SetInput` call can
+  // be cancelled.
+  session_->SetInput(
+      context_->MakeRequest(session_->GetCapabilities()),
+      base::BindOnce(
+          [](mojo::Remote<blink::mojom::AILanguageModelAppendClient>
+                 client_remote,
+             base::expected<
+                 size_t,
+                 optimization_guide::OptimizationGuideModelExecutionError>
+                 result) {
+            if (!result.has_value()) {
+              client_remote->OnError(
+                  AIUtils::ConvertModelExecutionError(result.error().error()));
+            } else {
+              client_remote->OnAppendComplete();
+            }
+          },
+          std::move(client_remote)));
+}
+
 void AILanguageModel::PromptGetInputSizeCompletion(
     mojo::RemoteSetElementId responder_id,
     Context::ContextItem current_item,
@@ -427,6 +487,28 @@
                      std::move(item), std::move(constraint)));
 }
 
+void AILanguageModel::Append(
+    std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+    mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient> client) {
+  // Build the request to calculate the token size, the prompts will only be
+  // added to the context in the completion callback.
+  MultimodalMessage request = EmptyMessage();
+  for (auto& prompt : prompts) {
+    AddPromptToField(*prompt,
+                     request.edit().MutableRepeatedField(
+                         PromptApiRequest::kPromptHistoryFieldNumber),
+                     session_->GetCapabilities());
+  }
+
+  mojo::Remote<blink::mojom::AILanguageModelAppendClient> client_remote(
+      std::move(client));
+  session_->GetContextSizeInTokens(
+      request.read(),
+      base::BindOnce(&AILanguageModel::AppendItemGetInputSizeCompletion,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(prompts),
+                     std::move(client_remote)));
+}
+
 void AILanguageModel::Fork(
     mojo::PendingRemote<blink::mojom::AIManagerCreateLanguageModelClient>
         client) {
diff --git a/chrome/browser/ai/ai_language_model.h b/chrome/browser/ai/ai_language_model.h
index 03bf7aa..dae537a 100644
--- a/chrome/browser/ai/ai_language_model.h
+++ b/chrome/browser/ai/ai_language_model.h
@@ -130,6 +130,9 @@
               on_device_model::mojom::ResponseConstraintPtr constraint,
               mojo::PendingRemote<blink::mojom::ModelStreamingResponder>
                   pending_responder) override;
+  void Append(std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+              mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient>
+                  client) override;
   void Fork(
       mojo::PendingRemote<blink::mojom::AIManagerCreateLanguageModelClient>
           client) override;
@@ -151,6 +154,10 @@
   mojo::PendingRemote<blink::mojom::AILanguageModel> TakePendingRemote();
 
  private:
+  void AppendItemGetInputSizeCompletion(
+      std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+      mojo::Remote<blink::mojom::AILanguageModelAppendClient> client,
+      std::optional<uint32_t> result);
   void PromptGetInputSizeCompletion(
       mojo::RemoteSetElementId responder_id,
       Context::ContextItem current_item,
diff --git a/chrome/browser/ai/ai_language_model_unittest.cc b/chrome/browser/ai/ai_language_model_unittest.cc
index b2ee121..de6961d 100644
--- a/chrome/browser/ai/ai_language_model_unittest.cc
+++ b/chrome/browser/ai/ai_language_model_unittest.cc
@@ -14,6 +14,7 @@
 #include "base/functional/callback_forward.h"
 #include "base/functional/callback_helpers.h"
 #include "base/notreached.h"
+#include "base/run_loop.h"
 #include "base/strings/strcat.h"
 #include "base/strings/stringprintf.h"
 #include "base/task/current_thread.h"
@@ -85,6 +86,9 @@
      "M: I'm fine, thank you, and you?\n"
      "U: I'm fine too.\n");
 
+const char kTestAppendPrompt[] = "Test append prompt";
+const char kExpectedFormattedAppendPrompt[] = "U: Test append prompt\n";
+
 SkBitmap CreateTestBitmap(int width, int height) {
   SkBitmap bitmap;
   bitmap.allocN32Pixels(width, height);
@@ -1057,6 +1061,109 @@
   run_loop.Run();
 }
 
+TEST_F(AILanguageModelTest, Append) {
+  SetupMockOptimizationGuideKeyedService();
+  EXPECT_CALL(*mock_optimization_guide_keyed_service_, StartSession(_, _))
+      .WillOnce([&](optimization_guide::ModelBasedCapabilityKey feature,
+                    const std::optional<
+                        optimization_guide::SessionConfigParams>&
+                        config_params) {
+        auto session = std::make_unique<
+            testing::NiceMock<optimization_guide::MockSession>>();
+
+        SetUpMockSession(*session);
+
+        ON_CALL(*session, GetContextSizeInTokens(_, _))
+            .WillByDefault(
+                [&](MultimodalMessageReadView request_metadata,
+                    optimization_guide::
+                        OptimizationGuideModelSizeInTokenCallback callback) {
+                  std::move(callback).Run(1);
+                });
+        ON_CALL(*session, SetInput(_, _))
+            .WillByDefault(
+                [&, is_append = true](MultimodalMessage request_metadata,
+                                      SetInputCallback callback) mutable {
+                  if (is_append) {
+                    is_append = false;
+                    EXPECT_THAT(ToString(request_metadata),
+                                kExpectedFormattedAppendPrompt);
+                    std::move(callback).Run(1ul);
+                  } else {
+                    EXPECT_THAT(ToString(request_metadata),
+                                base::StrCat({kExpectedFormattedAppendPrompt,
+                                              kExpectedFormattedTestPrompt}));
+                  }
+                });
+
+        EXPECT_CALL(*session, ExecuteModelWithResponseConstraint(_, _, _))
+            .WillOnce(
+                [&](const google::protobuf::MessageLite& request_metadata,
+                    on_device_model::mojom::ResponseConstraintPtr constraint,
+                    optimization_guide::
+                        OptimizationGuideModelExecutionResultStreamingCallback
+                            callback) {
+                  EXPECT_THAT(request_metadata.ByteSizeLong(), 0);
+                  callback.Run(
+                      CreateExecutionResult("OK", /*is_complete=*/true,
+                                            /*input_token_count=*/1u,
+                                            /*output_token_count=*/1u));
+                });
+        return session;
+      });
+
+  base::test::TestFuture<mojo::PendingRemote<blink::mojom::AILanguageModel>>
+      session_future;
+  AITestUtils::MockCreateLanguageModelClient mock_create_language_model_client;
+
+  EXPECT_CALL(mock_create_language_model_client, OnResult(_, _))
+      .WillOnce(
+          [&](mojo::PendingRemote<blink::mojom::AILanguageModel> language_model,
+              blink::mojom::AILanguageModelInstanceInfoPtr info) {
+            EXPECT_TRUE(language_model);
+            EXPECT_EQ(info->input_quota,
+                      AITestUtils::GetFakeTokenLimits().max_context_tokens);
+            EXPECT_EQ(info->input_usage, 0ul);
+            session_future.SetValue(
+                mojo::PendingRemote<blink::mojom::AILanguageModel>(
+                    std::move(language_model)));
+          });
+
+  mojo::Remote<blink::mojom::AIManager> mock_remote = GetAIManagerRemote();
+
+  mock_remote->CreateLanguageModel(
+      mock_create_language_model_client.BindNewPipeAndPassRemote(),
+      blink::mojom::AILanguageModelCreateOptions::New(
+          /*sampling_params=*/nullptr,
+          /*initial_prompts=*/
+          std::vector<blink::mojom::AILanguageModelPromptPtr>(),
+          /*expected_inputs=*/std::nullopt));
+
+  auto mock_responder = std::make_unique<
+      testing::NiceMock<AITestUtils::MockModelStreamingResponder>>();
+  base::RunLoop responder_run_loop;
+  EXPECT_CALL(*mock_responder, OnCompletion(_))
+      .WillOnce(testing::Invoke(
+          [&](blink::mojom::ModelExecutionContextInfoPtr context_info) {
+            responder_run_loop.Quit();
+          }));
+  auto mock_append_client = std::make_unique<
+      testing::NiceMock<AITestUtils::MockLanguageModelAppendClient>>();
+  base::RunLoop append_run_loop;
+  EXPECT_CALL(*mock_append_client, OnAppendComplete()).WillOnce([&]() {
+    append_run_loop.Quit();
+  });
+  mojo::Remote<blink::mojom::AILanguageModel> mock_session(
+      session_future.Take());
+  mock_session->Append(MakeInput(kTestAppendPrompt),
+                       mock_append_client->BindNewPipeAndPassRemote());
+  append_run_loop.Run();
+  mock_session->Prompt(MakeInput(kTestPrompt),
+                       /*constraint=*/nullptr,
+                       mock_responder->BindNewPipeAndPassRemote());
+  responder_run_loop.Run();
+}
+
 // Tests `AILanguageModel::Context` creation without initial prompts.
 TEST(AILanguageModelContextCreationTest, CreateContext_WithoutInitialPrompts) {
   AILanguageModel::Context context(kTestMaxContextToken, {});
diff --git a/chrome/browser/ai/ai_test_utils.cc b/chrome/browser/ai/ai_test_utils.cc
index 5d55a292..94b4b6c 100644
--- a/chrome/browser/ai/ai_test_utils.cc
+++ b/chrome/browser/ai/ai_test_utils.cc
@@ -37,6 +37,17 @@
 AITestUtils::MockCreateLanguageModelClient::BindNewPipeAndPassRemote() {
   return receiver_.BindNewPipeAndPassRemote();
 }
+
+AITestUtils::MockLanguageModelAppendClient::MockLanguageModelAppendClient() =
+    default;
+AITestUtils::MockLanguageModelAppendClient::~MockLanguageModelAppendClient() =
+    default;
+
+mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient>
+AITestUtils::MockLanguageModelAppendClient::BindNewPipeAndPassRemote() {
+  return receiver_.BindNewPipeAndPassRemote();
+}
+
 AITestUtils::FakeComponent::FakeComponent(std::string id, uint64_t total_bytes)
     : id_(std::move(id)), total_bytes_(total_bytes) {}
 
diff --git a/chrome/browser/ai/ai_test_utils.h b/chrome/browser/ai/ai_test_utils.h
index 14ac607..34160ab 100644
--- a/chrome/browser/ai/ai_test_utils.h
+++ b/chrome/browser/ai/ai_test_utils.h
@@ -103,6 +103,32 @@
         this};
   };
 
+  class MockLanguageModelAppendClient
+      : public blink::mojom::AILanguageModelAppendClient {
+   public:
+    MockLanguageModelAppendClient();
+    ~MockLanguageModelAppendClient() override;
+    MockLanguageModelAppendClient(const MockLanguageModelAppendClient&) =
+        delete;
+    MockLanguageModelAppendClient& operator=(
+        const MockLanguageModelAppendClient&) = delete;
+
+    mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient>
+    BindNewPipeAndPassRemote();
+
+    MOCK_METHOD(void, OnAppendComplete, (), (override));
+
+    MOCK_METHOD(void, OnQuotaOverflow, (), (override));
+
+    MOCK_METHOD(void,
+                OnError,
+                (blink::mojom::ModelStreamingResponseStatus error),
+                (override));
+
+   private:
+    mojo::Receiver<blink::mojom::AILanguageModelAppendClient> receiver_{this};
+  };
+
   class FakeComponent {
    public:
     FakeComponent(std::string id, uint64_t total_bytes);
diff --git a/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle.cc b/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle.cc
index 7b34725..0cf35611 100644
--- a/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle.cc
+++ b/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle.cc
@@ -365,7 +365,7 @@
             on_task_blocklist->one_level_deep_original_url()[original_tab_id];
       }
       if (source_url.is_valid()) {
-        if (url.DomainIs(source_url.host())) {
+        if (OnTaskBlocklist::IsURLInDomain(url, source_url)) {
           // Same domain navigation.
           on_task_blocklist->MaybeSetURLRestrictionLevel(
               navigation_handle()->GetWebContents(), url,
diff --git a/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle_interactive_ui_test.cc b/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle_interactive_ui_test.cc
index d057e532..d9b128b 100644
--- a/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle_interactive_ui_test.cc
+++ b/chrome/browser/ash/boca/on_task/on_task_locked_session_navigation_throttle_interactive_ui_test.cc
@@ -54,12 +54,12 @@
 namespace ash {
 namespace {
 
-constexpr char kTabUrl1Host[] = "example.com";
+constexpr char kTabUrl1Host[] = "www.example.com";
 constexpr char kTabUrl1SubDomainHost[] = "example.child.com";
 constexpr char kTabUrl1FrontSubDomainHost[] = "sub.example.com";
-constexpr char kTabUrl2Host[] = "company.org";
+constexpr char kTabUrl2Host[] = "www.company.org";
 constexpr char kTabUrlRedirectHost[] = "redirect-url.com";
-constexpr char kTabGoogleHost[] = "google.com";
+constexpr char kTabGoogleHost[] = "www.google.com";
 constexpr char kTabGoogleDocsHost[] = "docs.google.com";
 
 // Fake delegate implementation for the `OnTaskNotificationsManager` to minimize
diff --git a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc
index 10535d2..abc53fe 100644
--- a/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc
+++ b/chrome/browser/ash/boca/on_task/on_task_locked_session_window_tracker_browsertest.cc
@@ -66,11 +66,11 @@
 namespace ash::boca {
 namespace {
 
-constexpr char kTabUrl1Host[] = "example.com";
+constexpr char kTabUrl1Host[] = "www.example.com";
 constexpr char kTabUrl1SubDomainHost[] = "example.child.com";
 constexpr char kTabUrl1FrontSubDomainHost[] = "sub.example.com";
-constexpr char kTabUrl2Host[] = "company.org";
-constexpr char kTabGoogleHost[] = "google.com";
+constexpr char kTabUrl2Host[] = "www.company.org";
+constexpr char kTabGoogleHost[] = "www.google.com";
 constexpr char kTabGoogleDocsHost[] = "docs.google.com";
 constexpr char kChromeBocaAppQueryUrl[] =
     "chrome-untrusted://boca-app/q?queryForm";
diff --git a/chrome/browser/ash/file_manager/file_tasks.cc b/chrome/browser/ash/file_manager/file_tasks.cc
index b851df25..5ca76e48 100644
--- a/chrome/browser/ash/file_manager/file_tasks.cc
+++ b/chrome/browser/ash/file_manager/file_tasks.cc
@@ -19,6 +19,7 @@
 #include "ash/constants/ash_features.h"
 #include "ash/constants/web_app_id_constants.h"
 #include "ash/webui/file_manager/url_constants.h"
+#include "base/barrier_callback.h"
 #include "base/containers/contains.h"
 #include "base/containers/fixed_flat_map.h"
 #include "base/containers/fixed_flat_set.h"
@@ -38,6 +39,7 @@
 #include "chrome/browser/apps/app_service/app_launch_params.h"
 #include "chrome/browser/apps/app_service/app_service_proxy.h"
 #include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
+#include "chrome/browser/apps/app_service/launch_result_type.h"
 #include "chrome/browser/apps/app_service/metrics/app_platform_metrics.h"
 #include "chrome/browser/apps/app_service/metrics/app_service_metrics.h"
 #include "chrome/browser/ash/drive/drive_integration_service.h"
@@ -349,17 +351,41 @@
 
 // Opens the files specified by |file_urls| with the browser for |profile|.
 // Returns true on success. It's a failure if no files are opened.
-bool OpenFilesWithBrowser(Profile* profile,
+void OpenFilesWithBrowser(Profile* profile,
                           const std::vector<FileSystemURL>& file_urls,
-                          const std::string& action_id) {
-  int num_opened = 0;
+                          const std::string& action_id,
+                          FileTaskFinishedCallback done) {
+  const auto track_opens = base::BarrierCallback<
+      std::optional<apps::LaunchResult::State>>(
+      file_urls.size(),
+      base::BindOnce(
+          [](FileTaskFinishedCallback done,
+             const std::vector<std::optional<apps::LaunchResult::State>>&
+                 opens) {
+            const int num_opened =
+                std::count_if(opens.begin(), opens.end(), [](auto& o) {
+                  return o.has_value() &&
+                         o.value() == apps::LaunchResult::State::kSuccess;
+                });
+
+            if (num_opened > 0) {
+              std::move(done).Run(
+                  extensions::api::file_manager_private::TaskResult::kOpened,
+                  "");
+            } else {
+              std::move(done).Run(
+                  extensions::api::file_manager_private::TaskResult::kFailed,
+                  "");
+            }
+          },
+          std::move(done)));
   for (const FileSystemURL& file_url : file_urls) {
     if (ash::FileSystemBackend::CanHandleURL(file_url)) {
-      num_opened +=
-          util::OpenFileWithAppOrBrowser(profile, file_url, action_id) ? 1 : 0;
+      util::OpenFileWithAppOrBrowser(profile, file_url, action_id, track_opens);
+    } else {
+      track_opens.Run({apps::LaunchResult::State::kFailed});
     }
   }
-  return num_opened > 0;
 }
 
 void RecordDriveOfflineUMAsGotDocsOfflineStats(
@@ -803,13 +829,8 @@
   // this will always open on the current desktop, regardless of which profile
   // owns the files, so return TASK_RESULT_OPENED.
   if (ShouldBeOpenedWithBrowser(task.app_id, parsed_action_id)) {
-    const bool result =
-        OpenFilesWithBrowser(profile, file_urls, parsed_action_id);
-    if (result && done) {
-      std::move(done).Run(
-          extensions::api::file_manager_private::TaskResult::kOpened, "");
-    }
-    return result;
+    OpenFilesWithBrowser(profile, file_urls, parsed_action_id, std::move(done));
+    return true;
   }
 
   for (const FileSystemURL& file_url : file_urls) {
diff --git a/chrome/browser/ash/file_manager/open_with_browser.cc b/chrome/browser/ash/file_manager/open_with_browser.cc
index a7c2839..3b7c462 100644
--- a/chrome/browser/ash/file_manager/open_with_browser.cc
+++ b/chrome/browser/ash/file_manager/open_with_browser.cc
@@ -234,10 +234,12 @@
         integration_service->GetRelativeDrivePath(file_path, &path)) {
       integration_service->GetDriveFsInterface()->GetMetadata(
           path, base::BindOnce(&OpenEncryptedDriveFsFile, file_path));
+      std::move(callback).Run({apps::LaunchResult::State::kSuccess});
       return true;
     }
     LOG(WARNING) << "Failed to open file (extension): " << file_path.Extension()
                  << ": no connection to integration service";
+    std::move(callback).Run({apps::LaunchResult::State::kFailed});
     return false;
   }
 
@@ -272,6 +274,7 @@
     // Failed to open the file of unknown type.
     LOG(WARNING) << "Unknown file type (extension): " << file_path.Extension()
                  << " action: " << action_id;
+    std::move(callback).Run({apps::LaunchResult::State::kFailed});
     return false;
   }
 
@@ -297,10 +300,12 @@
             page_url = net::FilePathToFileURL(file_path);
           }
           OpenNewTab(page_url);
+          std::move(callback).Run({apps::LaunchResult::State::kSuccess});
           return;
         }
         LOG(WARNING) << "Not viewable in browser: MIME: " << mime
                      << " action: " << action_id;
+        std::move(callback).Run({apps::LaunchResult::State::kFailed});
       },
       std::move(callback), file_path, file_system_url, action_id,
       base::Owned(mime_type_collector));
diff --git a/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc b/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc
index 6b84353b..e6cf1c9 100644
--- a/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc
+++ b/chrome/browser/ash/shimless_rma/chrome_shimless_rma_delegate_unittest.cc
@@ -134,6 +134,21 @@
                            web_app::IwaStorageOwnedBundle{
                                "random_folder", /*dev_mode=*/false})));
   }
+
+  void RemoveInstallManagementMaybeUninstall(
+      const webapps::AppId& app_id,
+      web_app::WebAppManagement::Type install_management,
+      webapps::WebappUninstallSource uninstall_source,
+      UninstallCallback callback,
+      const base::Location& location) override {
+    EXPECT_EQ(install_management,
+              web_app::WebAppManagement::Type::kIwaShimlessRma);
+    EXPECT_EQ(uninstall_source, webapps::WebappUninstallSource::kUnknown);
+
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
+        FROM_HERE, base::BindOnce(std::move(callback),
+                                  webapps::UninstallResultCode::kAppRemoved));
+  }
 };
 
 class FakeDiagnosticsAppProfileHelperDelegate
@@ -156,7 +171,7 @@
     return &web_app_command_scheduler_;
   }
 
-  const web_app::WebApp* GetWebAppById(
+  const web_app::WebApp* GetWebAppByIdUnsafe(
       const webapps::AppId& app_id,
       content::BrowserContext* browser_context) override {
     return &web_app_;
@@ -171,7 +186,7 @@
  protected:
   FakeServiceWorkerContext fake_service_worker_context_;
   FakeWebAppCommandScheduler web_app_command_scheduler_;
-  web_app::WebApp web_app_{/*AppId=*/""};
+  web_app::WebApp web_app_{/*app_id=*/""};
 };
 
 class ChromeShimlessRmaDelegatePrepareDiagnosticsAppProfileTest
diff --git a/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.cc b/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.cc
index fbf4542..0f1b3ec 100644
--- a/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.cc
+++ b/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.cc
@@ -39,6 +39,7 @@
 #include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
 #include "components/strings/grit/components_strings.h"
 #include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
+#include "components/webapps/browser/uninstall_result_code.h"
 #include "components/webapps/common/web_app_id.h"
 #include "content/public/browser/service_worker_context.h"
 #include "extensions/browser/crx_file_info.h"
@@ -171,7 +172,7 @@
     return;
   }
 
-  const web_app::WebApp* web_app = state->delegate->GetWebAppById(
+  const web_app::WebApp* web_app = state->delegate->GetWebAppByIdUnsafe(
       web_app::IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(
           *state->iwa_id)
           .app_id(),
@@ -216,6 +217,33 @@
 void InstallIsolatedWebApp(
     std::unique_ptr<PrepareDiagnosticsAppProfileState> state) {
   CHECK(state->context);
+  CHECK(state->iwa_id);
+
+  auto url_info = web_app::IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(
+      state->iwa_id.value());
+  auto install_source = web_app::IsolatedWebAppInstallSource::FromShimlessRma(
+      web_app::IwaSourceBundleProdModeWithFileOp(
+          state->swbn_path, web_app::IwaSourceBundleProdFileOp::kCopy));
+  state->delegate->GetWebAppCommandScheduler(state->context)
+      ->InstallIsolatedWebApp(
+          url_info, install_source,
+          /*expected_version=*/std::nullopt, /*optional_keep_alive=*/nullptr,
+          /*optional_profile_keep_alive=*/nullptr,
+          base::BindOnce(&OnIsolatedWebAppInstalled, std::move(state)));
+}
+
+void OnIsolatedWebAppRemoved(
+    std::unique_ptr<PrepareDiagnosticsAppProfileState> state,
+    webapps::UninstallResultCode code) {
+  if (!webapps::UninstallSucceeded(code)) {
+    LOG(WARNING) << "Failed to unsintalled IWA before installing IWA";
+  }
+  InstallIsolatedWebApp(std::move(state));
+}
+
+void PrepareIsolatedWebApp(
+    std::unique_ptr<PrepareDiagnosticsAppProfileState> state) {
+  CHECK(state->context);
   CHECK(state->extension_id);
 
   auto info =
@@ -229,15 +257,24 @@
 
   auto url_info = web_app::IsolatedWebAppUrlInfo::CreateFromSignedWebBundleId(
       state->iwa_id.value());
-  auto install_source = web_app::IsolatedWebAppInstallSource::FromShimlessRma(
-      web_app::IwaSourceBundleProdModeWithFileOp(
-          state->swbn_path, web_app::IwaSourceBundleProdFileOp::kCopy));
+  const web_app::WebApp* web_app =
+      state->delegate->GetWebAppByIdUnsafe(url_info.app_id(), state->context);
+  if (!web_app) {
+    // Install the IWA directly if IWA doesn't exist.
+    InstallIsolatedWebApp((std::move(state)));
+    return;
+  }
+
+  // Since we can not install IWA when the IWA is already installed, we should
+  // remove the existing IWA first before installation.
+  // It is safe to run uninstall job here since Shimless RMA is the only install
+  // source for the third-party diagnostics IWA.
+  // Note that the flow will be broken if there are multiple install sources.
   state->delegate->GetWebAppCommandScheduler(state->context)
-      ->InstallIsolatedWebApp(
-          url_info, install_source,
-          /*expected_version=*/std::nullopt, /*optional_keep_alive=*/nullptr,
-          /*optional_profile_keep_alive=*/nullptr,
-          base::BindOnce(&OnIsolatedWebAppInstalled, std::move(state)));
+      ->RemoveInstallManagementMaybeUninstall(
+          url_info.app_id(), web_app::WebAppManagement::Type::kIwaShimlessRma,
+          webapps::WebappUninstallSource::kUnknown,
+          base::BindOnce(&OnIsolatedWebAppRemoved, std::move(state)));
 }
 
 void CheckExtensionIsReady(
@@ -267,7 +304,7 @@
     return;
   }
 
-  InstallIsolatedWebApp(std::move(state));
+  PrepareIsolatedWebApp(std::move(state));
 }
 
 void CheckExtensionIsReady(
@@ -435,7 +472,7 @@
   return &web_app_provider->scheduler();
 }
 
-const web_app::WebApp* DiagnosticsAppProfileHelperDelegate::GetWebAppById(
+const web_app::WebApp* DiagnosticsAppProfileHelperDelegate::GetWebAppByIdUnsafe(
     const webapps::AppId& app_id,
     content::BrowserContext* browser_context) {
   auto* web_app_provider = web_app::WebAppProvider::GetForWebApps(
diff --git a/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.h b/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.h
index 474b3ae..41d4858 100644
--- a/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.h
+++ b/chrome/browser/ash/shimless_rma/diagnostics_app_profile_helper.h
@@ -38,7 +38,7 @@
   virtual web_app::WebAppCommandScheduler* GetWebAppCommandScheduler(
       content::BrowserContext* browser_context);
 
-  virtual const web_app::WebApp* GetWebAppById(
+  virtual const web_app::WebApp* GetWebAppByIdUnsafe(
       const webapps::AppId& app_id,
       content::BrowserContext* browser_context);
 
diff --git a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
index ad7faece..f1d6c39 100644
--- a/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
+++ b/chrome/browser/autofill/android/java/src/org/chromium/chrome/browser/autofill/AutofillUiUtils.java
@@ -41,6 +41,7 @@
 import android.widget.PopupWindow;
 import android.widget.TextView;
 
+import androidx.annotation.DimenRes;
 import androidx.annotation.IntDef;
 import androidx.annotation.Px;
 import androidx.annotation.VisibleForTesting;
@@ -121,30 +122,43 @@
     /** Contains dimensional specs for icons by the {@code AutofillImageFetcher}. */
     public static class IconSpecs {
         private final Context mContext;
-        private final int mWidthId;
-        private final int mHeightId;
-        private final int mCornerRadiusId;
-        private final int mBorderWidthId;
+        private final @ImageType int mImageType;
+        private final @DimenRes int mWidthId;
+        private final @DimenRes int mHeightId;
+        private final @DimenRes int mCornerRadiusId;
+        private final @DimenRes int mBorderWidthId;
 
         /**
          * @param context to get the resources.
+         * @param imageType the type of the image supported by the {@link AutofillImageFetcher}.
          * @param widthId Resource Id for the icon's width spec.
          * @param heightId Resource Id for the icon's height spec.
          */
-        private IconSpecs(Context context, int widthId, int heightId) {
-            this(context, widthId, heightId, 0, 0);
+        private IconSpecs(
+                Context context,
+                @ImageType int imageType,
+                @DimenRes int widthId,
+                @DimenRes int heightId) {
+            this(context, imageType, widthId, heightId, 0, 0);
         }
 
         /**
          * @param context to get the resources.
+         * @param imageType the type of the image supported by the {@link AutofillImageFetcher}.
          * @param widthId Resource Id for the icon's width spec.
          * @param heightId Resource Id for the icon's height spec.
          * @param cornerRadiusId Resource Id for the icon's corner radius spec.
          * @param borderWidthId Resource Id for the icon's border width spec.
          */
         private IconSpecs(
-                Context context, int widthId, int heightId, int cornerRadiusId, int borderWidthId) {
+                Context context,
+                @ImageType int imageType,
+                @DimenRes int widthId,
+                @DimenRes int heightId,
+                @DimenRes int cornerRadiusId,
+                @DimenRes int borderWidthId) {
             mContext = context;
+            mImageType = imageType;
             mWidthId = widthId;
             mHeightId = heightId;
             mCornerRadiusId = cornerRadiusId;
@@ -180,6 +194,7 @@
                 case ImageSize.LARGE:
                     return new IconSpecs(
                             context,
+                            ImageType.CREDIT_CARD_ART_IMAGE,
                             R.dimen.large_card_icon_width,
                             R.dimen.large_card_icon_height,
                             R.dimen.large_card_icon_corner_radius,
@@ -187,6 +202,7 @@
                 case ImageSize.SQUARE:
                     return new IconSpecs(
                             context,
+                            ImageType.CREDIT_CARD_ART_IMAGE,
                             R.dimen.square_card_icon_side_length,
                             R.dimen.square_card_icon_side_length,
                             R.dimen.square_card_icon_corner_radius,
@@ -194,6 +210,7 @@
                 case ImageSize.SMALL:
                     return new IconSpecs(
                             context,
+                            ImageType.CREDIT_CARD_ART_IMAGE,
                             R.dimen.small_card_icon_width,
                             R.dimen.small_card_icon_height,
                             R.dimen.small_card_icon_corner_radius,
@@ -208,11 +225,13 @@
                 case ImageSize.LARGE:
                     return new IconSpecs(
                             context,
+                            ImageType.VALUABLE_IMAGE,
                             R.dimen.large_valuable_icon_size,
                             R.dimen.large_valuable_icon_size);
                 case ImageSize.SMALL:
                     return new IconSpecs(
                             context,
+                            ImageType.VALUABLE_IMAGE,
                             R.dimen.small_valuable_icon_size,
                             R.dimen.small_valuable_icon_size);
             }
@@ -221,7 +240,17 @@
         }
 
         public GURL getResolvedIconUrl(GURL iconUrl) {
-            return getFifeIconUrlWithParams(iconUrl, getWidth(), getHeight());
+            switch (mImageType) {
+                case ImageType.CREDIT_CARD_ART_IMAGE:
+                case ImageType.PIX_ACCOUNT_IMAGE:
+                    return getFifeIconUrlWithParams(
+                            iconUrl, getWidth(), getHeight(), /* circleCrop= */ false);
+                case ImageType.VALUABLE_IMAGE:
+                    return getFifeIconUrlWithParams(
+                            iconUrl, getWidth(), getHeight(), /* circleCrop= */ true);
+            }
+            assert false : "Image type not handled: " + mImageType;
+            return assumeNonNull(null);
         }
 
         public @Px int getWidth() {
@@ -639,14 +668,19 @@
      * @param customIconUrl A FIFE URL to fetch the image.
      * @param width in pixels.
      * @param height in pixels.
+     * @param circleCrop whether to the circle crop parameter to the URL ('-cc').
      * @return {@link GURL} formatted with the icon dimensions to fetch the image.
      */
     @VisibleForTesting
-    static GURL getFifeIconUrlWithParams(GURL customIconUrl, @Px int width, @Px int height) {
+    static GURL getFifeIconUrlWithParams(
+            GURL customIconUrl, @Px int width, @Px int height, boolean circleCrop) {
         // Params can be added to a FIFE URL by appending them at the end like URL[=params]. "w"
         // option is used to set the width in pixels, and "h" is used to set the height in pixels.
         StringBuilder url = new StringBuilder(customIconUrl.getSpec());
         url.append("=w").append(width).append("-h").append(height);
+        if (circleCrop) {
+            url.append("-cc");
+        }
 
         return new GURL(url.toString());
     }
diff --git a/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java b/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
index d7f9997..c2e6001 100644
--- a/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
+++ b/chrome/browser/autofill/test/android/java/src/org/chromium/chrome/browser/autofill/PersonalDataManagerTest.java
@@ -389,7 +389,10 @@
         // The URL should be updated as `cardArtUrl=w{width}-h{height}`.
         assertThat(
                         AutofillUiUtils.getFifeIconUrlWithParams(
-                                capitalOneIconUrl, widthPixels, heightPixels))
+                                capitalOneIconUrl,
+                                widthPixels,
+                                heightPixels,
+                                /* circleCrop= */ false))
                 .isEqualTo(
                         new GURL(
                                 capitalOneIconUrl.getSpec()
@@ -397,7 +400,24 @@
                                         + widthPixels
                                         + "-h"
                                         + heightPixels));
-        assertThat(AutofillUiUtils.getFifeIconUrlWithParams(cardArtUrl, widthPixels, heightPixels))
+        // The URL should be updated as `cardArtUrl=w{width}-h{height}-cc`.
+        assertThat(
+                        AutofillUiUtils.getFifeIconUrlWithParams(
+                                capitalOneIconUrl,
+                                widthPixels,
+                                heightPixels,
+                                /* circleCrop= */ true))
+                .isEqualTo(
+                        new GURL(
+                                capitalOneIconUrl.getSpec()
+                                        + "=w"
+                                        + widthPixels
+                                        + "-h"
+                                        + heightPixels
+                                        + "-cc"));
+        assertThat(
+                        AutofillUiUtils.getFifeIconUrlWithParams(
+                                cardArtUrl, widthPixels, heightPixels, /* circleCrop= */ false))
                 .isEqualTo(
                         new GURL(cardArtUrl.getSpec() + "=w" + widthPixels + "-h" + heightPixels));
     }
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc
index 57a1acd3..60dcfa89 100644
--- a/chrome/browser/chrome_content_browser_client.cc
+++ b/chrome/browser/chrome_content_browser_client.cc
@@ -192,7 +192,6 @@
 #include "chrome/browser/ui/prefs/pref_watcher.h"
 #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_delegate.h"
 #include "chrome/browser/ui/ui_features.h"
-#include "chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h"
 #include "chrome/browser/ui/webid/identity_dialog_controller.h"
 #include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
 #include "chrome/browser/ui/webui/internal_debug_pages_disabled/internal_debug_pages_disabled_ui.h"
@@ -480,8 +479,6 @@
 #include "chrome/browser/ash/fileapi/external_file_url_loader_factory.h"
 #include "chrome/browser/ash/fileapi/file_system_backend.h"
 #include "chrome/browser/ash/fileapi/mtp_file_system_backend_delegate.h"
-#include "chrome/browser/ash/login/signin/merge_session_navigation_throttle.h"
-#include "chrome/browser/ash/login/signin/merge_session_throttling_utils.h"
 #include "chrome/browser/ash/login/signin_partition_manager.h"
 #include "chrome/browser/ash/login/startup_utils.h"
 #include "chrome/browser/ash/main_parts/chrome_browser_main_parts_ash.h"
@@ -513,7 +510,6 @@
 #include "base/android/application_status_listener.h"
 #include "base/android/build_info.h"
 #include "base/feature_list.h"
-#include "chrome/android/features/dev_ui/buildflags.h"
 #include "chrome/browser/android/customtabs/client_data_header_web_contents_observer.h"
 #include "chrome/browser/android/devtools_manager_delegate_android.h"
 #include "chrome/browser/android/ntp/new_tab_page_url_handler.h"
@@ -522,7 +518,6 @@
 #include "chrome/browser/android/tab_web_contents_delegate_android.h"
 #include "chrome/browser/chrome_browser_main_android.h"
 #include "chrome/browser/digital_credentials/digital_identity_provider_android.h"
-#include "chrome/browser/download/android/intercept_oma_download_navigation_throttle.h"
 #include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "chrome/browser/safe_browsing/android/safe_browsing_referring_app_bridge_android.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
@@ -530,7 +525,6 @@
 #include "components/browser_ui/accessibility/android/font_size_prefs_android.h"
 #include "components/crash/content/browser/child_exit_observer_android.h"
 #include "components/crash/content/browser/crash_memory_metrics_collector_android.h"
-#include "components/navigation_interception/intercept_navigation_delegate.h"
 #include "components/viz/common/features.h"
 #include "components/viz/common/viz_utils.h"
 #include "content/public/browser/android/java_interfaces.h"
@@ -538,9 +532,6 @@
 #include "ui/base/resource/resource_bundle_android.h"
 #include "ui/base/ui_base_paths.h"
 #include "ui/display/util/display_util.h"
-#if BUILDFLAG(DFMIFY_DEV_UI)
-#include "chrome/browser/dev_ui/android/dev_ui_loader_throttle.h"
-#endif  // BUILDFLAG(DFMIFY_DEV_UI)
 #elif BUILDFLAG(IS_POSIX)
 #include "chrome/browser/chrome_browser_main_posix.h"
 #endif
@@ -565,9 +556,6 @@
 #include "ash/shell.h"
 #include "base/debug/leak_annotations.h"
 #include "chrome/browser/apps/app_service/app_install/app_install_navigation_throttle.h"
-#include "chrome/browser/apps/intent_helper/chromeos_disabled_apps_throttle.h"
-#include "chrome/browser/apps/link_capturing/chromeos_link_capturing_delegate.h"
-#include "chrome/browser/apps/link_capturing/chromeos_reimpl_navigation_capturing_throttle.h"
 #include "chrome/browser/chromeos/policy/dlp/dlp_scoped_file_access_delegate.h"
 #include "chrome/browser/chromeos/tablet_mode/chrome_content_browser_client_tablet_mode_part.h"
 #include "chrome/browser/file_system_access/cloud_identifier/cloud_identifier_util_cros.h"
@@ -583,7 +571,6 @@
 #endif
 
 #if !BUILDFLAG(IS_ANDROID)
-#include "chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.h"
 #include "chrome/browser/devtools/chrome_devtools_manager_delegate.h"
 #include "chrome/browser/devtools/devtools_window.h"
 #include "chrome/browser/direct_sockets/chrome_direct_sockets_delegate.h"
@@ -632,8 +619,6 @@
 
 #if BUILDFLAG(IS_ANDROID)
 #include "components/crash/content/browser/crash_handler_host_linux.h"
-#else
-#include "chrome/browser/apps/link_capturing/web_app_link_capturing_delegate.h"
 #endif
 
 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN)
@@ -679,7 +664,6 @@
 #include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
 #include "chrome/browser/extensions/chrome_extension_cookies.h"
 #include "extensions/browser/api/web_request/web_request_api.h"
-#include "extensions/browser/extension_navigation_throttle.h"
 #include "extensions/browser/extension_protocols.h"
 #include "extensions/browser/extension_registry.h"
 #include "extensions/browser/extension_util.h"
@@ -697,7 +681,6 @@
 #if BUILDFLAG(ENABLE_EXTENSIONS)
 #include "chrome/browser/accessibility/animation_policy_prefs.h"
 #include "chrome/browser/extensions/extension_util.h"
-#include "chrome/browser/extensions/user_script_listener.h"
 #include "chrome/browser/speech/extension_api/tts_engine_extension_api.h"
 #include "chrome/browser/ui/web_applications/app_browser_controller.h"
 #include "chrome/browser/web_applications/web_app_utils.h"
@@ -711,10 +694,6 @@
 #include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
 #endif
 
-#if BUILDFLAG(ENABLE_PLATFORM_APPS)
-#include "chrome/browser/apps/platform_apps/platform_app_navigation_redirector.h"
-#endif
-
 #if BUILDFLAG(ENABLE_PLUGINS)
 #include "chrome/browser/plugins/chrome_content_browser_client_plugins_part.h"
 #include "chrome/browser/plugins/plugin_response_interceptor_url_loader_throttle.h"
@@ -5402,103 +5381,10 @@
   CreateAndAddChromeThrottlesForNavigation(registry);
 
   content::NavigationHandle& handle = registry.GetNavigationHandle();
-  // TODO(https://crbug.com/412524375): Move the following code to
-  // CreateAndAddChromeThrottlesForNavigation().
-
-#if BUILDFLAG(IS_ANDROID)
-  // TODO(davidben): This is insufficient to integrate with prerender properly.
-  // https://crbug.com/370595
-  prerender::NoStatePrefetchContents* no_state_prefetch_contents =
-      prerender::ChromeNoStatePrefetchContentsDelegate::FromWebContents(
-          handle.GetWebContents());
-  if (!no_state_prefetch_contents) {
-    navigation_interception::InterceptNavigationDelegate::MaybeCreateAndAdd(
-        registry, navigation_interception::SynchronyMode::kAsync);
-  }
-  registry.AddThrottle(InterceptOMADownloadNavigationThrottle::Create(&handle));
-
-#if BUILDFLAG(DFMIFY_DEV_UI)
-  // If the DevUI DFM is already installed, then this is a no-op, except for the
-  // side effect of ensuring that the DevUI DFM is loaded.
-  registry.MaybeAddThrottle(
-      dev_ui::DevUiLoaderThrottle::MaybeCreateThrottleFor(&handle));
-#endif  // BUILDFLAG(DFMIFY_DEV_UI)
-
-#elif BUILDFLAG(ENABLE_PLATFORM_APPS)
-  // Redirect some navigations to apps that have registered matching URL
-  // handlers ('url_handlers' in the manifest).
-  PlatformAppNavigationRedirector::MaybeCreateAndAdd(registry);
-#endif
-
-#if BUILDFLAG(IS_CHROMEOS)
-  // Check if we need to add merge session throttle. This throttle will postpone
-  // loading of main frames.
-  if (handle.IsInMainFrame()) {
-    // Add interstitial page while merge session process (cookie reconstruction
-    // from OAuth2 refresh token in ChromeOS login) is still in progress while
-    // we are attempting to load a google property.
-    if (ash::merge_session_throttling_utils::ShouldAttachNavigationThrottle() &&
-        !ash::merge_session_throttling_utils::AreAllSessionMergedAlready() &&
-        handle.GetURL().SchemeIsHTTPOrHTTPS()) {
-      registry.AddThrottle(
-          ash::MergeSessionNavigationThrottle::Create(&handle));
-    }
-  }
-
-  registry.MaybeAddThrottle(
-      apps::ChromeOsDisabledAppsThrottle::MaybeCreate(&handle));
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
-#if !BUILDFLAG(IS_ANDROID)
-  std::unique_ptr<apps::LinkCapturingNavigationThrottle::Delegate>
-      link_capturing_delegate;
-
-#if BUILDFLAG(IS_CHROMEOS)
-  link_capturing_delegate =
-      std::make_unique<apps::ChromeOsLinkCapturingDelegate>();
-#else
-  link_capturing_delegate =
-      std::make_unique<web_app::WebAppLinkCapturingDelegate>();
-#endif
-  std::unique_ptr<content::NavigationThrottle> url_to_apps_throttle =
-      apps::LinkCapturingNavigationThrottle::MaybeCreate(
-          &handle, std::move(link_capturing_delegate));
-
-  bool url_to_apps_throttle_created = url_to_apps_throttle != nullptr;
-  if (url_to_apps_throttle_created) {
-    registry.AddThrottle(std::move(url_to_apps_throttle));
-  }
-#if BUILDFLAG(IS_CHROMEOS)
-  // TODO(crbug.com/366547977): This currently does nothing and allows all
-  // navigations to proceed if v2 is enabled on ChromeOS. Implement.
-  std::unique_ptr<content::NavigationThrottle>
-      chromeos_reimpl_navigation_throttle =
-          apps::ChromeOsReimplNavigationCapturingThrottle::MaybeCreate(&handle);
-  if (chromeos_reimpl_navigation_throttle) {
-    // Verify the v1 throttle has not been created.
-    CHECK(!url_to_apps_throttle_created);
-    registry.AddThrottle(std::move(chromeos_reimpl_navigation_throttle));
-  }
-#endif  // BUILDFLAG(IS_CHROMEOS)
-
-  registry.MaybeAddThrottle(
-      web_app::NavigationCapturingRedirectionThrottle::MaybeCreate(&handle));
-#endif  // !BUILDFLAG(IS_ANDROID)
-
   Profile* profile =
       Profile::FromBrowserContext(handle.GetWebContents()->GetBrowserContext());
-
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-  if (!ChromeContentBrowserClientExtensionsPart::
-          AreExtensionsDisabledForProfile(profile)) {
-    registry.AddThrottle(
-        std::make_unique<extensions::ExtensionNavigationThrottle>(&handle));
-
-    registry.MaybeAddThrottle(extensions::ExtensionsBrowserClient::Get()
-                                  ->GetUserScriptListener()
-                                  ->CreateNavigationThrottle(&handle));
-  }
-#endif
+  // TODO(https://crbug.com/412524375): Move the following code to
+  // CreateAndAddChromeThrottlesForNavigation().
 
 #if BUILDFLAG(ENABLE_GUEST_VIEW)
   registry.MaybeAddThrottle(
diff --git a/chrome/browser/chrome_content_browser_client_navigation_throttles.cc b/chrome/browser/chrome_content_browser_client_navigation_throttles.cc
index 475a92c..07c231c84 100644
--- a/chrome/browser/chrome_content_browser_client_navigation_throttles.cc
+++ b/chrome/browser/chrome_content_browser_client_navigation_throttles.cc
@@ -4,9 +4,48 @@
 
 #include "chrome/browser/chrome_content_browser_client_navigation_throttles.h"
 
+#include "build/buildflag.h"
+#include "chrome/browser/preloading/prefetch/no_state_prefetch/chrome_no_state_prefetch_contents_delegate.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/web_applications/navigation_capturing_redirection_throttle.h"
 #include "components/page_load_metrics/browser/metrics_navigation_throttle.h"
 #include "content/public/browser/navigation_handle.h"
 #include "content/public/browser/navigation_throttle_registry.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/buildflags/buildflags.h"
+
+#if BUILDFLAG(IS_ANDROID)
+#include "chrome/android/features/dev_ui/buildflags.h"
+#include "chrome/browser/download/android/intercept_oma_download_navigation_throttle.h"
+#include "components/navigation_interception/intercept_navigation_delegate.h"
+
+#if BUILDFLAG(DFMIFY_DEV_UI)
+#include "chrome/browser/dev_ui/android/dev_ui_loader_throttle.h"
+#endif  // BUILDFLAG(DFMIFY_DEV_UI)
+
+#else  // BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.h"
+#include "chrome/browser/apps/link_capturing/web_app_link_capturing_delegate.h"
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(IS_CHROMEOS)
+#include "chrome/browser/apps/intent_helper/chromeos_disabled_apps_throttle.h"
+#include "chrome/browser/apps/link_capturing/chromeos_link_capturing_delegate.h"
+#include "chrome/browser/apps/link_capturing/chromeos_reimpl_navigation_capturing_throttle.h"
+#include "chrome/browser/ash/login/signin/merge_session_navigation_throttle.h"
+#include "chrome/browser/ash/login/signin/merge_session_throttling_utils.h"
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
+#if BUILDFLAG(ENABLE_PLATFORM_APPS)
+#include "chrome/browser/apps/platform_apps/platform_app_navigation_redirector.h"
+#endif  // BUILDFLAG(ENABLE_PLATFORM_APPS)
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "chrome/browser/extensions/chrome_content_browser_client_extensions_part.h"
+#include "chrome/browser/extensions/user_script_listener.h"
+#include "extensions/browser/extension_navigation_throttle.h"
+#include "extensions/browser/extensions_browser_client.h"
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
 void CreateAndAddChromeThrottlesForNavigation(
     content::NavigationThrottleRegistry& registry) {
@@ -23,5 +62,100 @@
     page_load_metrics::MetricsNavigationThrottle::CreateAndAdd(registry);
   }
 
+#if BUILDFLAG(IS_ANDROID)
+  // TODO(davidben): This is insufficient to integrate with prerender properly.
+  // https://crbug.com/370595
+  prerender::NoStatePrefetchContents* no_state_prefetch_contents =
+      prerender::ChromeNoStatePrefetchContentsDelegate::FromWebContents(
+          handle.GetWebContents());
+  if (!no_state_prefetch_contents) {
+    navigation_interception::InterceptNavigationDelegate::MaybeCreateAndAdd(
+        registry, navigation_interception::SynchronyMode::kAsync);
+  }
+  registry.AddThrottle(InterceptOMADownloadNavigationThrottle::Create(&handle));
+
+#if BUILDFLAG(DFMIFY_DEV_UI)
+  // If the DevUI DFM is already installed, then this is a no-op, except for the
+  // side effect of ensuring that the DevUI DFM is loaded.
+  registry.MaybeAddThrottle(
+      dev_ui::DevUiLoaderThrottle::MaybeCreateThrottleFor(&handle));
+#endif  // BUILDFLAG(DFMIFY_DEV_UI)
+
+#elif BUILDFLAG(ENABLE_PLATFORM_APPS)
+  // Redirect some navigations to apps that have registered matching URL
+  // handlers ('url_handlers' in the manifest).
+  PlatformAppNavigationRedirector::MaybeCreateAndAdd(registry);
+#endif  // BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(IS_CHROMEOS)
+  // Check if we need to add merge session throttle. This throttle will postpone
+  // loading of main frames.
+  if (handle.IsInMainFrame()) {
+    // Add interstitial page while merge session process (cookie reconstruction
+    // from OAuth2 refresh token in ChromeOS login) is still in progress while
+    // we are attempting to load a google property.
+    if (ash::merge_session_throttling_utils::ShouldAttachNavigationThrottle() &&
+        !ash::merge_session_throttling_utils::AreAllSessionMergedAlready() &&
+        handle.GetURL().SchemeIsHTTPOrHTTPS()) {
+      registry.AddThrottle(
+          ash::MergeSessionNavigationThrottle::Create(&handle));
+    }
+  }
+
+  registry.MaybeAddThrottle(
+      apps::ChromeOsDisabledAppsThrottle::MaybeCreate(&handle));
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
+#if !BUILDFLAG(IS_ANDROID)
+  std::unique_ptr<apps::LinkCapturingNavigationThrottle::Delegate>
+      link_capturing_delegate;
+
+#if BUILDFLAG(IS_CHROMEOS)
+  link_capturing_delegate =
+      std::make_unique<apps::ChromeOsLinkCapturingDelegate>();
+#else   // BUILDFLAG(IS_CHROMEOS)
+  link_capturing_delegate =
+      std::make_unique<web_app::WebAppLinkCapturingDelegate>();
+#endif  // BUILDFLAG(IS_CHROMEOS)
+  std::unique_ptr<content::NavigationThrottle> url_to_apps_throttle =
+      apps::LinkCapturingNavigationThrottle::MaybeCreate(
+          &handle, std::move(link_capturing_delegate));
+
+  bool url_to_apps_throttle_created = url_to_apps_throttle != nullptr;
+  if (url_to_apps_throttle_created) {
+    registry.AddThrottle(std::move(url_to_apps_throttle));
+  }
+#if BUILDFLAG(IS_CHROMEOS)
+  // TODO(crbug.com/366547977): This currently does nothing and allows all
+  // navigations to proceed if v2 is enabled on ChromeOS. Implement.
+  std::unique_ptr<content::NavigationThrottle>
+      chromeos_reimpl_navigation_throttle =
+          apps::ChromeOsReimplNavigationCapturingThrottle::MaybeCreate(&handle);
+  if (chromeos_reimpl_navigation_throttle) {
+    // Verify the v1 throttle has not been created.
+    CHECK(!url_to_apps_throttle_created);
+    registry.AddThrottle(std::move(chromeos_reimpl_navigation_throttle));
+  }
+#endif  // BUILDFLAG(IS_CHROMEOS)
+
+  registry.MaybeAddThrottle(
+      web_app::NavigationCapturingRedirectionThrottle::MaybeCreate(&handle));
+#endif  // !BUILDFLAG(IS_ANDROID)
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+  Profile* profile =
+      Profile::FromBrowserContext(handle.GetWebContents()->GetBrowserContext());
+
+  if (!extensions::ChromeContentBrowserClientExtensionsPart::
+          AreExtensionsDisabledForProfile(profile)) {
+    registry.AddThrottle(
+        std::make_unique<extensions::ExtensionNavigationThrottle>(&handle));
+
+    registry.MaybeAddThrottle(extensions::ExtensionsBrowserClient::Get()
+                                  ->GetUserScriptListener()
+                                  ->CreateNavigationThrottle(&handle));
+  }
+#endif
+
   // Add new throttles here.
-}
\ No newline at end of file
+}
diff --git a/chrome/browser/chrome_resource_bundle_helper.cc b/chrome/browser/chrome_resource_bundle_helper.cc
index d1e99bf1..fc0f55998 100644
--- a/chrome/browser/chrome_resource_bundle_helper.cc
+++ b/chrome/browser/chrome_resource_bundle_helper.cc
@@ -21,6 +21,7 @@
 #include "components/prefs/pref_service.h"
 #include "extensions/buildflags/buildflags.h"
 #include "ui/base/resource/resource_bundle.h"
+#include "ui/lottie/resource.h"
 
 #if BUILDFLAG(IS_ANDROID)
 #include "ui/base/resource/resource_bundle_android.h"
@@ -29,7 +30,6 @@
 #if BUILDFLAG(IS_CHROMEOS)
 #include "ash/constants/ash_switches.h"
 #include "chrome/common/pref_names.h"
-#include "ui/lottie/resource.h"  // nogncheck
 #endif
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
@@ -88,10 +88,8 @@
       local_state->GetString(language::prefs::kApplicationLocale);
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS)
   ui::ResourceBundle::SetLottieParsingFunctions(
       &lottie::ParseLottieAsStillImage, &lottie::ParseLottieAsThemedStillImage);
-#endif
 
   TRACE_EVENT0("startup",
                "ChromeBrowserMainParts::InitResourceBundleAndDetermineLocale");
diff --git a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationIntegrationTest.java b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationIntegrationTest.java
index cb95023..b73645d 100644
--- a/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationIntegrationTest.java
+++ b/chrome/browser/collaboration/android/java/src/org/chromium/chrome/browser/collaboration/CollaborationIntegrationTest.java
@@ -62,6 +62,7 @@
 import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory;
 import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
 import org.chromium.chrome.test.R;
+import org.chromium.components.collaboration.CollaborationService;
 import org.chromium.components.data_sharing.DataSharingSDKDelegateBridge;
 import org.chromium.components.data_sharing.DataSharingSDKDelegateTestImpl;
 import org.chromium.components.data_sharing.DataSharingServiceImpl;
@@ -297,24 +298,10 @@
     @Test
     @MediumTest
     public void testDataSharingShowShare() {
-        // Sign in and sets selected types for tab groups.
-        mActivityTestRule.setUpAccountAndSignInForTesting();
-        mActivityTestRule.setSelectedTypes(
-                true,
-                new HashSet<>(
-                        Arrays.asList(
-                                UserSelectableType.TABS, UserSelectableType.SAVED_TAB_GROUPS)));
+        setUpSyncAndSignIn();
 
-        // Create a tab group and open tab grid dialog.
         final ChromeTabbedActivity cta = (ChromeTabbedActivity) mActivityTestRule.getActivity();
-        addBlankTabs(cta, false, 2);
-        enterTabSwitcher(cta);
-        mergeAllNormalTabsToAGroup(cta);
-        LocalTabGroupId localTabGroupId =
-                new LocalTabGroupId(
-                        cta.getTabModelSelector().getModel(false).getTabAt(0).getTabGroupId());
-        clickFirstCardFromTabSwitcher(cta);
-        CriteriaHelper.pollUiThread(() -> isDialogFullyVisible(cta));
+        createTabGroupAndOpenTabGridDialog(cta);
 
         // Setting create flow callback to show share sheet with share link.
         Callback<Boolean> callback =
@@ -326,12 +313,33 @@
         setupShareDelegateSupplier();
 
         onView(withId(R.id.share_button)).perform(relaxedClick());
-        prepareToShareTabGroup(/* owner= */ true, localTabGroupId, TEST_COLLABORATION_ID);
+        prepareToShareTabGroup(/* owner= */ true, getLocalTabGroupId(cta), TEST_COLLABORATION_ID);
 
         // Check share button changes to manage.
         onViewWaiting(withText(R.string.tab_grid_manage_button_text)).check(matches(isDisplayed()));
     }
 
+    @Test
+    @MediumTest
+    public void testDataSharingShowShareCancelled() {
+        setUpSyncAndSignIn();
+
+        final ChromeTabbedActivity cta = (ChromeTabbedActivity) mActivityTestRule.getActivity();
+        createTabGroupAndOpenTabGridDialog(cta);
+
+        // Setting create flow callback to cancel create flow.
+        Callback<Boolean> callback =
+                (success) -> {
+                    mDataSharingUIDelegate.forceCreateFlowCancellation();
+                };
+        mDataSharingUIDelegate.setShowCreateFlowCallback(callback);
+
+        onView(withId(R.id.share_button)).perform(relaxedClick());
+
+        // Check share button doesn't change.
+        onViewWaiting(withText(R.string.tab_grid_share_button_text)).check(matches(isDisplayed()));
+    }
+
     private static ViewAction relaxedClick() {
         final ViewAction clickAction = click();
         return new ViewAction() {
@@ -382,8 +390,33 @@
                 });
     }
 
+    // Sign in and sets selected types for tab groups.
+    private void setUpSyncAndSignIn() {
+        mActivityTestRule.setUpAccountAndSignInForTesting();
+        mActivityTestRule.setSelectedTypes(
+                true,
+                new HashSet<>(
+                        Arrays.asList(
+                                UserSelectableType.TABS, UserSelectableType.SAVED_TAB_GROUPS)));
+    }
+
+    // Returns the local tab group id.
+    private LocalTabGroupId getLocalTabGroupId(ChromeTabbedActivity cta) {
+        return new LocalTabGroupId(
+                cta.getTabModelSelector().getModel(false).getTabAt(0).getTabGroupId());
+    }
+
+    // Create a tab group and open tab grid dialog.
+    private void createTabGroupAndOpenTabGridDialog(ChromeTabbedActivity cta) {
+        addBlankTabs(cta, false, 2);
+        enterTabSwitcher(cta);
+        mergeAllNormalTabsToAGroup(cta);
+        clickFirstCardFromTabSwitcher(cta);
+        CriteriaHelper.pollUiThread(() -> isDialogFullyVisible(cta));
+    }
+
     // Mock share delegate and return success for opening the share sheet.
-    private void setupShareDelegateSupplier(){
+    private void setupShareDelegateSupplier() {
         ThreadUtils.runOnUiThreadBlocking(
                 () -> {
                     doReturn(mShareDelegate).when(mShareDelegateSupplier).get();
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/FakeDataSharingUIDelegateImpl.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/FakeDataSharingUIDelegateImpl.java
index b5a82c7..d26e753 100644
--- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/FakeDataSharingUIDelegateImpl.java
+++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/FakeDataSharingUIDelegateImpl.java
@@ -93,4 +93,10 @@
                             assert success;
                         });
     }
+
+    /* Calls onCancelClicked when showCreateFlow() is called. */
+    public void forceCreateFlowCancellation() {
+        if (mCreateUiConfig == null || mCreateUiConfig.getCreateCallback() == null) return;
+        mCreateUiConfig.getCreateCallback().onCancelClicked();
+    }
 }
diff --git a/chrome/browser/glic/widget/glic_window_controller_impl.cc b/chrome/browser/glic/widget/glic_window_controller_impl.cc
index 7ecb640..9f9d3bb 100644
--- a/chrome/browser/glic/widget/glic_window_controller_impl.cc
+++ b/chrome/browser/glic/widget/glic_window_controller_impl.cc
@@ -1013,9 +1013,6 @@
     return;
   }
 
-  // The widget may have moved without a drag event so save the final position.
-  SaveWidgetPosition();
-
   const bool reopen_detached = state_ == State::kClosingToReopenDetached;
   DCHECK(!reopen_detached || reopen_detached_source.has_value());
 
@@ -1033,6 +1030,10 @@
   if (state_ == State::kClosed) {
     return;
   }
+
+  // Save the widge position on close so we can restore in the same position.
+  SaveWidgetPosition();
+
   glic_window_animator_.reset();
   glic_service_->metrics()->OnGlicWindowClose();
   base::UmaHistogramEnumeration("Glic.PanelWebUiState.FinishState2",
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
index 78d1a4a..8d30886 100644
--- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
+++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -46,15 +46,14 @@
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
 
-using content_settings::PageSpecificContentSettings;
+using ::blink::mojom::MediaStreamRequestResult;
+using ::content_settings::PageSpecificContentSettings;
 
 class MediaStreamDevicesControllerTest : public WebRtcTestBase {
  public:
   MediaStreamDevicesControllerTest()
       : example_audio_id_("fake_audio_dev"),
-        example_video_id_("fake_video_dev"),
-        media_stream_result_(
-            blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS) {
+        example_video_id_("fake_video_dev") {
     // `kLeftHandSideActivityIndicators` should be disabled as it changes the UI
     // of the camera/mic activity indicator. The new UI will be tested
     // separately.
@@ -64,7 +63,7 @@
 
   void OnMediaStreamResponse(
       const blink::mojom::StreamDevicesSet& stream_devices_set,
-      blink::mojom::MediaStreamRequestResult result,
+      MediaStreamRequestResult result,
       std::unique_ptr<content::MediaStreamUI> ui) {
     blink::MediaStreamDevices devices_list =
         blink::ToMediaStreamDevicesList(stream_devices_set);
@@ -88,7 +87,7 @@
   const std::string& example_audio_id() const { return example_audio_id_; }
   const std::string& example_video_id() const { return example_video_id_; }
 
-  blink::mojom::MediaStreamRequestResult media_stream_result() const {
+  std::optional<MediaStreamRequestResult> media_stream_result() const {
     return media_stream_result_;
   }
 
@@ -218,7 +217,7 @@
     return prompt_factory_.get();
   }
 
-  void VerifyResultState(blink::mojom::MediaStreamRequestResult result,
+  void VerifyResultState(std::optional<MediaStreamRequestResult> result,
                          bool has_audio,
                          bool has_video) {
     EXPECT_EQ(result, media_stream_result());
@@ -246,8 +245,7 @@
 
     // Cleanup.
     media_stream_devices_.clear();
-    media_stream_result_ =
-        blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS;
+    media_stream_result_.reset();
 
     blink::MediaStreamDevices audio_devices;
     blink::MediaStreamDevice fake_audio_device(
@@ -279,7 +277,7 @@
   const std::string example_video_id_;
 
   blink::MediaStreamDevices media_stream_devices_;
-  blink::mojom::MediaStreamRequestResult media_stream_result_;
+  std::optional<MediaStreamRequestResult> media_stream_result_;
 
   base::OnceClosure quit_closure_;
 
@@ -651,18 +649,18 @@
 
   // The expected media stream result after clicking accept/deny for the given
   // inputs.
-  blink::mojom::MediaStreamRequestResult ExpectedMediaStreamResult(
+  MediaStreamRequestResult ExpectedMediaStreamResult(
       const media::VideoCaptureControlSupport& control_support) const {
     if (ExpectMicAllowed() && ExpectCamAllowed()) {
       if (!control_support.pan && !control_support.tilt &&
           !control_support.zoom) {
-        return blink::mojom::MediaStreamRequestResult::OK;
+        return MediaStreamRequestResult::OK;
       }
       if (ptz != CONTENT_SETTING_BLOCK) {
-        return blink::mojom::MediaStreamRequestResult::OK;
+        return MediaStreamRequestResult::OK;
       }
     }
-    return blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
+    return MediaStreamRequestResult::PERMISSION_DENIED;
   }
 };
 
@@ -797,7 +795,7 @@
 
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true);
+  VerifyResultState(MediaStreamRequestResult::OK, false, true);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
@@ -818,7 +816,7 @@
   ASSERT_TRUE(
       prompt_factory()->RequestTypeSeen(permissions::RequestType::kMicStream));
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true);
+  VerifyResultState(MediaStreamRequestResult::OK, true, true);
 
   // Check that re-requesting allows without prompting.
   prompt_factory()->ResetCounts();
@@ -827,7 +825,7 @@
       CreateRequest(example_audio_id(), example_video_id(), false));
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true);
+  VerifyResultState(MediaStreamRequestResult::OK, true, true);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
@@ -843,8 +841,7 @@
                             blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
-                    false, false);
+  VerifyResultState(MediaStreamRequestResult::PERMISSION_DENIED, false, false);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) {
@@ -862,9 +859,8 @@
   RequestPermissions(nullptr, request);
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(
-      blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false,
-      false);
+  VerifyResultState(MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false,
+                    false);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
@@ -888,13 +884,11 @@
       CreateRequest(example_audio_id(), example_video_id(), false),
       base::BindOnce(
           [](const blink::mojom::StreamDevicesSet& stream_devices_set,
-             blink::mojom::MediaStreamRequestResult result,
+             MediaStreamRequestResult result,
              std::unique_ptr<content::MediaStreamUI> ui) {
             // The permission may be dismissed before we have a chance to delete
             // the request.
-            EXPECT_EQ(
-                blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED,
-                result);
+            EXPECT_EQ(MediaStreamRequestResult::PERMISSION_DISMISSED, result);
           }),
       nullptr);
   // Since the mock prompt factory holds a reference to the
@@ -907,9 +901,7 @@
   EXPECT_EQ(previous_tab_count - 1, browser()->tab_strip_model()->count());
   base::RunLoop().RunUntilIdle();
 
-  VerifyResultState(
-      blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS, false,
-      false);
+  VerifyResultState(std::nullopt, false, false);
 }
 
 // Request and block microphone and camera access with kill switch.
@@ -936,8 +928,7 @@
       CreateRequest(example_audio_id(), example_video_id(), false));
 
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON,
-                    false, false);
+  VerifyResultState(MediaStreamRequestResult::KILL_SWITCH_ON, false, false);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
@@ -966,8 +957,7 @@
 
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
-                    false, false);
+  VerifyResultState(MediaStreamRequestResult::PERMISSION_DENIED, false, false);
   EXPECT_TRUE(GetContentSettings()->GetMicrophoneCameraState().empty());
 }
 
@@ -997,8 +987,7 @@
 
   ASSERT_EQ(0, prompt_factory()->TotalRequestCount());
 
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
-                    false, false);
+  VerifyResultState(MediaStreamRequestResult::PERMISSION_DENIED, false, false);
   EXPECT_TRUE(GetContentSettings()->GetMicrophoneCameraState().empty());
 }
 
@@ -1010,7 +999,7 @@
       GetWebContents(),
       CreateRequestWithType(example_audio_id(), std::string(), false,
                             blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, false);
+  VerifyResultState(MediaStreamRequestResult::OK, true, false);
 }
 
 IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
@@ -1021,5 +1010,5 @@
       GetWebContents(),
       CreateRequestWithType(std::string(), example_video_id(), false,
                             blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY));
-  VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true);
+  VerifyResultState(MediaStreamRequestResult::OK, false, true);
 }
diff --git a/chrome/browser/notifications/OWNERS b/chrome/browser/notifications/OWNERS
index 3c237e4e..e25194c 100644
--- a/chrome/browser/notifications/OWNERS
+++ b/chrome/browser/notifications/OWNERS
@@ -1,6 +1,5 @@
 dewittj@chromium.org
 dimich@chromium.org
-finnur@chromium.org
 peter@chromium.org
 yoshiki@chromium.org
 
diff --git a/chrome/browser/notifications/win/OWNERS b/chrome/browser/notifications/win/OWNERS
index 118c023..88a112d1 100644
--- a/chrome/browser/notifications/win/OWNERS
+++ b/chrome/browser/notifications/win/OWNERS
@@ -1,3 +1 @@
-finnur@chromium.org
-
 per-file notification_helper*=file://chrome/notification_helper/OWNERS
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
index abd37cf..1a6396e 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckController.java
@@ -4,10 +4,12 @@
 
 package org.chromium.chrome.browser.pwd_check_wrapper;
 
+import static org.chromium.chrome.browser.flags.ChromeFeatureList.LOGIN_DB_DEPRECATION_ANDROID;
 import static org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge.usesSplitStoresAndUPMForLocal;
 
 import org.chromium.build.annotations.NullMarked;
 import org.chromium.build.annotations.Nullable;
+import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.password_manager.PasswordCheckReferrer;
 import org.chromium.chrome.browser.password_manager.PasswordManagerHelper;
 import org.chromium.chrome.browser.password_manager.PasswordStoreBridge;
@@ -141,7 +143,9 @@
 
         // If using split stores and UPM for local passwords is enabled, the local passwords are
         // stored in the profile store.
-        if (usesSplitStoresAndUPMForLocal(mPrefService)) {
+        // After login db deprecation all users have split stores.
+        if (ChromeFeatureList.isEnabled(LOGIN_DB_DEPRECATION_ANDROID)
+                || usesSplitStoresAndUPMForLocal(mPrefService)) {
             mPasswordsCountAccountStorage.complete(
                     mPasswordStoreBridge.getPasswordStoreCredentialsCountForAccountStore());
             mPasswordsCountLocalStorage.complete(
diff --git a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckControllerTest.java b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckControllerTest.java
index 0513182..1e8c9132 100644
--- a/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckControllerTest.java
+++ b/chrome/browser/password_manager/android/pwd_check_wrapper/java/src/org/chromium/chrome/browser/pwd_check_wrapper/GmsCorePasswordCheckControllerTest.java
@@ -4,6 +4,7 @@
 
 package org.chromium.chrome.browser.pwd_check_wrapper;
 
+import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -16,10 +17,12 @@
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
+import org.robolectric.ParameterizedRobolectricTestRunner;
+import org.robolectric.ParameterizedRobolectricTestRunner.Parameter;
+import org.robolectric.ParameterizedRobolectricTestRunner.Parameters;
 import org.robolectric.annotation.Config;
 
-import org.chromium.base.test.BaseRobolectricTestRunner;
-import org.chromium.base.test.util.Features;
+import org.chromium.base.FeatureOverrides;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError;
 import org.chromium.chrome.browser.password_manager.FakePasswordCheckupClientHelper;
@@ -45,22 +48,30 @@
 import org.chromium.components.user_prefs.UserPrefs;
 import org.chromium.components.user_prefs.UserPrefsJni;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.OptionalInt;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
 /** Unit tests for {@link GmsCorePasswordCheckController}. */
-@RunWith(BaseRobolectricTestRunner.class)
+@RunWith(ParameterizedRobolectricTestRunner.class)
 @Config(manifest = Config.NONE)
 // This is only used from Safety Check v1 which will be soon deprecated in favor Safety Check v2.
 // There is still one entry point to this from the PhishGuard dialog.
-// TODO(crbug.com/397186266): Update together with the GmsCorePasswordCheckController isntantiation.
-@Features.DisableFeatures(ChromeFeatureList.LOGIN_DB_DEPRECATION_ANDROID)
 public class GmsCorePasswordCheckControllerTest {
     private static final String TEST_EMAIL_ADDRESS = "test@example.com";
 
+    @Parameters
+    public static Collection testCases() {
+        return Arrays.asList(
+                /* isLoginDbDeprecationEnabled= */ false, /* isLoginDbDeprecationEnabled= */ true);
+    }
+
     @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule();
 
+    @Parameter public boolean mIsLoginDbDeprecationEnabled;
+
     @Mock private SyncService mSyncService;
     @Mock private PasswordStoreBridge mPasswordStoreBridge;
     @Mock private Profile mProfile;
@@ -74,6 +85,11 @@
 
     @Before
     public void setUp() {
+        if (mIsLoginDbDeprecationEnabled) {
+            FeatureOverrides.enable(ChromeFeatureList.LOGIN_DB_DEPRECATION_ANDROID);
+        } else {
+            FeatureOverrides.disable(ChromeFeatureList.LOGIN_DB_DEPRECATION_ANDROID);
+        }
         setupUserProfileWithMockPrefService();
         configureMockSyncServiceToSyncPasswords();
         configurePasswordManagerBackendSupport();
@@ -89,11 +105,18 @@
     private void configurePasswordManagerBackendSupport() {
         PasswordManagerUtilBridgeJni.setInstanceForTesting(mPasswordManagerUtilBridgeNativeMock);
         PasswordManagerHelperJni.setInstanceForTesting(mPasswordManagerHelperNativeMock);
-        when(mPasswordManagerUtilBridgeNativeMock.shouldUseUpmWiring(mSyncService, mPrefService))
-                .thenReturn(true);
-        when(mPasswordManagerUtilBridgeNativeMock.usesSplitStoresAndUPMForLocal(mPrefService))
-                .thenReturn(false);
-        when(mPasswordManagerUtilBridgeNativeMock.areMinUpmRequirementsMet()).thenReturn(true);
+        if (mIsLoginDbDeprecationEnabled) {
+            when(mPasswordManagerUtilBridgeNativeMock.isPasswordManagerAvailable(
+                            mPrefService, true))
+                    .thenReturn(true);
+        } else {
+            when(mPasswordManagerUtilBridgeNativeMock.shouldUseUpmWiring(
+                            mSyncService, mPrefService))
+                    .thenReturn(true);
+            when(mPasswordManagerUtilBridgeNativeMock.usesSplitStoresAndUPMForLocal(mPrefService))
+                    .thenReturn(false);
+            when(mPasswordManagerUtilBridgeNativeMock.areMinUpmRequirementsMet()).thenReturn(true);
+        }
 
         FakePasswordManagerBackendSupportHelper helper =
                 new FakePasswordManagerBackendSupportHelper();
@@ -132,10 +155,12 @@
      * are obtained -> 10 passwords overall have been loaded.
      */
     @Test
-    public void passwordCheckResultIsCompleteNoBreachedCredentials()
+    public void passwordCheckResultIsCompleteNoBreachedCredentials_NoSplitStores()
             throws ExecutionException, InterruptedException {
+        assumeFalse(mIsLoginDbDeprecationEnabled);
         // Set fake to return 0 breached credentials.
         final int totalPasswords = 10;
+        // Before splitting stores, the account storage is backend by the profile store.
         when(mPasswordStoreBridge.getPasswordStoreCredentialsCountForProfileStore())
                 .thenReturn(totalPasswords);
         mPasswordCheckupClientHelper.setBreachedCredentialsCount(0);
@@ -151,6 +176,34 @@
     }
 
     /**
+     * The flow: checkPasswords is called -> as a result of password check 0 breached credentials
+     * are obtained -> 10 passwords overall have been loaded.
+     */
+    @Test
+    public void passwordCheckResultIsCompleteNoBreachedCredentials_SplitStores()
+            throws ExecutionException, InterruptedException {
+        // The split stores check is only important before the login db deprecation.
+        when(mPasswordManagerUtilBridgeNativeMock.usesSplitStoresAndUPMForLocal(mPrefService))
+                .thenReturn(!mIsLoginDbDeprecationEnabled);
+
+        // Set fake to return 0 breached credentials.
+        final int totalPasswords = 10;
+        when(mPasswordStoreBridge.getPasswordStoreCredentialsCountForAccountStore())
+                .thenReturn(totalPasswords);
+        when(mPasswordStoreBridge.getPasswordStoreCredentialsCountForProfileStore()).thenReturn(0);
+        mPasswordCheckupClientHelper.setBreachedCredentialsCount(0);
+        mController.onSavedPasswordsChanged(totalPasswords);
+
+        PasswordCheckResult passwordCheckResult =
+                mController.checkPasswords(PasswordStorageType.ACCOUNT_STORAGE).get();
+
+        Assert.assertEquals(OptionalInt.of(0), passwordCheckResult.getBreachedCount());
+        Assert.assertEquals(
+                OptionalInt.of(totalPasswords), passwordCheckResult.getTotalPasswordsCount());
+        Assert.assertEquals(null, passwordCheckResult.getError());
+    }
+
+    /**
      * The flow: passwords loading has finished and there are 0 passwords -> as a result of password
      * check 0 breached credentials are obtained.
      */
@@ -219,6 +272,7 @@
     @Test
     public void getBreachedCredentialsCountReturnsBackendVersionNotSupportedError()
             throws ExecutionException, InterruptedException {
+        assumeFalse(mIsLoginDbDeprecationEnabled);
         when(mPasswordManagerUtilBridgeNativeMock.isGmsCoreUpdateRequired(any(), any()))
                 .thenReturn(true);
 
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_browser_test_base.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_browser_test_base.cc
index 921828d5..92588653 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_browser_test_base.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_browser_test_base.cc
@@ -67,6 +67,7 @@
 
 void SearchPrefetchBaseBrowserTest::SetUpOnMainThread() {
   InProcessBrowserTest::SetUpOnMainThread();
+  SearchPrefetchRequest::SetIsTest();
   host_resolver()->AddRule(kSearchDomain, "127.0.0.1");
   host_resolver()->AddRule(kSuggestDomain, "127.0.0.1");
 
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.cc
index 7734fb9..6431015 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.cc
@@ -11,6 +11,8 @@
 #include <vector>
 
 #include "base/check.h"
+#include "base/check_is_test.h"
+#include "base/debug/dump_without_crashing.h"
 #include "base/functional/bind.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/metrics/histogram_functions.h"
@@ -125,8 +127,30 @@
       trace_id, base::TimeTicks::Now());
 }
 
+// TODO(crbug.com/413557424): remove this block.
+bool is_test = false;
+// Restrict per-client to report one check failure.
+bool has_reported = false;
+bool CheckPrefetchParameterExistence(const GURL& url) {
+  std::string_view query_piece = url.query_piece();
+  url::Component query(0, url.query_piece().length());
+  url::Component key, value;
+  while (url::ExtractQueryKeyValue(query_piece, &query, &key, &value)) {
+    if (query_piece.substr(key.begin, key.len) == "pf" && !value.is_empty()) {
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace
 
+// static
+void SearchPrefetchRequest::SetIsTest() {
+  CHECK_IS_TEST();
+  is_test = true;
+}
+
 SearchPrefetchRequest::SearchPrefetchRequest(
     const GURL& canonical_search_url,
     const GURL& prefetch_url,
@@ -316,6 +340,14 @@
   }
 
   prefetch_url_ = resource_request->url;
+
+  // It is quite common that a test does not specify the parameter.
+  if (!has_reported &&
+      !CheckPrefetchParameterExistence(resource_request->url) && !is_test) {
+    has_reported = true;
+    base::debug::DumpWithoutCrashing();
+  }
+
   SetSearchPrefetchStatus(SearchPrefetchStatus::kCanBeServed);
   streaming_url_loader_ =
       base::MakeRefCounted<StreamingSearchPrefetchURLLoader>(
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.h b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.h
index 7d66b30b..789f800 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.h
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_request.h
@@ -82,6 +82,8 @@
 //   more easily.
 class SearchPrefetchRequest {
  public:
+  static void SetIsTest();
+
   SearchPrefetchRequest(const GURL& canonical_search_url,
                         const GURL& prefetch_url,
                         bool navigation_prefetch,
diff --git a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
index ff58cd7..1ab7310 100644
--- a/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
+++ b/chrome/browser/preloading/prefetch/search_prefetch/search_prefetch_service_browsertest.cc
@@ -1356,21 +1356,37 @@
       "Omnibox.SearchPrefetch.DuplicateSearchTermsAge", 1);
 }
 
+enum class NVSDiskCacheEnabled {
+  kDisableAll = 0,
+  kEnableHttpCacheNoVarySearchOnly = 1,
+  kEnableSearchPrefetchWithNoVarySearchDiskCache = 2,
+};
 // Tests used for integrating to No-Vary-Search Disk Cache.
 class SearchPrefetchServiceEnabledWithNVSBrowserTest
-    : public testing::WithParamInterface<bool>,
+    : public testing::WithParamInterface<NVSDiskCacheEnabled>,
       public SearchPrefetchServiceEnabledBrowserTest {
  public:
   SearchPrefetchServiceEnabledWithNVSBrowserTest() {
-    if (GetParam()) {
-      feature_list_.InitWithFeaturesAndParameters(
-          {{net::features::kHttpCacheNoVarySearch, {{"max_entries", "1"}}},
-           {kSearchPrefetchWithNoVarySearchDiskCache, {}}},
-          /*disabled_features=*/{});
-    } else {
-      feature_list_.InitWithFeatures(
-          {}, {net::features::kHttpCacheNoVarySearch,
-               kSearchPrefetchWithNoVarySearchDiskCache});
+    switch (GetParam()) {
+      case NVSDiskCacheEnabled::kDisableAll:
+        feature_list_.InitWithFeatures(
+            /*enabled_features=*/{},
+            {net::features::kHttpCacheNoVarySearch,
+             kSearchPrefetchWithNoVarySearchDiskCache});
+        break;
+      case NVSDiskCacheEnabled::kEnableHttpCacheNoVarySearchOnly:
+        feature_list_.InitWithFeaturesAndParameters(
+            {
+                {net::features::kHttpCacheNoVarySearch, {{"max_entries", "1"}}},
+            },
+            {kSearchPrefetchWithNoVarySearchDiskCache});
+        break;
+      case NVSDiskCacheEnabled::kEnableSearchPrefetchWithNoVarySearchDiskCache:
+        feature_list_.InitWithFeaturesAndParameters(
+            {{net::features::kHttpCacheNoVarySearch, {{"max_entries", "1"}}},
+             {kSearchPrefetchWithNoVarySearchDiskCache, {}}},
+            /*disabled_features=*/{});
+        break;
     }
   }
   void SetUpOnMainThread() override {
@@ -1386,9 +1402,13 @@
   base::test::ScopedFeatureList feature_list_;
 };
 
-INSTANTIATE_TEST_SUITE_P(All,
-                         SearchPrefetchServiceEnabledWithNVSBrowserTest,
-                         testing::Bool());
+INSTANTIATE_TEST_SUITE_P(
+    All,
+    SearchPrefetchServiceEnabledWithNVSBrowserTest,
+    testing::ValuesIn(
+        {NVSDiskCacheEnabled::kDisableAll,
+         NVSDiskCacheEnabled::kEnableHttpCacheNoVarySearchOnly,
+         NVSDiskCacheEnabled::kEnableSearchPrefetchWithNoVarySearchDiskCache}));
 
 IN_PROC_BROWSER_TEST_P(SearchPrefetchServiceEnabledWithNVSBrowserTest,
                        BackPrefetchServed) {
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html
index ee53bf0..46637d3 100644
--- a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html
+++ b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.html
@@ -89,11 +89,11 @@
 
 <template is="dom-if" if="[[showingDeleteDialog_]]" restamp>
   <cr-dialog close-text="delete" show-on-attach>
-    <div slot="title">Delete this dictionary</div>
-    <div slot="body">[[dict.name]] will be permanently deleted. This action can't be undone</div>
+    <div slot="title">$i18n{japaneseDeleteDictionary}</div>
+    <div slot="body">[[i18nDialogString_(dict.name)]]</div>
     <div slot="button-container">
-        <cr-button class="cancel-button" on-click="hideDeleteDialog_">Cancel</cr-button>
-        <cr-button class="action-button" on-click="deleteDictionary_">Delete</cr-button>
+        <cr-button class="cancel-button" on-click="hideDeleteDialog_">$i18n{cancel}</cr-button>
+        <cr-button class="action-button" on-click="deleteDictionary_">$i18n{japaneseDeleteDictionaryButton}</cr-button>
     </div>
   </cr-dialog>
 </template>
\ No newline at end of file
diff --git a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts
index e666415b..dd65682 100644
--- a/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts
+++ b/chrome/browser/resources/ash/settings/os_languages_page/os_japanese_dictionary_expand.ts
@@ -10,6 +10,7 @@
 import 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js';
 
 import type {CrInputElement} from 'chrome://resources/ash/common/cr_elements/cr_input/cr_input.js';
+import {I18nMixin} from 'chrome://resources/ash/common/cr_elements/i18n_mixin.js';
 import type {BigBuffer} from 'chrome://resources/mojo/mojo/public/mojom/base/big_buffer.mojom-webui.js';
 import type {BigString} from 'chrome://resources/mojo/mojo/public/mojom/base/big_string.mojom-webui.js';
 import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -26,7 +27,8 @@
   };
 }
 
-class OsJapaneseDictionaryExpandElement extends PolymerElement {
+class OsJapaneseDictionaryExpandElement extends I18nMixin
+(PolymerElement) {
   static get is() {
     return 'os-japanese-dictionary-expand' as const;
   }
@@ -163,8 +165,13 @@
     this.dispatchEvent(
         new CustomEvent('dictionary-saved', {bubbles: true, composed: true}));
   }
+
+  private i18nDialogString_(dictName: string): string {
+    return this.i18n('japaneseDeleteDictionaryDetail', dictName);
+  }
 }
 
+
 customElements.define(
     OsJapaneseDictionaryExpandElement.is, OsJapaneseDictionaryExpandElement);
 
diff --git a/chrome/browser/safe_browsing/BUILD.gn b/chrome/browser/safe_browsing/BUILD.gn
index 79bb5c34..4e2ad1d 100644
--- a/chrome/browser/safe_browsing/BUILD.gn
+++ b/chrome/browser/safe_browsing/BUILD.gn
@@ -230,6 +230,7 @@
       "//components/no_state_prefetch/browser",
       "//components/omnibox/browser",
       "//components/password_manager/content/browser",
+      "//components/password_manager/core/browser/features:password_features",
       "//components/password_manager/core/browser/form_parsing",
       "//components/permissions",
       "//components/safe_browsing/content/browser",
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service.cc b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
index 1d5ce41..27c3ebf 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service.cc
@@ -9,6 +9,7 @@
 #include <string>
 
 #include "base/containers/contains.h"
+#include "base/feature_list.h"
 #include "base/functional/bind.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
@@ -47,6 +48,7 @@
 #include "components/enterprise/connectors/core/reporting_event_router.h"
 #include "components/google/core/common/google_util.h"
 #include "components/omnibox/common/omnibox_features.h"
+#include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
 #include "components/password_manager/core/browser/insecure_credentials_helper.h"
 #include "components/password_manager/core/browser/leak_detection_dialog_utils.h"
@@ -1142,11 +1144,16 @@
       // checkup for that store will open.
 
       bool should_show_checkup_for_local = true;
+
+      // After login db deprecation, all users have split stores.
+      bool uses_split_password_stores =
+          base::FeatureList::IsEnabled(
+              password_manager::features::kLoginDbDeprecationAndroid) ||
+          password_manager::UsesSplitStoresAndUPMForLocal(profile_->GetPrefs());
       if (credentials_store.is_account_store) {
         should_show_checkup_for_local = false;
       } else if (credentials_store.is_profile_store && is_syncing_passwords &&
-                 !password_manager::UsesSplitStoresAndUPMForLocal(
-                     profile_->GetPrefs())) {
+                 !uses_split_password_stores) {
         should_show_checkup_for_local = false;
       }
       checkup_launcher_->LaunchCheckupOnDevice(
diff --git a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
index 4569fb27..68094082 100644
--- a/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
+++ b/chrome/browser/safe_browsing/chrome_password_protection_service_unittest.cc
@@ -16,6 +16,7 @@
 #include "base/test/bind.h"
 #include "base/test/mock_callback.h"
 #include "base/test/scoped_feature_list.h"
+#include "base/test/with_feature_override.h"
 #include "build/build_config.h"
 #include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client.h"
 #include "chrome/browser/enterprise/connectors/reporting/realtime_reporting_client_factory.h"
@@ -39,6 +40,7 @@
 #include "chrome/test/base/testing_profile_manager.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/enterprise/connectors/core/reporting_test_utils.h"
+#include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/hash_password_manager.h"
 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
 #include "components/password_manager/core/browser/password_manager_test_utils.h"
@@ -1873,8 +1875,13 @@
 };
 
 class PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest
-    : public PasswordCheckupWithPhishGuardTest {
+    : public base::test::WithFeatureOverride,
+      public PasswordCheckupWithPhishGuardTest {
  public:
+  PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest()
+      : base::test::WithFeatureOverride(
+            password_manager::features::kLoginDbDeprecationAndroid) {}
+
   void SetUp() override {
     // Override the GMS version to be big enough for local UPM support, so these
     // tests still pass in bots with an outdated version.
@@ -1884,7 +1891,7 @@
   }
 };
 
-TEST_F(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
+TEST_P(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
        VerifyPhishGuardDialogOpensPasswordCheckupForAccountStoreSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
@@ -1906,7 +1913,7 @@
   SimulateChangePasswordDialogAction(/*is_syncing=*/true);
 }
 
-TEST_F(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
+TEST_P(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
        VerifyPhishGuardDialogOpensPasswordCheckupForProfileStoreSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
@@ -1929,7 +1936,7 @@
   SimulateChangePasswordDialogAction(/*is_syncing=*/true);
 }
 
-TEST_F(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
+TEST_P(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
        VerifyPhishGuardDialogOpensPasswordCheckupForProfileStoreNotSyncing) {
   service_->ConfigService(/*is_incognito=*/false,
                           /*is_extended_reporting=*/true);
@@ -1952,7 +1959,7 @@
   SimulateChangePasswordDialogAction(/*is_syncing=*/false);
 }
 
-TEST_F(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
+TEST_P(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
        VerifyPhishGuardDialogOpensSafetyCheckMenuForBothStoresSyncing) {
   feature_list_.InitWithFeatures(
       {}, {/*disabled_features=*/features::kSafetyHubLocalPasswordsModule});
@@ -1977,7 +1984,7 @@
   SimulateChangePasswordDialogAction(/*is_syncing=*/true);
 }
 
-TEST_F(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
+TEST_P(PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest,
        VerifyPhishGuardDialogOpensSafetyHubMenuForBothStoresSyncing) {
   feature_list_.InitWithFeatures(
       /*enabled_features=*/{features::kSafetyHubLocalPasswordsModule}, {});
@@ -2002,6 +2009,9 @@
   SimulateChangePasswordDialogAction(/*is_syncing=*/true);
 }
 
+INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(
+    PasswordCheckupWithPhishGuardAfterPasswordStoreSplitAndroidTest);
+
 class PasswordCheckupWithPhishGuardUPMBeforeStoreSplitAndroidTest
     : public PasswordCheckupWithPhishGuardTest {
  public:
@@ -2009,7 +2019,12 @@
     // Force split stores to be off by faking an outdated GmsCore version.
     base::android::BuildInfo::GetInstance()->set_gms_version_code_for_test("0");
     PasswordCheckupWithPhishGuardTest::SetUp();
+    feature_list_.InitAndDisableFeature(
+        password_manager::features::kLoginDbDeprecationAndroid);
   }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
 };
 
 TEST_F(
@@ -2057,6 +2072,7 @@
 
   SimulateChangePasswordDialogAction(/*is_syncing=*/true);
 }
+
 #endif
 
 }  // namespace
diff --git a/chrome/browser/sync/test/integration/exponential_backoff_helper.cc b/chrome/browser/sync/test/integration/exponential_backoff_helper.cc
index a0ba4d3..6ad80ec 100644
--- a/chrome/browser/sync/test/integration/exponential_backoff_helper.cc
+++ b/chrome/browser/sync/test/integration/exponential_backoff_helper.cc
@@ -50,15 +50,12 @@
               backoff + current_delay * syncer::kBackoffJitterFactor)};
 }
 
-// static
 std::vector<ExponentialBackoffChecker::DelayRange>
-ExponentialBackoffChecker::BuildExpectedDelayTable() {
+ExponentialBackoffChecker::BuildExpectedDelayTable(
+    base::TimeDelta initial_delay) {
   std::vector<DelayRange> delay_table;
 
-  // Start off with the initial value used for tests, where SyncTest forces a
-  // short retry time via command-line kSyncShortInitialRetryOverride.
-  delay_table.push_back(
-      CalculateDelayRange(syncer::kInitialBackoffShortRetryTime));
+  delay_table.push_back(CalculateDelayRange(initial_delay));
 
   for (size_t i = 1; i < kMaxRetriesToVerify; ++i) {
     DelayRange range;
@@ -73,9 +70,10 @@
 }
 
 ExponentialBackoffChecker::ExponentialBackoffChecker(
-    syncer::SyncServiceImpl* sync_service)
+    syncer::SyncServiceImpl* sync_service,
+    base::TimeDelta initial_delay)
     : SingleClientStatusChangeChecker(sync_service),
-      expected_delay_table_(BuildExpectedDelayTable()) {
+      expected_delay_table_(BuildExpectedDelayTable(initial_delay)) {
   // Upon construction, backoff must not have started, since it's otherwise
   // impossible to determine the precise timestamp corresponding to the first
   // backed-off sync cycle, required to predict the exponential behavior.
diff --git a/chrome/browser/sync/test/integration/exponential_backoff_helper.h b/chrome/browser/sync/test/integration/exponential_backoff_helper.h
index 9d766d3..95e39e8 100644
--- a/chrome/browser/sync/test/integration/exponential_backoff_helper.h
+++ b/chrome/browser/sync/test/integration/exponential_backoff_helper.h
@@ -17,7 +17,8 @@
 class ExponentialBackoffChecker : public SingleClientStatusChangeChecker {
  public:
   // Upon construction, it is expected that backoff hasn't started yet.
-  explicit ExponentialBackoffChecker(syncer::SyncServiceImpl* sync_service);
+  explicit ExponentialBackoffChecker(syncer::SyncServiceImpl* sync_service,
+                                     base::TimeDelta initial_delay);
   ~ExponentialBackoffChecker() override;
 
   ExponentialBackoffChecker(const ExponentialBackoffChecker&) = delete;
@@ -39,7 +40,8 @@
 
   // Helper functions to build the delay table.
   static DelayRange CalculateDelayRange(base::TimeDelta current_delay);
-  static std::vector<DelayRange> BuildExpectedDelayTable();
+  static std::vector<DelayRange> BuildExpectedDelayTable(
+      base::TimeDelta initial_delay);
 
   const std::vector<DelayRange> expected_delay_table_;
   std::vector<base::TimeDelta> actual_delays_;
diff --git a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
index 42d44e7..5bb681e 100644
--- a/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
+++ b/chrome/browser/sync/test/integration/sync_exponential_backoff_test.cc
@@ -8,6 +8,7 @@
 #include "chrome/browser/sync/test/integration/exponential_backoff_helper.h"
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "chrome/browser/sync/test/integration/updated_progress_marker_checker.h"
+#include "components/sync/engine/polling_constants.h"
 #include "components/sync/service/sync_service_impl.h"
 #include "components/sync/test/fake_server_http_post_provider.h"
 #include "content/public/test/browser_test.h"
@@ -58,7 +59,9 @@
 
   // Verify that the client goes into exponential backoff while it is unable to
   // reach the sync server.
-  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0)).Wait());
+  ASSERT_TRUE(ExponentialBackoffChecker(
+                  GetSyncService(0), syncer::kInitialBackoffImmediateRetryTime)
+                  .Wait());
 
   // Double check that the folder hasn't been committed.
   ASSERT_EQ(
@@ -101,7 +104,9 @@
 
   // Verify that the client goes into exponential backoff while it is unable to
   // reach the sync server.
-  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0)).Wait());
+  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
+                                        syncer::kInitialBackoffShortRetryTime)
+                  .Wait());
 }
 
 IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest, InternalServerError) {
@@ -118,7 +123,9 @@
 
   // Verify that the client goes into exponential backoff while it is unable to
   // reach the sync server.
-  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0)).Wait());
+  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
+                                        syncer::kInitialBackoffShortRetryTime)
+                  .Wait());
 }
 
 IN_PROC_BROWSER_TEST_F(SyncExponentialBackoffTest, TransientErrorTest) {
@@ -135,7 +142,9 @@
 
   // Verify that the client goes into exponential backoff while it is unable to
   // reach the sync server.
-  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0)).Wait());
+  ASSERT_TRUE(ExponentialBackoffChecker(GetSyncService(0),
+                                        syncer::kInitialBackoffShortRetryTime)
+                  .Wait());
 }
 
 }  // namespace
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 44b8d5b..315e2dcd8 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -1448,6 +1448,9 @@
       <message name="IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON" desc="Title of the button that will open the delete browsing data dialog.">
         Delete browsing data…
       </message>
+      <message name="IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON_ACCESSIBILITY_DESCRIPTION" desc="Accessibility description of the button that will open the delete browsing data dialog.">
+        Delete browsing data; select data to delete
+      </message>
       <message name="IDS_OPEN_FULL_CHROME_HISTORY" desc="Title of the button that will open the full history in Chrome browser from CCT history page.">
               Open full Chrome history
       </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON_ACCESSIBILITY_DESCRIPTION.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON_ACCESSIBILITY_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..d975b9b
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_OPEN_CLEAR_BROWSING_DATA_DIALOG_BUTTON_ACCESSIBILITY_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+f0125cbe76dc3701101c828cfcfbc133c7805a65
\ No newline at end of file
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
index d496df2b..b73f479 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarView.java
@@ -358,6 +358,10 @@
             return snackbar.getBackgroundColor();
         }
 
+        if (SnackbarManager.isFloatingSnackbarEnabled()) {
+            return SemanticColorUtils.getFloatingSnackbarBackgroundColor(view.getContext());
+        }
+
         return SemanticColorUtils.getSnackbarBackgroundColor(view.getContext());
     }
 
@@ -402,6 +406,9 @@
         if (SnackbarManager.isFloatingSnackbarEnabled()) {
             // Round the corners for snackbars in both tablets and non-tablets.
             mSnackbarView.setBackgroundResource(R.drawable.snackbar_background);
+            GradientDrawable backgroundDrawable =
+                    (GradientDrawable) mSnackbarView.getBackground().mutate();
+            backgroundDrawable.setColor(mBackgroundColor);
         } else if (mIsTablet) {
             // isFloatingSnackbarEnabled == false, mIsTablet == true
             // On tablet, snackbars have rounded corners.
diff --git a/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc b/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc
index ceb8f98..27863c1 100644
--- a/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc
+++ b/chrome/browser/ui/views/autofill/popup/popup_cell_utils.cc
@@ -70,6 +70,9 @@
 constexpr int kChromeRefreshIconSize = 20;
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
 constexpr int kGooglePayLogoWidth = 40;
+// The icon size used in the suggestion dropdown for displaying the Google
+// Wallet icon in the "Manage loyalty cards" entry.
+constexpr int kGoogleWalletIconSize = 20;
 #endif
 
 // The additional height of the row in case it has two lines of text.
@@ -137,6 +140,7 @@
     case Suggestion::Icon::kGoogleMonochrome:
     case Suggestion::Icon::kGooglePasswordManager:
     case Suggestion::Icon::kGooglePay:
+    case Suggestion::Icon::kGoogleWallet:
     case Suggestion::Icon::kHome:
     case Suggestion::Icon::kHttpsInvalid:
     case Suggestion::Icon::kHttpWarning:
@@ -356,6 +360,14 @@
 #else
       return ImageModelFromVectorIcon(kCreditCardIcon, kIconSize);
 #endif
+    case Suggestion::Icon::kGoogleWallet:
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+      return ImageModelFromVectorIcon(vector_icons::kGoogleWalletIcon,
+                                      kGoogleWalletIconSize);
+#else
+      return std::nullopt;
+#endif
+
     case Suggestion::Icon::kIban:
     case Suggestion::Icon::kCreate:
     case Suggestion::Icon::kOfferTag:
diff --git a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
index a84bef99..a4798fc 100644
--- a/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/frame/multi_contents_view_interactive_uitest.cc
@@ -521,8 +521,10 @@
   net::EmbeddedTestServer http_server_;
 };
 
+// TODO(crbug.com/414590951): This test has been flaky on some MacOS versions,
+// and DnD testing isn't well-supported for other platforms.
 IN_PROC_BROWSER_TEST_F(MultiContentsViewDragEntrypointsUiTest,
-                       ShowsDropTargetOnLinkDragged) {
+                       DISABLED_ShowsDropTargetOnLinkDragged) {
   RunTestSequence(
       AddInstrumentedTab(kNewTab, GetURL("/links.html"), 0),
       CheckTabIsActive(0),
@@ -579,8 +581,10 @@
   }
 };
 
+// TODO(crbug.com/414590951): This test has been flaky on some MacOS versions,
+// and DnD testing isn't well-supported for other platforms.
 IN_PROC_BROWSER_TEST_F(MultiContentsViewBookmarkDragEntrypointsUiTest,
-                       ShowsDropTargetOnBookmarkedLinkDragged) {
+                       DISABLED_ShowsDropTargetOnBookmarkedLinkDragged) {
   bookmarks::BookmarkModel* const model =
       BookmarkModelFactory::GetForBrowserContext(browser()->profile());
   const std::u16string bookmark_title = u"Bookmark";
diff --git a/chrome/browser/ui/views/location_bar/star_view.cc b/chrome/browser/ui/views/location_bar/star_view.cc
index c25715f..f9c6952 100644
--- a/chrome/browser/ui/views/location_bar/star_view.cc
+++ b/chrome/browser/ui/views/location_bar/star_view.cc
@@ -42,6 +42,7 @@
 #include "ui/views/animation/ink_drop.h"
 #include "ui/views/bubble/bubble_dialog_delegate_view.h"
 #include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
 
 StarView::StarView(CommandUpdater* command_updater,
                    Browser* browser,
@@ -81,9 +82,24 @@
   }
 }
 
+void StarView::OnWidgetDestroyed(views::Widget* widget) {
+  UpdateTooltipText();
+  if (scoped_observation_.IsObserving()) {
+    scoped_observation_.Reset();
+  }
+}
+
 void StarView::UpdateImpl() {
   SetVisible(browser_defaults::bookmarks_enabled &&
              edit_bookmarks_enabled_.GetValue());
+
+  if (GetBubble() && GetBubble()->GetWidget()) {
+    if (scoped_observation_.IsObserving()) {
+      scoped_observation_.Reset();
+    }
+
+    scoped_observation_.Observe(GetBubble()->GetWidget());
+  }
 }
 
 void StarView::OnExecuting(PageActionIconView::ExecuteSource execute_source) {
diff --git a/chrome/browser/ui/views/location_bar/star_view.h b/chrome/browser/ui/views/location_bar/star_view.h
index 9d42db03..64ed59c 100644
--- a/chrome/browser/ui/views/location_bar/star_view.h
+++ b/chrome/browser/ui/views/location_bar/star_view.h
@@ -6,16 +6,19 @@
 #define CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
 
 #include "base/memory/raw_ptr.h"
+#include "base/scoped_observation.h"
 #include "chrome/browser/ui/views/page_action/page_action_icon_view.h"
 #include "components/prefs/pref_member.h"
 #include "components/user_education/common/feature_promo/feature_promo_controller.h"
 #include "ui/base/metadata/metadata_header_macros.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_observer.h"
 
 class Browser;
 class CommandUpdater;
 
 // The star icon to show a bookmark bubble.
-class StarView : public PageActionIconView {
+class StarView : public PageActionIconView, public views::WidgetObserver {
   METADATA_HEADER(StarView, PageActionIconView)
 
  public:
@@ -30,6 +33,9 @@
   // ui::PropertyHandler:
   void AfterPropertyChange(const void* key, int64_t old_value) override;
 
+  // views::WidgetObserver overrides:
+  void OnWidgetDestroyed(views::Widget* widget) override;
+
  protected:
   // PageActionIconView:
   void UpdateImpl() override;
@@ -42,6 +48,9 @@
   void EditBookmarksPrefUpdated();
 
   BooleanPrefMember edit_bookmarks_enabled_;
+  base::ScopedObservation<views::Widget, views::WidgetObserver>
+      scoped_observation_{this};
+  base::WeakPtrFactory<StarView> weak_ptr_factory_{this};
 };
 
 #endif  // CHROME_BROWSER_UI_VIEWS_LOCATION_BAR_STAR_VIEW_H_
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
index ab1e4b85..df781743 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view.cc
@@ -235,6 +235,10 @@
       view_factory_->CreateMainPageView(std::move(initialized_callback));
   main_page_view->SetID(PageInfoViewFactory::VIEW_ID_PAGE_INFO_CURRENT_VIEW);
   page_container_->SwitchToPage(std::move(main_page_view));
+
+  auto* close_button = page_container_->GetViewByID(
+      PageInfoViewFactory::VIEW_ID_PAGE_INFO_CLOSE_BUTTON);
+  close_button->RequestFocus();
 }
 
 void PageInfoBubbleView::OpenSecurityPage() {
diff --git a/chrome/browser/ui/views/page_info/page_info_main_view.cc b/chrome/browser/ui/views/page_info/page_info_main_view.cc
index 467ec0e..e5f5f3d 100644
--- a/chrome/browser/ui/views/page_info/page_info_main_view.cc
+++ b/chrome/browser/ui/views/page_info/page_info_main_view.cc
@@ -625,6 +625,7 @@
               views::BubbleFrameView::CreateCloseButton(
                   base::BindRepeating(&PageInfoNavigationHandler::CloseBubble,
                                       base::Unretained(navigation_handler_))))
+              .SetID(PageInfoViewFactory::VIEW_ID_PAGE_INFO_CLOSE_BUTTON)
               .SetVisible(true)
               .SetProperty(views::kCrossAxisAlignmentKey,
                            views::LayoutAlignment::kStart)
diff --git a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
index 76f2c857..f1e14696 100644
--- a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
+++ b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.cc
@@ -162,7 +162,6 @@
           views::DISTANCE_TEXTFIELD_HORIZONTAL_TEXT_PADDING));
 
   set_draggable(true);
-  SetButtons(static_cast<int>(ui::mojom::DialogButton::kOk));
 #if BUILDFLAG(GOOGLE_CHROME_BRANDING)
   // Show Google Chrome Enterprise logo only for official build.
   SetExtraView(std::make_unique<LogoView>());
@@ -190,7 +189,7 @@
 
 void EnterpriseStartupDialogView::DisplayLaunchingInformationWithThrobber(
     const std::u16string& information) {
-  ResetDialog(false);
+  ResetDialog(std::nullopt);
 
   std::unique_ptr<views::Label> text = CreateText(information);
   auto throbber = std::make_unique<views::Throbber>();
@@ -204,18 +203,12 @@
 void EnterpriseStartupDialogView::DisplayErrorMessage(
     const std::u16string& error_message,
     const std::optional<std::u16string>& accept_button) {
-  ResetDialog(accept_button.has_value());
+  ResetDialog(accept_button);
   std::unique_ptr<views::Label> text = CreateText(error_message);
   auto error_icon =
       std::make_unique<views::ImageView>(ui::ImageModel::FromVectorIcon(
           kBrowserToolsErrorIcon, ui::kColorAlertHighSeverity, kIconSize));
 
-  if (accept_button) {
-    // TODO(ellyjones): This should use SetButtonLabel()
-    // instead of changing the button text directly - this might break the
-    // dialog's layout.
-    GetOkButton()->SetText(*accept_button);
-  }
   AddContent(std::move(error_icon), std::move(text));
 }
 
@@ -266,10 +259,19 @@
   return gfx::Size(kDialogContentWidth, kDialogContentHeight);
 }
 
-void EnterpriseStartupDialogView::ResetDialog(bool show_accept_button) {
-  DCHECK(GetOkButton());
+void EnterpriseStartupDialogView::ResetDialog(
+    const std::optional<std::u16string>& accept_button) {
+  if (accept_button.has_value()) {
+    SetButtons(static_cast<int>(ui::mojom::DialogButton::kOk));
+    SetButtonLabel(ui::mojom::DialogButton::kOk, *accept_button);
 
-  GetOkButton()->SetVisible(show_accept_button);
+    // TODO(https://crbug.com/414502419): Explicitly request focus to ensure the
+    // focus ring appears, as DialogDelegate::SetDefaultButton does not visually
+    // indicate focus.
+    GetOkButton()->RequestFocus();
+  } else {
+    SetButtons(static_cast<int>(ui::mojom::DialogButton::kNone));
+  }
   RemoveAllChildViews();
 }
 
diff --git a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.h b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.h
index fcc4020..c333cd6b 100644
--- a/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.h
+++ b/chrome/browser/ui/views/policy/enterprise_startup_dialog_view.h
@@ -54,8 +54,9 @@
   gfx::Size CalculatePreferredSize(
       const views::SizeBounds& available_size) const override;
 
-  // Remove all existing child views from the dialog, show/hide dialog buttons.
-  void ResetDialog(bool show_accept_button);
+  // Removes all existing child views from the dialog and sets the dialog
+  // buttons.
+  void ResetDialog(const std::optional<std::u16string>& accept_button);
   // Append child views to the content area.
   void AddContent(std::unique_ptr<views::View> icon,
                   std::unique_ptr<views::View> text);
diff --git a/chrome/browser/ui/web_applications/web_app_browser_controller.h b/chrome/browser/ui/web_applications/web_app_browser_controller.h
index 71cfb74..53c3709 100644
--- a/chrome/browser/ui/web_applications/web_app_browser_controller.h
+++ b/chrome/browser/ui/web_applications/web_app_browser_controller.h
@@ -24,8 +24,6 @@
 #include "chrome/browser/web_applications/web_app_registrar.h"
 #include "components/services/app_service/public/cpp/icon_types.h"
 #include "components/webapps/common/web_app_id.h"
-#include "third_party/liburlpattern/options.h"
-#include "third_party/liburlpattern/pattern.h"
 #include "third_party/re2/src/re2/set.h"
 #include "third_party/skia/include/core/SkColor.h"
 #include "ui/base/models/image_model.h"
diff --git a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
index 0ed54c2..3b15951 100644
--- a/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
+++ b/chrome/browser/ui/webui/ash/settings/pages/device/inputs_section.cc
@@ -473,6 +473,12 @@
       {"editDictionaryLabel", IDS_OS_SETTINGS_LANGUAGES_EDIT_DICTIONARY_LABEL},
       {"japaneseClearPersonalizationData",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_CLEAR_PERSONALIZATION_DATA},
+      {"japaneseDeleteDictionary",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY},
+      {"japaneseDeleteDictionaryDetail",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_DETAIL},
+      {"japaneseDeleteDictionaryButton",
+       IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_DICTIONARY_BUTTON},
       {"japaneseDeleteItems",
        IDS_SETTINGS_INPUT_METHOD_OPTIONS_JAPANESE_DELETE_ITEMS},
       {"japaneseConversationHistory",
diff --git a/chrome/browser/web_applications/BUILD.gn b/chrome/browser/web_applications/BUILD.gn
index aff5551..3b0bf2ffd1 100644
--- a/chrome/browser/web_applications/BUILD.gn
+++ b/chrome/browser/web_applications/BUILD.gn
@@ -426,6 +426,8 @@
 
   if (is_mac) {
     sources += [
+      "commands/rewrite_diy_icons_command.cc",
+      "commands/rewrite_diy_icons_command.h",
       "os_integration/mac/app_shim_launch.h",
       "os_integration/mac/app_shim_launch.mm",
       "os_integration/mac/app_shim_registry.cc",
@@ -959,6 +961,7 @@
 
   if (is_mac) {
     sources += [
+      "commands/rewrite_diy_icons_command_unittest.mm",
       "os_integration/mac/app_shim_registry_unittest.cc",
       "os_integration/mac/icns_encoder_unittest.cc",
       "os_integration/mac/icon_utils_unittest.mm",
diff --git a/chrome/browser/web_applications/commands/rewrite_diy_icons_command.cc b/chrome/browser/web_applications/commands/rewrite_diy_icons_command.cc
new file mode 100644
index 0000000..21535bd
--- /dev/null
+++ b/chrome/browser/web_applications/commands/rewrite_diy_icons_command.cc
@@ -0,0 +1,104 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/commands/rewrite_diy_icons_command.h"
+
+#include "base/feature_list.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/task/sequenced_task_runner.h"
+#include "chrome/browser/web_applications/commands/command_result.h"
+#include "chrome/browser/web_applications/locks/app_lock.h"
+#include "chrome/browser/web_applications/os_integration/mac/apps_folder_support.h"
+#include "chrome/browser/web_applications/os_integration/mac/web_app_shortcut_creator.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
+#include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_filter.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
+#include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "chrome/browser/web_applications/web_app_utils.h"
+#include "chrome/common/chrome_features.h"
+#include "components/webapps/browser/features.h"
+#include "components/webapps/browser/installable/installable_metrics.h"
+#include "components/webapps/common/web_app_id.h"
+
+namespace web_app {
+
+namespace {
+RewriteIconResult RecordIconMigrationResult(RewriteIconResult result) {
+  base::UmaHistogramEnumeration("WebApp.DIY.IconMigrationResult", result);
+  return result;
+}
+}  // namespace
+
+RewriteDiyIconsCommand::RewriteDiyIconsCommand(
+    const webapps::AppId& app_id,
+    base::OnceCallback<void(RewriteIconResult)> callback)
+    : WebAppCommand(
+          "RewriteDiyIconsCommand",
+          AppLockDescription({app_id}),
+          base::BindOnce(&RecordIconMigrationResult).Then(std::move(callback)),
+          std::make_tuple(RewriteIconResult::kUpdateShortcutFailed)),
+      app_id_(app_id) {
+  GetMutableDebugValue().Set("app_id", app_id_);
+}
+
+RewriteDiyIconsCommand::~RewriteDiyIconsCommand() = default;
+
+void RewriteDiyIconsCommand::StartWithLock(std::unique_ptr<AppLock> lock) {
+  lock_ = std::move(lock);
+
+  const WebAppRegistrar& registrar = lock_->registrar();
+  if (!registrar.AppMatches(app_id_, WebAppFilter::IsDiyWithOsShortcut())) {
+    CompleteAndSelfDestruct(CommandResult::kSuccess,
+                            RewriteIconResult::kUnexpectedAppStateChange);
+    return;
+  }
+
+  if (registrar.IsDiyAppIconsMarkedMaskedOnMac(app_id_)) {
+    CompleteAndSelfDestruct(CommandResult::kSuccess,
+                            RewriteIconResult::kUnexpectedAppStateChange);
+    return;
+  }
+
+  lock_->os_integration_manager().GetShortcutInfoForAppFromRegistrar(
+      app_id_, base::BindOnce(&RewriteDiyIconsCommand::OnGetShortcutInfo,
+                              weak_factory_.GetWeakPtr()));
+}
+
+void RewriteDiyIconsCommand::OnGetShortcutInfo(
+    std::unique_ptr<ShortcutInfo> info) {
+  if (!info) {
+    CompleteAndSelfDestruct(CommandResult::kFailure,
+                            RewriteIconResult::kShortcutInfoFetchFailed);
+    return;
+  }
+
+  WebAppShortcutCreator shortcut_creator(internals::GetShortcutDataDir(*info),
+                                         GetChromeAppsFolder(), info.get(),
+                                         /*use_ad_hoc_signing=*/false);
+  std::vector<base::FilePath> updated_app_paths;
+
+  if (shortcut_creator.UpdateShortcuts(
+          /*create_if_needed=*/false, &updated_app_paths)) {
+    auto update = lock_->sync_bridge().BeginUpdate();
+    WebApp* web_app = update->UpdateApp(app_id_);
+    CHECK(web_app);
+    web_app->SetDiyAppIconsMaskedOnMac(true);
+
+    CompleteAndSelfDestruct(CommandResult::kSuccess,
+                            RewriteIconResult::kUpdateSucceeded);
+    return;
+  }
+
+  CompleteAndSelfDestruct(CommandResult::kFailure,
+                          RewriteIconResult::kUpdateShortcutFailed);
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/commands/rewrite_diy_icons_command.h b/chrome/browser/web_applications/commands/rewrite_diy_icons_command.h
new file mode 100644
index 0000000..f55b9a1
--- /dev/null
+++ b/chrome/browser/web_applications/commands/rewrite_diy_icons_command.h
@@ -0,0 +1,56 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_REWRITE_DIY_ICONS_COMMAND_H_
+#define CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_REWRITE_DIY_ICONS_COMMAND_H_
+
+#include <memory>
+
+#include "base/functional/callback.h"
+#include "base/memory/weak_ptr.h"
+#include "chrome/browser/web_applications/commands/web_app_command.h"
+#include "chrome/browser/web_applications/locks/app_lock.h"
+#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
+#include "components/webapps/common/web_app_id.h"
+
+namespace web_app {
+
+struct ShortcutInfo;
+
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused. Keep in sync with RewriteIconResult
+// in tools/metrics/histograms/metadata/webapps/enums.xml.
+enum class RewriteIconResult {
+  kUnexpectedAppStateChange = 0,
+  kUpdateSucceeded = 1,
+  kShortcutInfoFetchFailed = 2,
+  kUpdateShortcutFailed = 3,
+  kMaxValue = kUpdateShortcutFailed
+};
+
+class RewriteDiyIconsCommand
+    : public WebAppCommand<AppLock, RewriteIconResult> {
+ public:
+  RewriteDiyIconsCommand(const webapps::AppId& app_id,
+                         base::OnceCallback<void(RewriteIconResult)> callback);
+
+  ~RewriteDiyIconsCommand() override;
+
+  RewriteDiyIconsCommand(const RewriteDiyIconsCommand&) = delete;
+  RewriteDiyIconsCommand& operator=(const RewriteDiyIconsCommand&) = delete;
+
+  // WebAppCommand:
+  void StartWithLock(std::unique_ptr<AppLock> lock) override;
+
+ private:
+  void OnGetShortcutInfo(std::unique_ptr<ShortcutInfo> info);
+
+  const webapps::AppId app_id_;
+  std::unique_ptr<AppLock> lock_;
+  base::WeakPtrFactory<RewriteDiyIconsCommand> weak_factory_{this};
+};
+
+}  // namespace web_app
+
+#endif  // CHROME_BROWSER_WEB_APPLICATIONS_COMMANDS_REWRITE_DIY_ICONS_COMMAND_H_
diff --git a/chrome/browser/web_applications/commands/rewrite_diy_icons_command_unittest.mm b/chrome/browser/web_applications/commands/rewrite_diy_icons_command_unittest.mm
new file mode 100644
index 0000000..63dca41
--- /dev/null
+++ b/chrome/browser/web_applications/commands/rewrite_diy_icons_command_unittest.mm
@@ -0,0 +1,292 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/web_applications/commands/rewrite_diy_icons_command.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/base_paths.h"
+#include "base/files/file_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/path_service.h"
+#include "base/test/bind.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/test_future.h"
+#include "base/time/time.h"
+#include "chrome/browser/web_applications/os_integration/mac/icon_utils.h"
+#include "chrome/browser/web_applications/os_integration/web_app_file_handler_manager.h"
+#include "chrome/browser/web_applications/os_integration/web_app_protocol_handler_manager.h"
+#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
+#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
+#include "chrome/browser/web_applications/test/web_app_test.h"
+#include "chrome/browser/web_applications/web_app.h"
+#include "chrome/browser/web_applications/web_app_command_manager.h"
+#include "chrome/browser/web_applications/web_app_command_scheduler.h"
+#include "chrome/browser/web_applications/web_app_constants.h"
+#include "chrome/browser/web_applications/web_app_helpers.h"
+#include "chrome/browser/web_applications/web_app_install_info.h"
+#include "chrome/browser/web_applications/web_app_provider.h"
+#include "chrome/browser/web_applications/web_app_registrar.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
+#include "chrome/browser/web_applications/web_app_sync_bridge.h"
+#include "components/webapps/browser/installable/installable_metrics.h"
+#include "content/public/test/test_utils.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image.h"
+#include "ui/gfx/test/sk_gmock_support.h"
+
+namespace web_app {
+
+namespace {
+
+gfx::Image LoadTestIcon(const char* filename) {
+  base::FilePath data_root =
+      base::PathService::CheckedGet(base::DIR_SRC_TEST_DATA_ROOT);
+  base::FilePath image_path =
+      data_root.Append(FILE_PATH_LITERAL("chrome/test/data/web_apps/"))
+          .Append(filename);
+  std::string png_data;
+  base::ReadFileToString(image_path, &png_data);
+  return gfx::Image::CreateFrom1xPNGBytes(base::as_byte_span(png_data));
+}
+
+}  // namespace
+
+class RewriteDiyIconsCommandTest : public WebAppTest {
+ public:
+  RewriteDiyIconsCommandTest() = default;
+  ~RewriteDiyIconsCommandTest() override = default;
+
+  void SetUp() override {
+    WebAppTest::SetUp();
+    auto* provider = FakeWebAppProvider::Get(profile());
+    provider->UseRealOsIntegrationManager();
+
+    test::AwaitStartWebAppProviderAndSubsystems(profile());
+  }
+
+  void TearDown() override {
+    EXPECT_TRUE(test::UninstallAllWebApps(profile()));
+    WebAppTest::TearDown();
+  }
+
+  WebAppRegistrar& registrar() { return fake_provider().registrar_unsafe(); }
+
+  // Get the OsIntegrationTestOverrideImpl instance.
+  scoped_refptr<OsIntegrationTestOverrideImpl> GetTestOverride() {
+    return OsIntegrationTestOverrideImpl::Get();
+  }
+
+  // Explicitly sets the DIY app's masked state to `masked_on_mac`.
+  webapps::AppId InstallDiyApp(bool set_masked_on_mac = false) {
+    auto install_info = std::make_unique<WebAppInstallInfo>(
+        GURL("https://example.com/manifest"), GURL("https://example.com/app"));
+    install_info->title = u"Test DIY App";
+    install_info->scope = GURL("https://example.com/");
+    install_info->is_diy_app = true;
+
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(32, 32);
+    bitmap.eraseColor(SK_ColorBLUE);
+    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+    image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, 1.0f));
+    install_info->icon_bitmaps.any[icon_size::k32] = bitmap;
+
+    auto web_app_id = test::InstallWebApp(profile(), std::move(install_info));
+
+    // Always explicitly set the masked state to ensure we start from a known
+    // state. For migration testing, we need to ensure it starts as false.
+    ScopedRegistryUpdate update =
+        fake_provider().sync_bridge_unsafe().BeginUpdate();
+    WebApp* web_app = update->UpdateApp(web_app_id);
+    CHECK(web_app);
+
+    // Explicitly set the masked state as requested.
+    web_app->SetDiyAppIconsMaskedOnMac(set_masked_on_mac);
+
+    return web_app_id;
+  }
+
+  webapps::AppId InstallNonDiyApp() {
+    auto install_info = std::make_unique<WebAppInstallInfo>(
+        GURL("https://example.com/manifest"), GURL("https://example.com/app"));
+    install_info->title = u"Test Regular App";
+    install_info->scope = GURL("https://example.com/");
+    install_info->is_diy_app = false;
+
+    SkBitmap bitmap;
+    bitmap.allocN32Pixels(32, 32);
+    bitmap.eraseColor(SK_ColorBLUE);
+    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+    image_skia.AddRepresentation(gfx::ImageSkiaRep(bitmap, 1.0f));
+    install_info->icon_bitmaps.any[icon_size::k32] = bitmap;
+
+    return test::InstallWebApp(profile(), std::move(install_info));
+  }
+
+  // Check if app's icon is marked as masked.
+  bool IsDiyAppIconsMarkedMaskedOnMac(const webapps::AppId& app_id) {
+    return registrar().IsDiyAppIconsMarkedMaskedOnMac(app_id);
+  }
+};
+
+// Test that the actual RewriteDiyIcons command can be scheduled and executed.
+TEST_F(RewriteDiyIconsCommandTest, ScheduleAndExecuteCommand) {
+  base::HistogramTester histogram_tester;
+
+  auto disable_icon_masking = testing::SetDisableIconMaskingForTesting(true);
+
+  webapps::AppId app_id = InstallDiyApp(/*set_masked_on_mac=*/false);
+
+  auto reenable_icon_masking = testing::SetDisableIconMaskingForTesting(false);
+
+  // Get initial state and verify it's correctly set to false.
+  const WebApp* app = registrar().GetAppById(app_id);
+  EXPECT_TRUE(app);
+  EXPECT_TRUE(app->is_diy_app());
+  EXPECT_FALSE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+
+  // Record initial shortcut state.
+  std::string app_name = registrar().GetAppShortName(app_id);
+
+  // Get the installed icon.
+  std::optional<SkBitmap> installed_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+
+  // Load and compare with the original unmasked icon.
+  SkBitmap expected_bitmap;
+  expected_bitmap.allocN32Pixels(256, 256);
+  expected_bitmap.eraseColor(SK_ColorBLUE);
+  EXPECT_THAT(installed_icon.value(), gfx::test::EqualsBitmap(expected_bitmap));
+
+  base::test::TestFuture<RewriteIconResult> future;
+  fake_provider().scheduler().RewriteDiyIcons(app_id, future.GetCallback(),
+                                              FROM_HERE);
+
+  EXPECT_TRUE(future.Wait());
+
+  // Verify the rewrite operation result was successful.
+  EXPECT_EQ(future.Get(), RewriteIconResult::kUpdateSucceeded);
+
+  // Verify icon flag was updated from false to true.
+  EXPECT_TRUE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+
+  // Verify shortcut existence state (newly created or existing).
+  EXPECT_TRUE(
+      GetTestOverride()->IsShortcutCreated(profile(), app_id, app_name));
+
+  // Get the current icon.
+  std::optional<SkBitmap> current_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+  EXPECT_TRUE(current_icon.has_value());
+
+  // compare with the original icon.
+  EXPECT_THAT(current_icon.value(),
+              ::testing::Not(gfx::test::EqualsBitmap(expected_bitmap)));
+
+  // Load and compare with the expected icon.
+  gfx::Image expected_icon = LoadTestIcon("diy_app_updated_128x128_icon.png");
+
+  EXPECT_THAT(current_icon.value(),
+              gfx::test::EqualsBitmap(expected_icon.AsBitmap()));
+
+  histogram_tester.ExpectUniqueSample(
+      "WebApp.DIY.IconMigrationResult",
+      static_cast<int>(RewriteIconResult::kUpdateSucceeded), 1);
+}
+
+// Test that the actual RewriteDiyIcons command correctly handles non-DIY apps.
+TEST_F(RewriteDiyIconsCommandTest, ScheduleCommandForNonDiyApp) {
+  auto disable_icon_masking = testing::SetDisableIconMaskingForTesting(true);
+
+  webapps::AppId app_id = InstallNonDiyApp();
+
+  auto reenable_icon_masking = testing::SetDisableIconMaskingForTesting(false);
+
+  // Get initial state.
+  const WebApp* app = registrar().GetAppById(app_id);
+  EXPECT_TRUE(app);
+  EXPECT_FALSE(app->is_diy_app());
+  EXPECT_FALSE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+
+  std::string app_name = registrar().GetAppShortName(app_id);
+
+  // Get the installed icon.
+  std::optional<SkBitmap> installed_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+
+  // Load and compare with the original unmasked icon.
+  SkBitmap expected_bitmap;
+  expected_bitmap.allocN32Pixels(256, 256);
+  expected_bitmap.eraseColor(SK_ColorBLUE);
+  EXPECT_THAT(installed_icon.value(), gfx::test::EqualsBitmap(expected_bitmap));
+
+  base::test::TestFuture<RewriteIconResult> future;
+  fake_provider().scheduler().RewriteDiyIcons(app_id, future.GetCallback(),
+                                              FROM_HERE);
+
+  std::optional<SkBitmap> current_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+  EXPECT_TRUE(current_icon.has_value());
+  EXPECT_THAT(current_icon.value(), gfx::test::EqualsBitmap(expected_bitmap));
+
+  EXPECT_TRUE(future.Wait());
+
+  EXPECT_EQ(future.Get(), RewriteIconResult::kUnexpectedAppStateChange);
+
+  EXPECT_FALSE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+}
+
+// Test that the actual RewriteDiyIcons command correctly handles already masked
+// apps.
+TEST_F(RewriteDiyIconsCommandTest, ScheduleCommandForAlreadyMaskedApp) {
+  auto disable_icon_masking = testing::SetDisableIconMaskingForTesting(true);
+
+  webapps::AppId app_id = InstallDiyApp(/*set_masked_on_mac=*/true);
+
+  auto reenable_icon_masking = testing::SetDisableIconMaskingForTesting(false);
+  // Get initial state.
+  const WebApp* app = registrar().GetAppById(app_id);
+  EXPECT_TRUE(app);
+  EXPECT_TRUE(app->is_diy_app());
+  EXPECT_TRUE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+
+  std::string app_name = registrar().GetAppShortName(app_id);
+
+  // Get the installed icon.
+  std::optional<SkBitmap> installed_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+
+  // Load and compare with the original unmasked icon.
+  SkBitmap expected_bitmap;
+  expected_bitmap.allocN32Pixels(256, 256);
+  expected_bitmap.eraseColor(SK_ColorBLUE);
+  EXPECT_THAT(installed_icon.value(), gfx::test::EqualsBitmap(expected_bitmap));
+
+  base::test::TestFuture<RewriteIconResult> future;
+  fake_provider().scheduler().RewriteDiyIcons(app_id, future.GetCallback(),
+                                              FROM_HERE);
+
+  std::optional<SkBitmap> current_icon = GetTestOverride()->GetShortcutIcon(
+      profile(), std::make_optional(GetTestOverride()->chrome_apps_folder()),
+      app_id, app_name);
+  EXPECT_TRUE(current_icon.has_value());
+  EXPECT_THAT(current_icon.value(), gfx::test::EqualsBitmap(expected_bitmap));
+
+  EXPECT_TRUE(future.Wait());
+
+  EXPECT_EQ(future.Get(), RewriteIconResult::kUnexpectedAppStateChange);
+
+  EXPECT_TRUE(IsDiyAppIconsMarkedMaskedOnMac(app_id));
+}
+
+}  // namespace web_app
diff --git a/chrome/browser/web_applications/os_integration/mac/icon_utils.h b/chrome/browser/web_applications/os_integration/mac/icon_utils.h
index dc386abb..1e9e6e95 100644
--- a/chrome/browser/web_applications/os_integration/mac/icon_utils.h
+++ b/chrome/browser/web_applications/os_integration/mac/icon_utils.h
@@ -5,6 +5,8 @@
 #ifndef CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_MAC_ICON_UTILS_H_
 #define CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_MAC_ICON_UTILS_H_
 
+#include "base/auto_reset.h"
+
 @class NSImage;
 @class NSImageRep;
 namespace gfx {
@@ -32,6 +34,12 @@
 // `overlay` over it using NSCompositingOperationSourceOver.
 NSImageRep* OverlayImageRep(NSImage* background, NSImageRep* overlay);
 
+namespace testing {
+// Sets whether icon masking should be disabled for testing purposes.
+[[nodiscard]] base::AutoReset<bool> SetDisableIconMaskingForTesting(
+    bool disabled);
+}  // namespace testing
+
 }  // namespace web_app
 
 #endif  // CHROME_BROWSER_WEB_APPLICATIONS_OS_INTEGRATION_MAC_ICON_UTILS_H_
diff --git a/chrome/browser/web_applications/os_integration/mac/icon_utils.mm b/chrome/browser/web_applications/os_integration/mac/icon_utils.mm
index d8986b6..d2c2a919 100644
--- a/chrome/browser/web_applications/os_integration/mac/icon_utils.mm
+++ b/chrome/browser/web_applications/os_integration/mac/icon_utils.mm
@@ -251,6 +251,16 @@
 
 namespace web_app {
 
+namespace testing {
+namespace {
+bool g_disable_icon_masking_for_testing = false;
+}  // namespace
+
+base::AutoReset<bool> SetDisableIconMaskingForTesting(bool disabled) {
+  return base::AutoReset<bool>(&g_disable_icon_masking_for_testing, disabled);
+}
+}  // namespace testing
+
 gfx::Image CreateAppleMaskedAppIcon(const gfx::Image& base_icon) {
   int base_size = base_icon.Width();
   IconGridParameters params = GetIconGridParameters(base_size);
@@ -303,6 +313,10 @@
 }
 
 gfx::Image MaskDiyAppIcon(const gfx::Image& icon) {
+  if (testing::g_disable_icon_masking_for_testing) {
+    return icon;
+  }
+
   // If the alpha value of the color is less than this value then it is ignored
   constexpr uint8_t kMinAlpha = 1;
   // Maximum allowed deviation between RGB components of colors outside the mask
diff --git a/chrome/browser/web_applications/tabbed_mode_scope_matcher_unittest.cc b/chrome/browser/web_applications/tabbed_mode_scope_matcher_unittest.cc
index 78398d2..bee37b6e 100644
--- a/chrome/browser/web_applications/tabbed_mode_scope_matcher_unittest.cc
+++ b/chrome/browser/web_applications/tabbed_mode_scope_matcher_unittest.cc
@@ -4,16 +4,20 @@
 
 #include "chrome/browser/web_applications/tabbed_mode_scope_matcher.h"
 
+#include "base/types/expected.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/status/status.h"
 #include "third_party/blink/public/common/safe_url_pattern.h"
 #include "third_party/liburlpattern/parse.h"
+#include "third_party/liburlpattern/pattern.h"
 #include "url/gurl.h"
 
 namespace {
 
 std::vector<liburlpattern::Part> ParsePatternInitField(std::string_view field) {
-  auto parse_result = liburlpattern::Parse(
-      field, [](std::string_view input) { return std::string(input); });
+  base::expected<liburlpattern::Pattern, absl::Status> parse_result =
+      liburlpattern::Parse(
+          field, [](std::string_view input) { return std::string(input); });
 
   // Should never fail because the input is coming from the test.
   DCHECK(parse_result.has_value());
diff --git a/chrome/browser/web_applications/test/fake_os_integration_manager.cc b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
index 323ce32..89480db3 100644
--- a/chrome/browser/web_applications/test/fake_os_integration_manager.cc
+++ b/chrome/browser/web_applications/test/fake_os_integration_manager.cc
@@ -53,9 +53,10 @@
 void FakeOsIntegrationManager::GetShortcutInfoForAppFromRegistrar(
     const webapps::AppId& app_id,
     GetShortcutInfoCallback callback) {
-  if (shortcut_info_map_.find(app_id) != shortcut_info_map_.end()) {
-    std::move(callback).Run(std::move(shortcut_info_map_[app_id]));
-    shortcut_info_map_.erase(app_id);
+  auto it = shortcut_info_map_.find(app_id);
+  if (it != shortcut_info_map_.end()) {
+    std::move(callback).Run(std::move(it->second));
+    shortcut_info_map_.erase(it);
   } else {
     std::move(callback).Run(nullptr);
   }
diff --git a/chrome/browser/web_applications/test/fake_web_app_provider.h b/chrome/browser/web_applications/test/fake_web_app_provider.h
index 6d9d6a6..e822b2fd8 100644
--- a/chrome/browser/web_applications/test/fake_web_app_provider.h
+++ b/chrome/browser/web_applications/test/fake_web_app_provider.h
@@ -227,7 +227,7 @@
   AutomaticIwaUpdateStrategy automatic_iwa_update_strategy_ =
       AutomaticIwaUpdateStrategy::kForceDisabled;
 
-  testing::NiceMock<syncer::MockDataTypeLocalChangeProcessor> mock_processor_;
+  ::testing::NiceMock<syncer::MockDataTypeLocalChangeProcessor> mock_processor_;
 };
 
 // Used in BrowserTests to ensure that the WebAppProvider that is create on
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.cc b/chrome/browser/web_applications/web_app_command_scheduler.cc
index c718919..2ee2a7d 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.cc
+++ b/chrome/browser/web_applications/web_app_command_scheduler.cc
@@ -96,6 +96,10 @@
 #include "chrome/browser/web_applications/jobs/link_capturing.h"
 #endif
 
+#if BUILDFLAG(IS_MAC)
+#include "chrome/browser/web_applications/commands/rewrite_diy_icons_command.h"
+#endif  // BUILDFLAG(IS_MAC)
+
 namespace web_app {
 
 WebAppCommandScheduler::WebAppCommandScheduler(Profile& profile)
@@ -649,6 +653,17 @@
       location);
 }
 
+#if BUILDFLAG(IS_MAC)
+void WebAppCommandScheduler::RewriteDiyIcons(
+    const webapps::AppId& app_id,
+    base::OnceCallback<void(RewriteIconResult)> callback,
+    const base::Location& from_here) {
+  provider_->command_manager().ScheduleCommand(
+      std::make_unique<RewriteDiyIconsCommand>(app_id, std::move(callback)),
+      from_here);
+}
+#endif  // BUILDFLAG(IS_MAC)
+
 void WebAppCommandScheduler::ScheduleDedupeInstallUrls(
     base::OnceClosure callback,
     const base::Location& location) {
diff --git a/chrome/browser/web_applications/web_app_command_scheduler.h b/chrome/browser/web_applications/web_app_command_scheduler.h
index 2388358..1ea7cea 100644
--- a/chrome/browser/web_applications/web_app_command_scheduler.h
+++ b/chrome/browser/web_applications/web_app_command_scheduler.h
@@ -84,6 +84,9 @@
 enum class CopyBundleToCacheError;
 #endif  // BUILDFLAG(IS_CHROMEOS)
 
+#if BUILDFLAG(IS_MAC)
+enum class RewriteIconResult;
+#endif  // BUILDFLAG(IS_MAC)
 // The command scheduler is the main API to access the web app system. The
 // scheduler internally ensures:
 // * Operations occur after the WebAppProvider is ready (so you don't have to
@@ -557,6 +560,16 @@
                           base::OnceClosure callback,
                           const base::Location& location = FROM_HERE);
 
+#if BUILDFLAG(IS_MAC)
+  // Rewrites icons for an app if and only if it is a DIY app, where this
+  // operation has not yet occurred (e.g. WebApp::diy_app_icons_masked_on_mac()
+  // returns false). This will set diy_app_icons_masked_on_mac() to true when
+  // complete.
+  void RewriteDiyIcons(const webapps::AppId& app_id,
+                       base::OnceCallback<void(RewriteIconResult)> callback,
+                       const base::Location& location = FROM_HERE);
+#endif  // BUILDFLAG(IS_MAC)
+
   // Finds web apps that share the same install URLs (possibly across different
   // install sources) and dedupes the install URL configs into the most
   // recently installed non-placeholder-like web app.
diff --git a/chrome/browser/web_applications/web_app_filter.cc b/chrome/browser/web_applications/web_app_filter.cc
index ac7c2ba7..1c9c528 100644
--- a/chrome/browser/web_applications/web_app_filter.cc
+++ b/chrome/browser/web_applications/web_app_filter.cc
@@ -84,4 +84,11 @@
   return filter;
 }
 
+// static
+WebAppFilter WebAppFilter::IsDiyWithOsShortcut() {
+  WebAppFilter filter;
+  filter.is_diy_with_os_shortcut_ = true;
+  return filter;
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_filter.h b/chrome/browser/web_applications/web_app_filter.h
index 2fc8ec4..f277263 100644
--- a/chrome/browser/web_applications/web_app_filter.h
+++ b/chrome/browser/web_applications/web_app_filter.h
@@ -42,6 +42,9 @@
   // integrated into the OS. This function should only be used for testing.
   static WebAppFilter InstalledInOperatingSystemForTesting();
 
+  // Only consider web apps that are DIY apps with OS shortcuts.
+  static WebAppFilter IsDiyWithOsShortcut();
+
   WebAppFilter& operator=(const WebAppFilter&) = delete;
   ~WebAppFilter() = default;
 
@@ -66,6 +69,7 @@
   bool supports_os_notifications_ = false;
   bool installed_in_chrome_ = false;
   bool installed_in_os_ = false;
+  bool is_diy_with_os_shortcut_ = false;
 };
 
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_management_type.h b/chrome/browser/web_applications/web_app_management_type.h
index e8205e2e..ebb81c8 100644
--- a/chrome/browser/web_applications/web_app_management_type.h
+++ b/chrome/browser/web_applications/web_app_management_type.h
@@ -85,6 +85,7 @@
     WebAppManagement::kOem,
     WebAppManagement::kOneDriveIntegration,
     WebAppManagement::kIwaUserInstalled,
+    WebAppManagement::kIwaShimlessRma,
 };
 
 // Management types that resulted from a user web app install.
diff --git a/chrome/browser/web_applications/web_app_provider.cc b/chrome/browser/web_applications/web_app_provider.cc
index 95d68f1..57e6c676 100644
--- a/chrome/browser/web_applications/web_app_provider.cc
+++ b/chrome/browser/web_applications/web_app_provider.cc
@@ -19,7 +19,6 @@
 #include "base/location.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/run_loop.h"
-#include "base/types/pass_key.h"
 #include "build/build_config.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/web_applications/commands/web_app_command.h"
@@ -66,12 +65,30 @@
 #include "chromeos/ash/components/browser_context_helper/browser_context_types.h"
 #endif
 
+#if BUILDFLAG(IS_MAC)
+#include "base/feature_list.h"
+#include "base/mac/mac_util.h"
+#include "base/metrics/histogram_functions.h"
+#include "base/rand_util.h"
+#include "chrome/browser/web_applications/commands/rewrite_diy_icons_command.h"
+#include "chrome/browser/web_applications/os_integration/mac/apps_folder_support.h"
+#include "chrome/browser/web_applications/os_integration/mac/web_app_shortcut_creator.h"
+#include "chrome/browser/web_applications/os_integration/web_app_shortcut.h"
+#include "chrome/browser/web_applications/web_app_registry_update.h"
+#include "content/public/browser/browser_thread.h"
+#endif
 namespace webapps {
 enum class WebappInstallSource;
 }
 
 namespace web_app {
 
+#if BUILDFLAG(IS_MAC)
+BASE_FEATURE(kDiyAppIconsMaskedOnMacUpdate,
+             "DiyAppIconsMaskedOnMacUpdate",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+#endif
+
 // static
 WebAppProvider* WebAppProvider::GetDeprecated(Profile* profile) {
   return WebAppProviderFactory::GetForProfile(profile);
@@ -487,6 +504,17 @@
 
   on_registry_ready_.Signal();
   is_registry_ready_ = true;
+
+#if BUILDFLAG(IS_MAC)
+  if (base::FeatureList::IsEnabled(kDiyAppIconsMaskedOnMacUpdate)) {
+    content::GetUIThreadTaskRunner({base::TaskPriority::BEST_EFFORT})
+        ->PostDelayedTask(
+            FROM_HERE,
+            base::BindOnce(&WebAppProvider::DoDelayedPostStartupWork,
+                           AsWeakPtr()),
+            base::Minutes(1));
+  }
+#endif
 }
 
 void WebAppProvider::CheckIsConnected() const {
@@ -495,4 +523,33 @@
                         "for on_registry_ready().";
 }
 
+#if BUILDFLAG(IS_MAC)
+void WebAppProvider::DoDelayedPostStartupWork() {
+  CHECK(base::FeatureList::IsEnabled(kDiyAppIconsMaskedOnMacUpdate));
+
+  const WebAppRegistrar& registrar = registrar_unsafe();
+
+  for (const auto& app : registrar.GetApps()) {
+    // Skip apps that don't match our criteria
+    if (!registrar.AppMatches(app.app_id(),
+                              WebAppFilter::IsDiyWithOsShortcut())) {
+      continue;
+    }
+
+    // Skip apps that are already masked
+    if (registrar.IsDiyAppIconsMarkedMaskedOnMac(app.app_id())) {
+      continue;
+    }
+
+    // Skip apps with open windows
+    if (ui_manager_->GetNumWindowsForApp(app.app_id()) != 0) {
+      continue;
+    }
+
+    // Schedule the command for eligible apps
+    scheduler().RewriteDiyIcons(app.app_id(), base::DoNothing());
+  }
+}
+#endif
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_provider.h b/chrome/browser/web_applications/web_app_provider.h
index f4daadb..ca19b30 100644
--- a/chrome/browser/web_applications/web_app_provider.h
+++ b/chrome/browser/web_applications/web_app_provider.h
@@ -242,6 +242,10 @@
   // Returns a nullptr in the default implementation
   virtual FakeWebAppProvider* AsFakeWebAppProviderForTesting();
 
+#if BUILDFLAG(IS_MAC)
+  void DoDelayedPostStartupWork();
+#endif
+
  protected:
   virtual void StartImpl();
 
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc
index a9c75ef..59ba2fd 100644
--- a/chrome/browser/web_applications/web_app_registrar.cc
+++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -861,6 +861,12 @@
     return !IsDiyApp(app_id);
   }
 
+  if (filter.is_diy_with_os_shortcut_) {
+    const WebApp* app = GetAppById(app_id);
+    return app && app->is_diy_app() &&
+           install_state == proto::INSTALLED_WITH_OS_INTEGRATION;
+  }
+
   if (filter.displays_badge_on_os_ || filter.supports_os_notifications_) {
     return install_state == proto::INSTALLED_WITH_OS_INTEGRATION;
   }
@@ -1945,4 +1951,10 @@
                          num_non_syncing_user_installed);
 }
 
+bool WebAppRegistrar::IsDiyAppIconsMarkedMaskedOnMac(
+    const webapps::AppId& app_id) const {
+  const WebApp* app = GetAppById(app_id);
+  return app && app->is_diy_app() && app->diy_app_icons_masked_on_mac();
+}
+
 }  // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_registrar.h b/chrome/browser/web_applications/web_app_registrar.h
index 202c400..6ed83c8 100644
--- a/chrome/browser/web_applications/web_app_registrar.h
+++ b/chrome/browser/web_applications/web_app_registrar.h
@@ -501,6 +501,9 @@
                                                   bool show);
 #endif
 
+  // Returns whether the DIY app's icons are marked as masked on Mac.
+  bool IsDiyAppIconsMarkedMaskedOnMac(const webapps::AppId& app_id) const;
+
   void AddObserver(WebAppRegistrarObserver* observer);
   void RemoveObserver(WebAppRegistrarObserver* observer);
 
diff --git a/chrome/browser/webid/BUILD.gn b/chrome/browser/webid/BUILD.gn
index 6991549..62cb6ed 100644
--- a/chrome/browser/webid/BUILD.gn
+++ b/chrome/browser/webid/BUILD.gn
@@ -7,7 +7,7 @@
 
 android_library("java") {
   sources = [
-    "android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegateImplementation.java",
+    "android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegate.java",
     "android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsPresentationDelegate.java",
     "android/java/src/org/chromium/chrome/browser/webid/DigitalIdentityProvider.java",
     "android/java/src/org/chromium/chrome/browser/webid/IdentityCredentialsDelegate.java",
diff --git a/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegateImplementation.java b/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegate.java
similarity index 97%
rename from chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegateImplementation.java
rename to chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegate.java
index 8fef243..a82ff03 100644
--- a/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegateImplementation.java
+++ b/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/DigitalCredentialsCreationDelegate.java
@@ -30,8 +30,8 @@
 import org.chromium.build.annotations.NullMarked;
 
 @NullMarked
-public class DigitalCredentialsCreationDelegateImplementation {
-    private static final String TAG = "DCCreateDelegateImpl";
+public class DigitalCredentialsCreationDelegate {
+    private static final String TAG = "DCCreationDelegate";
 
     // Arbitrary request code that is used when invoking the GMSCore API.
     private static final int REQUEST_CODE_DIGITAL_CREDENTIALS_CREATION = 777;
diff --git a/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/IdentityCredentialsDelegate.java b/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/IdentityCredentialsDelegate.java
index 7d5161b..44fe13d 100644
--- a/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/IdentityCredentialsDelegate.java
+++ b/chrome/browser/webid/android/java/src/org/chromium/chrome/browser/webid/IdentityCredentialsDelegate.java
@@ -41,8 +41,8 @@
     }
 
     public Promise<String> create(Activity window, String origin, String request) {
-        DigitalCredentialsCreationDelegateImplementation creationDelegate =
-                new DigitalCredentialsCreationDelegateImplementation();
+        DigitalCredentialsCreationDelegate creationDelegate =
+                new DigitalCredentialsCreationDelegate();
         return creationDelegate.create(window, origin, request);
     }
 }
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index 4de393b2..f8b0bb21 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1746748670-2ec1d34d52d69562137d213db1c31c74f5cd066f-1207e2173d79ef83a8e573890fa04e804afca8de.profdata
+chrome-android32-main-1746770214-85e3ff20dbe5fbc1fbdcc2f27c5216f1cc36173a-138306eae26b21ffa7139d2f39324827708eee3e.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index b05e3f8..e6ce547 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1746748670-e30c706e068b0e4acf605ef75468e713d1723c88-1207e2173d79ef83a8e573890fa04e804afca8de.profdata
+chrome-android64-main-1746778608-03cafa167ccfd98d7f7fa596e3c804a3697ee966-f8e3fd713bce1388b96bac43cda4286e03004bf7.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index bb325f9..629222c 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1746521668-853707a3e7deddc24f14363c9efa6fbd73111c58-b1de5d6bd7ba01d3806a69ca2a3f8726cd47bdce.profdata
+chrome-android-desktop-x64-main-1746744561-1e2ed49e23c5c367b2e7c480eb8ef6551db5f07f-53da0a30ea660dfbc0131525a44a6b9616ff07cb.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index ca0d68f..afbdc133 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1746727053-8bffbdf05c0e2a814cf7e11b77bd671857ac0e9a-8a7e3eb58b861bad419563c7eab04a42cd628814.profdata
+chrome-linux-main-1746770214-e9e8b5d7d1fba0a8407ea1dd5071caba050ec5fb-138306eae26b21ffa7139d2f39324827708eee3e.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index 5be0e9a..96a5b19 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1746748670-a98f730b785ee81b3fc972377e3fb791da3dda8f-1207e2173d79ef83a8e573890fa04e804afca8de.profdata
+chrome-mac-arm-main-1746784599-a43c3308e0f8fe89ce3ca0119eab01349db52f31-3ca3e0c36e96013871cc2ac817803e7269d32a95.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 95ce86e4..9e6c96c 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1746727053-a3d66ff1fe809b42166d1a8ecea42b77ac02ce2a-8a7e3eb58b861bad419563c7eab04a42cd628814.profdata
+chrome-mac-main-1746770214-df239f1b6f9d1ece535bc0c3c80816809e2a3387-138306eae26b21ffa7139d2f39324827708eee3e.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt
index 96ec547..c5cce9b 100644
--- a/chrome/build/win-arm64.pgo.txt
+++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@
-chrome-win-arm64-main-1746727053-9915f3cafb45e9b9e2f98fcd1d5170db100e5af0-8a7e3eb58b861bad419563c7eab04a42cd628814.profdata
+chrome-win-arm64-main-1746770214-3a984bff321e6159d531a9d2ca7aa7e2bce4b666-138306eae26b21ffa7139d2f39324827708eee3e.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 0eaaef3..2e4770c 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1746727053-8236c72987ba273680c6f01e32b6737857aea696-8a7e3eb58b861bad419563c7eab04a42cd628814.profdata
+chrome-win32-main-1746759389-a80b8166ea153c1c6d706e5092ee4d31d49e4041-5fc67995854e822b9f72ce7db6df7a9d9671e239.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 17b73c02..d833d1a 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1746705526-0d35afe1bf28d770dc921d45bfb35fab421ede29-d85876276c358c68ff50521bcaa24e5d3998dc14.profdata
+chrome-win64-main-1746759389-7c457fac4eedb1027d1533a33dd5dc5f183e7019-5fc67995854e822b9f72ce7db6df7a9d9671e239.profdata
diff --git a/chrome/notification_helper/OWNERS b/chrome/notification_helper/OWNERS
index 0d991fbf..bdbf9f3b 100644
--- a/chrome/notification_helper/OWNERS
+++ b/chrome/notification_helper/OWNERS
@@ -1,3 +1,2 @@
-finnur@chromium.org
 grt@chromium.org
 robliao@chromium.org
diff --git a/chrome/test/data/web_apps/diy_app_updated_128x128_icon.png b/chrome/test/data/web_apps/diy_app_updated_128x128_icon.png
new file mode 100644
index 0000000..49baf85
--- /dev/null
+++ b/chrome/test/data/web_apps/diy_app_updated_128x128_icon.png
Binary files differ
diff --git a/chromeos/ash/components/boca/on_task/BUILD.gn b/chromeos/ash/components/boca/on_task/BUILD.gn
index 7b521823..431d1987 100644
--- a/chromeos/ash/components/boca/on_task/BUILD.gn
+++ b/chromeos/ash/components/boca/on_task/BUILD.gn
@@ -37,6 +37,7 @@
     "//components/pref_registry",
     "//components/sessions",
     "//components/sessions:session_id",
+    "//components/url_matcher",
     "//content/public/browser",
     "//ui/message_center",
   ]
diff --git a/chromeos/ash/components/boca/on_task/DEPS b/chromeos/ash/components/boca/on_task/DEPS
index 92188bd..12f9327 100644
--- a/chromeos/ash/components/boca/on_task/DEPS
+++ b/chromeos/ash/components/boca/on_task/DEPS
@@ -3,6 +3,8 @@
   "+components/policy/core/browser",
   "+components/sessions/content/session_tab_helper.h",
   "+components/sessions/core/session_id.h",
+  "+components/url_matcher/url_matcher.h",
+  "+components/url_matcher/url_util.h",
   "+content/public/browser/web_contents.h",
   "+ui/base/l10n/l10n_util.h",
   "+ui/base/models/image_model.h",
diff --git a/chromeos/ash/components/boca/on_task/on_task_blocklist.cc b/chromeos/ash/components/boca/on_task/on_task_blocklist.cc
index b0756811..43a5cfa4 100644
--- a/chromeos/ash/components/boca/on_task/on_task_blocklist.cc
+++ b/chromeos/ash/components/boca/on_task/on_task_blocklist.cc
@@ -15,6 +15,8 @@
 #include "base/values.h"
 #include "components/google/core/common/google_util.h"
 #include "components/sessions/content/session_tab_helper.h"
+#include "components/url_matcher/url_matcher.h"
+#include "components/url_matcher/url_util.h"
 #include "content/public/browser/web_contents.h"
 
 namespace {
@@ -69,6 +71,16 @@
   CleanupBlocklist();
 }
 
+// static
+bool OnTaskBlocklist::IsURLInDomain(const GURL& url, const GURL& domain_url) {
+  base::Value::List domain_level_traffic_filter =
+      GetDomainLevelTrafficFilter(domain_url);
+  url_matcher::URLMatcher url_matcher;
+  url_matcher::util::AddAllowFiltersWithLimit(&url_matcher,
+                                              domain_level_traffic_filter);
+  return !url_matcher.MatchURL(url).empty();
+}
+
 policy::URLBlocklist::URLBlocklistState OnTaskBlocklist::GetURLBlocklistState(
     const GURL& url) const {
   if (current_page_restriction_level_ ==
@@ -193,7 +205,7 @@
     } else if (current_page_restriction_level_ ==
                LockedNavigationOptions::
                    SAME_DOMAIN_OPEN_OTHER_DOMAIN_LIMITED_NAVIGATION) {
-      if (!url.DomainIs(previous_url_.GetWithEmptyPath().GetContentPiece())) {
+      if (!IsURLInDomain(url, previous_url_)) {
         blocklist_source = std::make_unique<OnTaskBlocklistSource>(
             url, LockedNavigationOptions::DOMAIN_NAVIGATION);
         current_page_restriction_level_ =
@@ -254,7 +266,7 @@
 
     // Same domain + 1LD navigation restriction.
     return last_committed_url.is_valid() &&
-           last_committed_url.DomainIs(one_level_deep_original_url.host());
+           IsURLInDomain(last_committed_url, one_level_deep_original_url);
   }
   return true;
 }
diff --git a/chromeos/ash/components/boca/on_task/on_task_blocklist.h b/chromeos/ash/components/boca/on_task/on_task_blocklist.h
index 61e5713..d975726 100644
--- a/chromeos/ash/components/boca/on_task/on_task_blocklist.h
+++ b/chromeos/ash/components/boca/on_task/on_task_blocklist.h
@@ -49,6 +49,12 @@
   OnTaskBlocklist& operator=(const OnTaskBlocklist&) = delete;
   ~OnTaskBlocklist();
 
+  // Returns whether the `url` is in the same domain as `domain_url` (including
+  // sub-domains). This should ideally be a standalone util method, but we leave
+  // this in here for now so we can reuse domain level filters from the domain
+  // nav restriction setup.
+  static bool IsURLInDomain(const GURL& url, const GURL& domain_url);
+
   // Returns the URLBlocklistState for the given url.
   policy::URLBlocklist::URLBlocklistState GetURLBlocklistState(
       const GURL& url) const;
diff --git a/clank b/clank
index 86901d8..183abddd 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 86901d8e9a33f78ccf07acfa57b63439e7cfa5f8
+Subproject commit 183abddd96aaf0dbb5b0c1e4e41a0f3999176462
diff --git a/components/autofill/content/browser/content_identity_credential_delegate.cc b/components/autofill/content/browser/content_identity_credential_delegate.cc
index 24db15e..0385a7a 100644
--- a/components/autofill/content/browser/content_identity_credential_delegate.cc
+++ b/components/autofill/content/browser/content_identity_credential_delegate.cc
@@ -17,6 +17,95 @@
 
 namespace autofill {
 
+namespace {
+
+Suggestion::IdentityCredentialPayload CreateFederatedProfile(
+    IdentityRequestAccountPtr account) {
+  Suggestion::IdentityCredentialPayload profile =
+      Suggestion::IdentityCredentialPayload(
+          account->identity_provider->idp_metadata.config_url, account->id);
+
+  if (!account->email.empty() &&
+      base::Contains(account->identity_provider->disclosure_fields,
+                     content::IdentityRequestDialogDisclosureField::kEmail)) {
+    profile.fields[EMAIL_ADDRESS] = base::UTF8ToUTF16(account->email);
+  }
+
+  if (!account->name.empty() &&
+      base::Contains(account->identity_provider->disclosure_fields,
+                     content::IdentityRequestDialogDisclosureField::kName)) {
+    profile.fields[NAME_FULL] = base::UTF8ToUTF16(account->name);
+  }
+
+  if (!account->phone.empty() &&
+      base::Contains(
+          account->identity_provider->disclosure_fields,
+          content::IdentityRequestDialogDisclosureField::kPhoneNumber)) {
+    profile.fields[PHONE_HOME_WHOLE_NUMBER] = base::UTF8ToUTF16(account->phone);
+  }
+
+  return profile;
+}
+
+std::optional<Suggestion> CreateVerifiedEmailSuggestion(
+    IdentityRequestAccountPtr account) {
+  Suggestion::IdentityCredentialPayload profile =
+      CreateFederatedProfile(account);
+
+  if (!profile.fields.contains(EMAIL_ADDRESS)) {
+    return std::nullopt;
+  }
+
+  Suggestion suggestion(SuggestionType::kIdentityCredential);
+  suggestion.main_text = Suggestion::Text(profile.fields[EMAIL_ADDRESS]);
+  suggestion.icon = Suggestion::Icon::kEmail;
+  suggestion.minor_texts.emplace_back(l10n_util::GetStringFUTF16(
+      IDS_AUTOFILL_IDENTITY_CREDENTIAL_VERIFIED_MINOR_TEXT,
+      base::UTF8ToUTF16(account->identity_provider->idp_for_display)));
+  suggestion.labels.push_back({Suggestion::Text(l10n_util::GetStringUTF16(
+      IDS_AUTOFILL_IDENTITY_CREDENTIAL_VERIFIED_EMAIL_LABEL))});
+  suggestion.payload = profile;
+
+  return suggestion;
+}
+
+Suggestion CreatePasswordSuggestion(IdentityRequestAccountPtr account) {
+  Suggestion suggestion(SuggestionType::kIdentityCredential);
+
+  suggestion.main_text = Suggestion::Text(base::UTF8ToUTF16(account->email));
+  suggestion.custom_icon = account->decoded_picture;
+  // TODO(crbug.com/410421491): support more context.
+  suggestion.labels.push_back({Suggestion::Text(l10n_util::GetStringFUTF16(
+      IDS_AUTOFILL_IDENTITY_CREDENTIAL_LABEL_TEXT,
+      base::UTF8ToUTF16(account->identity_provider->idp_for_display)))});
+  suggestion.payload = CreateFederatedProfile(account);
+
+  return suggestion;
+}
+
+std::optional<Suggestion> CreateProvidedFieldSuggestion(
+    IdentityRequestAccountPtr account,
+    const FieldType& field_type) {
+  Suggestion::IdentityCredentialPayload profile =
+      CreateFederatedProfile(account);
+
+  if (!profile.fields.contains(field_type)) {
+    return std::nullopt;
+  }
+
+  Suggestion suggestion(SuggestionType::kIdentityCredential);
+  suggestion.main_text = Suggestion::Text(profile.fields[field_type]);
+  suggestion.icon = Suggestion::Icon::kAccount;
+  suggestion.minor_texts.emplace_back(l10n_util::GetStringFUTF16(
+      IDS_AUTOFILL_IDENTITY_CREDENTIAL_PROVIDED_MINOR_TEXT,
+      base::UTF8ToUTF16(account->identity_provider->idp_for_display)));
+  suggestion.payload = profile;
+
+  return suggestion;
+}
+
+}  // namespace
+
 ContentIdentityCredentialDelegate::ContentIdentityCredentialDelegate(
     content::WebContents* web_contents)
     : ContentIdentityCredentialDelegate(base::BindRepeating(
@@ -37,10 +126,6 @@
 std::vector<Suggestion>
 ContentIdentityCredentialDelegate::GetVerifiedAutofillSuggestions(
     const FieldType& field_type) const {
-  if (!(field_type == PASSWORD || field_type == EMAIL_ADDRESS ||
-        field_type == NAME_FULL || field_type == PHONE_HOME_WHOLE_NUMBER)) {
-    return {};
-  }
   // TODO(crbug.com/380367784): reproduce and add a test to make sure this
   // works properly when FedCM is called from inner frames.
   content::FederatedAuthAutofillSource* source = source_.Run();
@@ -58,57 +143,33 @@
 
   std::vector<Suggestion> suggestions;
   for (IdentityRequestAccountPtr account : *accounts) {
-    Suggestion suggestion(SuggestionType::kIdentityCredential);
-    auto payload = Suggestion::IdentityCredentialPayload(
-        account->identity_provider->idp_metadata.config_url, account->id);
-
-    if (!account->email.empty() &&
-        base::Contains(account->identity_provider->disclosure_fields,
-                       content::IdentityRequestDialogDisclosureField::kEmail)) {
-      payload.fields[EMAIL_ADDRESS] = base::UTF8ToUTF16(account->email);
-    }
-
-    if (!account->name.empty() &&
-        base::Contains(account->identity_provider->disclosure_fields,
-                       content::IdentityRequestDialogDisclosureField::kName)) {
-      payload.fields[NAME_FULL] = base::UTF8ToUTF16(account->name);
-    }
-
-    if (!account->phone.empty() &&
-        base::Contains(
-            account->identity_provider->disclosure_fields,
-            content::IdentityRequestDialogDisclosureField::kPhoneNumber)) {
-      payload.fields[PHONE_HOME_WHOLE_NUMBER] =
-          base::UTF8ToUTF16(account->phone);
-    }
-
-    if (field_type == EMAIL_ADDRESS || field_type == NAME_FULL ||
-        field_type == PHONE_HOME_WHOLE_NUMBER) {
-      if (!payload.fields.contains(field_type)) {
-        continue;
+    switch (field_type) {
+      case EMAIL_ADDRESS: {
+        if (std::optional<Suggestion> suggestion =
+                CreateVerifiedEmailSuggestion(account);
+            suggestion) {
+          suggestions.emplace_back(std::move(*suggestion));
+        }
+        break;
       }
-
-      suggestion.main_text = Suggestion::Text(payload.fields[field_type]);
-      // TODO(crbug.com/380367784): revisit the iconography of the suggestion
-      // if the field goes beyond email.
-      suggestion.icon = Suggestion::Icon::kEmail;
-      suggestion.minor_texts.emplace_back(l10n_util::GetStringFUTF16(
-          IDS_AUTOFILL_IDENTITY_CREDENTIAL_MINOR_TEXT,
-          base::UTF8ToUTF16(account->identity_provider->idp_for_display)));
-      suggestion.labels.push_back({Suggestion::Text(l10n_util::GetStringUTF16(
-          IDS_AUTOFILL_IDENTITY_CREDENTIAL_EMAIL_LABEL))});
-    } else if (field_type == PASSWORD) {
-      suggestion.main_text =
-          Suggestion::Text(base::UTF8ToUTF16(account->email));
-      suggestion.custom_icon = account->decoded_picture;
-      // TODO(crbug.com/410421491): support more context.
-      suggestion.labels.push_back({Suggestion::Text(l10n_util::GetStringFUTF16(
-          IDS_AUTOFILL_IDENTITY_CREDENTIAL_LABEL_TEXT,
-          base::UTF8ToUTF16(account->identity_provider->idp_for_display)))});
+      case NAME_FULL:
+        [[fallthrough]];  // Intentional fall through.
+      case PHONE_HOME_WHOLE_NUMBER: {
+        if (std::optional<Suggestion> suggestion =
+                CreateProvidedFieldSuggestion(account, field_type);
+            suggestion) {
+          suggestions.emplace_back(std::move(*suggestion));
+        }
+        break;
+      }
+      case PASSWORD: {
+        suggestions.emplace_back(CreatePasswordSuggestion(account));
+        break;
+      }
+      default:
+        // Unsupported field type.
+        return {};
     }
-
-    suggestion.payload = payload;
-    suggestions.push_back(std::move(suggestion));
   }
 
   return suggestions;
diff --git a/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc b/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc
index ea692a04..0de6c56 100644
--- a/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc
+++ b/components/autofill/content/browser/content_identity_credential_delegate_unittest.cc
@@ -43,7 +43,7 @@
 IdentityRequestAccountPtr CreateTestAccount() {
   IdentityRequestAccountPtr account =
       base::MakeRefCounted<content::IdentityRequestAccount>(
-          "id", "display_identifier", "display_name", "john@email.com", "name",
+          "id", "display_identifier", "display_name", "john@email.com", "John",
           "given_name", GURL(), "+1 (234) 567-8910", "username",
           /*login_hints=*/std::vector<std::string>(),
           /*domain_hints=*/std::vector<std::string>(),
@@ -73,7 +73,46 @@
   }));
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(EMAIL_ADDRESS);
-  EXPECT_EQ(0ul, suggestions.size());
+  ASSERT_EQ(0ul, suggestions.size());
+}
+
+TEST_F(ContentIdentityCredentialDelegateTest, NoAccounts) {
+  MockFederatedAuthAutofillSource mock;
+
+  ContentIdentityCredentialDelegate delegate(
+      base::BindLambdaForTesting([&mock]() {
+        content::FederatedAuthAutofillSource* result = &mock;
+        return result;
+      }));
+
+  std::vector<IdentityRequestAccountPtr> accounts = {};
+
+  EXPECT_CALL(mock, GetAutofillSuggestions).WillOnce(Return(accounts));
+
+  std::vector<Suggestion> suggestions =
+      delegate.GetVerifiedAutofillSuggestions(EMAIL_ADDRESS);
+  ASSERT_EQ(0ul, suggestions.size());
+}
+
+TEST_F(ContentIdentityCredentialDelegateTest, UnsupportedFieldType) {
+  MockFederatedAuthAutofillSource mock;
+
+  ContentIdentityCredentialDelegate delegate(
+      base::BindLambdaForTesting([&mock]() {
+        content::FederatedAuthAutofillSource* result = &mock;
+        return result;
+      }));
+
+  IdentityRequestAccountPtr account = CreateTestAccount();
+  account->identity_provider->disclosure_fields = {
+      content::IdentityRequestDialogDisclosureField::kEmail};
+  std::vector<IdentityRequestAccountPtr> accounts = {account};
+
+  EXPECT_CALL(mock, GetAutofillSuggestions).WillOnce(Return(accounts));
+
+  std::vector<Suggestion> suggestions =
+      delegate.GetVerifiedAutofillSuggestions(IBAN_VALUE);
+  ASSERT_EQ(0ul, suggestions.size());
 }
 
 TEST_F(ContentIdentityCredentialDelegateTest, GetVerifiedEmailRequest) {
@@ -95,12 +134,13 @@
 
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(EMAIL_ADDRESS);
-  EXPECT_EQ(1ul, suggestions.size());
+  ASSERT_EQ(1ul, suggestions.size());
 
   Suggestion suggestion = suggestions[0];
   EXPECT_EQ(suggestion.main_text.value, u"john@email.com");
-  EXPECT_EQ(suggestion.labels.size(), 1ul);
-  EXPECT_EQ(suggestion.minor_texts.size(), 1ul);
+  ASSERT_EQ(suggestion.labels.size(), 1ul);
+  ASSERT_EQ(suggestion.minor_texts.size(), 1ul);
+  EXPECT_EQ(suggestion.icon, Suggestion::Icon::kEmail);
 
   // Expect the payload to be populated properly.
   Suggestion::IdentityCredentialPayload payload =
@@ -109,7 +149,7 @@
   EXPECT_EQ(payload.config_url, GURL("https://idp.example"));
 
   // Expect only one field to be available in the payload.
-  EXPECT_EQ(payload.fields.size(), 1ul);
+  ASSERT_EQ(payload.fields.size(), 1ul);
 
   // Expect that email is previewed/filled because it was requested in the
   // conditional request.
@@ -141,12 +181,11 @@
 
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(PHONE_HOME_WHOLE_NUMBER);
-  EXPECT_EQ(1ul, suggestions.size());
+  ASSERT_EQ(1ul, suggestions.size());
 
   Suggestion suggestion = suggestions[0];
   EXPECT_EQ(suggestion.main_text.value, u"+1 (234) 567-8910");
-  EXPECT_EQ(suggestion.labels.size(), 1ul);
-  EXPECT_EQ(suggestion.minor_texts.size(), 1ul);
+  ASSERT_EQ(suggestion.minor_texts.size(), 1ul);
 
   // Expect the payload to be populated properly.
   Suggestion::IdentityCredentialPayload payload =
@@ -155,7 +194,7 @@
   EXPECT_EQ(payload.config_url, GURL("https://idp.example"));
 
   // Expect two fields to be available in the payload: emails and usernames.
-  EXPECT_EQ(payload.fields.size(), 2ul);
+  ASSERT_EQ(payload.fields.size(), 2ul);
 
   // Expect that email is previewed/filled because it was requested in the
   // conditional request.
@@ -188,7 +227,7 @@
 
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(NAME_FULL);
-  EXPECT_EQ(0ul, suggestions.size());
+  ASSERT_EQ(0ul, suggestions.size());
 }
 
 TEST_F(ContentIdentityCredentialDelegateTest,
@@ -215,7 +254,7 @@
 
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(EMAIL_ADDRESS);
-  EXPECT_EQ(0ul, suggestions.size());
+  ASSERT_EQ(0ul, suggestions.size());
 }
 
 TEST_F(ContentIdentityCredentialDelegateTest, GetSuggestionsForPassword) {
@@ -253,7 +292,7 @@
 
   std::vector<Suggestion> suggestions =
       delegate.GetVerifiedAutofillSuggestions(PASSWORD);
-  EXPECT_EQ(1ul, suggestions.size());
+  ASSERT_EQ(1ul, suggestions.size());
 
   Suggestion suggestion = suggestions[0];
   EXPECT_EQ(suggestion.main_text.value, u"john@email.com");
@@ -270,6 +309,48 @@
   EXPECT_TRUE(payload.fields.empty());
 }
 
+TEST_F(ContentIdentityCredentialDelegateTest, GetProvidedNameRequest) {
+  MockFederatedAuthAutofillSource mock;
+
+  ContentIdentityCredentialDelegate delegate(
+      base::BindLambdaForTesting([&mock]() {
+        content::FederatedAuthAutofillSource* result = &mock;
+        return result;
+      }));
+
+  IdentityRequestAccountPtr account = CreateTestAccount();
+  // Use only "name" in the selective disclosure request.
+  account->identity_provider->disclosure_fields = {
+      content::IdentityRequestDialogDisclosureField::kName};
+  std::vector<IdentityRequestAccountPtr> accounts = {account};
+
+  EXPECT_CALL(mock, GetAutofillSuggestions).WillOnce(Return(accounts));
+
+  std::vector<Suggestion> suggestions =
+      delegate.GetVerifiedAutofillSuggestions(NAME_FULL);
+  ASSERT_EQ(1ul, suggestions.size());
+
+  Suggestion suggestion = suggestions[0];
+  EXPECT_EQ(suggestion.main_text.value, u"John");
+  EXPECT_EQ(suggestion.labels.size(), 0ul);
+  EXPECT_EQ(suggestion.minor_texts.size(), 1ul);
+  EXPECT_EQ(suggestion.icon, Suggestion::Icon::kAccount);
+
+  // Expect the payload to be populated properly.
+  Suggestion::IdentityCredentialPayload payload =
+      suggestion.GetPayload<Suggestion::IdentityCredentialPayload>();
+  EXPECT_EQ(payload.account_id, "id");
+  EXPECT_EQ(payload.config_url, GURL("https://idp.example"));
+
+  // Expect only one field to be available in the payload.
+  ASSERT_EQ(payload.fields.size(), 1ul);
+
+  // Expect that email is previewed/filled because it was requested in the
+  // conditional request.
+  EXPECT_TRUE(payload.fields.contains(NAME_FULL));
+  EXPECT_EQ(payload.fields[NAME_FULL], u"John");
+}
+
 }  // namespace
 
 }  // namespace autofill
diff --git a/components/autofill/core/browser/data_model/payments/credit_card.cc b/components/autofill/core/browser/data_model/payments/credit_card.cc
index 466307b..b364aa58 100644
--- a/components/autofill/core/browser/data_model/payments/credit_card.cc
+++ b/components/autofill/core/browser/data_model/payments/credit_card.cc
@@ -350,6 +350,7 @@
     case Suggestion::Icon::kSettingsAndroid:
     case Suggestion::Icon::kUndo:
     case Suggestion::Icon::kBnpl:
+    case Suggestion::Icon::kGoogleWallet:
       NOTREACHED();
   }
   NOTREACHED();
diff --git a/components/autofill/core/browser/suggestions/suggestion.cc b/components/autofill/core/browser/suggestions/suggestion.cc
index 43defea9..f7186ec07 100644
--- a/components/autofill/core/browser/suggestions/suggestion.cc
+++ b/components/autofill/core/browser/suggestions/suggestion.cc
@@ -72,6 +72,8 @@
       return "kGooglePasswordManager";
     case Suggestion::Icon::kGooglePay:
       return "kGooglePay";
+    case Suggestion::Icon::kGoogleWallet:
+      return "kGoogleWallet";
     case Suggestion::Icon::kHome:
       return "kHome";
     case Suggestion::Icon::kHttpWarning:
diff --git a/components/autofill/core/browser/suggestions/suggestion.h b/components/autofill/core/browser/suggestions/suggestion.h
index 5e79ac3..a86cf4df 100644
--- a/components/autofill/core/browser/suggestions/suggestion.h
+++ b/components/autofill/core/browser/suggestions/suggestion.h
@@ -269,6 +269,7 @@
     kGoogleMonochrome,
     kGooglePasswordManager,
     kGooglePay,
+    kGoogleWallet,
     kHome,
     kHttpWarning,
     kHttpsInvalid,
diff --git a/components/autofill/core/browser/suggestions/suggestion_test_helpers.cc b/components/autofill/core/browser/suggestions/suggestion_test_helpers.cc
index 06b1806..3c67472 100644
--- a/components/autofill/core/browser/suggestions/suggestion_test_helpers.cc
+++ b/components/autofill/core/browser/suggestions/suggestion_test_helpers.cc
@@ -73,6 +73,10 @@
   return Field(&Suggestion::icon, icon);
 }
 
+Matcher<Suggestion> HasTrailingIcon(Suggestion::Icon icon) {
+  return Field(&Suggestion::trailing_icon, icon);
+}
+
 Matcher<Suggestion> HasIphFeature(
     raw_ptr<const base::Feature> feature_for_iph) {
   return Field(&Suggestion::iph_metadata,
diff --git a/components/autofill/core/browser/suggestions/suggestion_test_helpers.h b/components/autofill/core/browser/suggestions/suggestion_test_helpers.h
index f6be48f..5307782 100644
--- a/components/autofill/core/browser/suggestions/suggestion_test_helpers.h
+++ b/components/autofill/core/browser/suggestions/suggestion_test_helpers.h
@@ -47,6 +47,8 @@
 
 ::testing::Matcher<Suggestion> HasIcon(Suggestion::Icon icon);
 
+::testing::Matcher<Suggestion> HasTrailingIcon(Suggestion::Icon icon);
+
 ::testing::Matcher<Suggestion> HasIphFeature(
     raw_ptr<const base::Feature> feature);
 
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc
index 1732938..bf2064b4 100644
--- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc
+++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.cc
@@ -40,6 +40,9 @@
   Suggestion suggestion(u"Manage loyalty cards...",
                         SuggestionType::kManageLoyaltyCard);
   suggestion.icon = Suggestion::Icon::kSettings;
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  suggestion.trailing_icon = Suggestion::Icon::kGoogleWallet;
+#endif
   return suggestion;
 }
 
@@ -151,4 +154,24 @@
                            Suggestion(SuggestionType::kSeparator));
 }
 
+// TODO(crbug.com/404436027): Deduplicate autocomplete and loyalty cards
+// suggestions.
+void ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions(
+    std::vector<Suggestion>& autocomplete_suggestions,
+    const ValuablesDataManager& valuables_manager,
+    const GURL& url) {
+  // There is at least one autocomplete suggestion that we can separate from
+  // loyalty cards.
+  CHECK(autocomplete_suggestions.size() >= 1);
+  std::vector<Suggestion> loyalty_cards_suggestions =
+      GetLoyaltyCardSuggestions(valuables_manager, url);
+  if (loyalty_cards_suggestions.empty()) {
+    return;
+  }
+  autocomplete_suggestions.emplace_back(SuggestionType::kSeparator);
+  autocomplete_suggestions.insert(
+      autocomplete_suggestions.end(),
+      std::make_move_iterator(loyalty_cards_suggestions.begin()),
+      std::make_move_iterator(loyalty_cards_suggestions.end()));
+}
 }  // namespace autofill
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h
index bfaeeb23..0241cb07 100644
--- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h
+++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator.h
@@ -28,12 +28,22 @@
 // submenu.
 //
 // Loyalty cards suggestions are retrieved and follow the same logic as
-// `GetLoyaltyCardSuggestions()`.
+// `GetLoyaltyCardSuggestions()`. The passed `email_suggestions` must be at
+// least 3 suggestions long (email, separator and 'manage' suggestion).
 void ExtendEmailSuggestionsWithLoyaltyCardSuggestions(
     std::vector<Suggestion>& email_suggestions,
     const ValuablesDataManager& valuables_manager,
     const GURL& url);
 
+// Appends loyalty cards suggestions to given `autocomplete_suggestions`.
+//
+// Loyalty cards suggestions are retrieved and follow the same logic as
+// `GetLoyaltyCardSuggestions()`. The passed `autocomplete_suggestions` must not
+// be empty.
+void ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions(
+    std::vector<Suggestion>& autocomplete_suggestions,
+    const ValuablesDataManager& valuables_manager,
+    const GURL& url);
 }  // namespace autofill
 
 #endif  // COMPONENTS_AUTOFILL_CORE_BROWSER_SUGGESTIONS_VALUABLES_VALUABLE_SUGGESTION_GENERATOR_H_
diff --git a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc
index 49329df..ad41fb4 100644
--- a/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc
+++ b/components/autofill/core/browser/suggestions/valuables/valuable_suggestion_generator_unittest.cc
@@ -185,7 +185,10 @@
                   EqualsSuggestion(SuggestionType::kManageLoyaltyCard,
                                    u"Manage loyalty cards...",
                                    Suggestion::Icon::kSettings)));
-
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  EXPECT_THAT(suggestions.back(),
+              HasTrailingIcon(Suggestion::Icon::kGoogleWallet));
+#endif
   // Verify that for loyalty cards, the custom icon is shown.
   EXPECT_THAT(suggestions[0],
               SuggestionIconHasImageOrUrl(fake_image, program_logo));
@@ -241,6 +244,10 @@
                   EqualsSuggestion(SuggestionType::kManageLoyaltyCard,
                                    u"Manage loyalty cards...",
                                    Suggestion::Icon::kSettings)));
+#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
+  EXPECT_THAT(lc_submenu_suggestion.children.back(),
+              HasTrailingIcon(Suggestion::Icon::kGoogleWallet));
+#endif
 }
 
 TEST_F(ValuableSuggestionGeneratorTest,
@@ -268,6 +275,64 @@
                                             u"Manage addresses...")));
 }
 
+TEST_F(
+    ValuableSuggestionGeneratorTest,
+    ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions_ExistingLoyaltyCards) {
+  const std::vector<LoyaltyCard> loyalty_cards = {LoyaltyCard(
+      /*loyalty_card_id=*/ValuableId("loyalty_card_id_1"),
+      /*merchant_name=*/"CVS Pharmacy",
+      /*program_name=*/"CVS Extra",
+      /*program_logo=*/GURL("https://empty.url.com"),
+      /*loyalty_card_number=*/"987654321987654321",
+      {GURL("https://domain1.example"),
+       GURL("https://common-domain.example")})};
+
+  test_api(valuables_data_manager()).SetLoyaltyCards(loyalty_cards);
+
+  std::vector<Suggestion> suggestions = {
+      Suggestion(u"foobar1", SuggestionType::kAutocompleteEntry),
+      Suggestion(u"foobar2", SuggestionType::kAutocompleteEntry)};
+
+  ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions(
+      suggestions, valuables_data_manager(),
+      GURL("https://common-domain.example/test"));
+
+  EXPECT_THAT(
+      suggestions,
+      testing::ElementsAre(
+          EqualsSuggestion(SuggestionType::kAutocompleteEntry, u"foobar1"),
+          EqualsSuggestion(SuggestionType::kAutocompleteEntry, u"foobar2"),
+          EqualsSuggestion(SuggestionType::kSeparator),
+          EqualsSuggestion(
+              SuggestionType::kLoyaltyCardEntry, u"987654321987654321",
+              /*is_main_text_primary=*/true, Suggestion::Icon::kNoIcon,
+              {{Suggestion::Text(u"CVS Pharmacy")}},
+              Suggestion::Guid("loyalty_card_id_1")),
+          EqualsSuggestion(SuggestionType::kSeparator),
+          EqualsSuggestion(SuggestionType::kManageLoyaltyCard,
+                           u"Manage loyalty cards...",
+                           Suggestion::Icon::kSettings)));
+}
+
+TEST_F(ValuableSuggestionGeneratorTest,
+       ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions_NoLoyaltyCards) {
+  test_api(valuables_data_manager()).SetLoyaltyCards({});
+
+  std::vector<Suggestion> suggestions = {
+      Suggestion(u"foobar1", SuggestionType::kAutocompleteEntry),
+      Suggestion(u"foobar2", SuggestionType::kAutocompleteEntry)};
+
+  ExtendAutocompleteSuggestionsWithLoyaltyCardSuggestions(
+      suggestions, valuables_data_manager(),
+      GURL("https://common-domain.example/test"));
+
+  EXPECT_THAT(
+      suggestions,
+      testing::ElementsAre(
+          EqualsSuggestion(SuggestionType::kAutocompleteEntry, u"foobar1"),
+          EqualsSuggestion(SuggestionType::kAutocompleteEntry, u"foobar2")));
+}
+
 #if !BUILDFLAG(IS_ANDROID)
 TEST_F(ValuableSuggestionGeneratorTest,
        GetLoyaltyCardSuggestions_SuggestionsIPH) {
diff --git a/components/autofill/core/common/autocomplete_parsing_util.h b/components/autofill/core/common/autocomplete_parsing_util.h
index f1a7614..2b2591b6 100644
--- a/components/autofill/core/common/autocomplete_parsing_util.h
+++ b/components/autofill/core/common/autocomplete_parsing_util.h
@@ -24,13 +24,13 @@
 // - If ShouldIgnoreAutocompleteAttribute(autocomplete) is true.
 // An unrecognizable field_type doesn't stop parsing and yields
 // HtmlFieldType::kUnrecognized instead.
-// When adding a new field, keep the traits updated in
-// components/autofill/core/common/mojom/autofill_types.mojom.
 struct AutocompleteParsingResult {
   std::string ToString() const;
 
   bool operator==(const AutocompleteParsingResult&) const;
 
+  // LINT.IfChange(AutocompleteParsingResult)
+
   // `section` corresponds to the string after "section-".
   std::string section;
   HtmlFieldMode mode = HtmlFieldMode::kNone;
@@ -38,9 +38,10 @@
   HtmlFieldType field_type = HtmlFieldType::kUnspecified;
   // Whether the field has a `webauthn` token.
   bool webauthn = false;
-
   // Whether the field has a `webidentity` token.
   bool webidentity = false;
+
+  // LINT.ThenChange(components/autofill/core/common/mojom/autofill_types.mojom)
 };
 
 std::optional<AutocompleteParsingResult> ParseAutocompleteAttribute(
diff --git a/components/autofill_strings.grdp b/components/autofill_strings.grdp
index 6becf025..f062593 100644
--- a/components/autofill_strings.grdp
+++ b/components/autofill_strings.grdp
@@ -184,11 +184,15 @@
   </message>
 
   <!-- Autofill Identity Credentials Suggestions -->
-  <message name="IDS_AUTOFILL_IDENTITY_CREDENTIAL_MINOR_TEXT" desc="The minor text to display in an autofill suggestion (e.g. an email) that is verified by a third party website (e.g. google.com)." translateable="false">
+  <message name="IDS_AUTOFILL_IDENTITY_CREDENTIAL_PROVIDED_MINOR_TEXT" desc="The minor text to display in an autofill suggestion (e.g. an email) that is provided by a third party website (e.g. google.com)." translateable="false">
+    Provided by <ph name="IDP_ORIGIN">$1<ex>accounts.google.com</ex></ph>
+  </message>
+
+  <message name="IDS_AUTOFILL_IDENTITY_CREDENTIAL_VERIFIED_MINOR_TEXT" desc="The minor text to display in an autofill suggestion (e.g. an email) that is verified by a third party website (e.g. google.com)." translateable="false">
     Verified by <ph name="IDP_ORIGIN">$1<ex>accounts.google.com</ex></ph>
   </message>
 
-  <message name="IDS_AUTOFILL_IDENTITY_CREDENTIAL_EMAIL_LABEL" desc="The label text to display for verified autofill suggestions. If the user selects such email suggestion, the website receives cryptographic proof that the user has access to the email. The benefit for the user indicate in this message is that they can skip the manual process of receiving a confirmation email and pressing a link to prove ownership of the email." translateable="false">
+  <message name="IDS_AUTOFILL_IDENTITY_CREDENTIAL_VERIFIED_EMAIL_LABEL" desc="The label text to display for verified autofill suggestions. If the user selects such email suggestion, the website receives cryptographic proof that the user has access to the email. The benefit for the user indicate in this message is that they can skip the manual process of receiving a confirmation email and pressing a link to prove ownership of the email." translateable="false">
     Skip confirmation emails
   </message>
 
diff --git a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java
index 1066c05c..136b1fb0 100644
--- a/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java
+++ b/components/browser_ui/settings/android/widget/java/src/org/chromium/components/browser_ui/settings/SpinnerPreference.java
@@ -23,7 +23,7 @@
 
 /** A preference that takes value from a specified list of objects, presented as a dropdown. */
 @NullMarked
-public class SpinnerPreference extends Preference {
+public class SpinnerPreference extends Preference implements Preference.OnPreferenceClickListener {
     private @Nullable Spinner mSpinner;
     private @Nullable ArrayAdapter<Object> mAdapter;
     private int mSelectedIndex;
@@ -40,6 +40,7 @@
         } else {
             setLayoutResource(R.layout.preference_spinner);
         }
+        setOnPreferenceClickListener(this);
     }
 
     /**
@@ -95,6 +96,14 @@
 
         ((TextView) holder.findViewById(R.id.title)).setText(getTitle());
         mSpinner = (Spinner) holder.findViewById(R.id.spinner);
+        assert mSpinner != null;
+        // Set the inner spinner to non-focusable/clickable, this allows the screen reader to
+        // include the content description of all the Preference's inner elements in a single
+        // announcement. The click action of the inner spinner will instead be handled by
+        // onPreferenceClick().
+        mSpinner.setFocusable(false);
+        mSpinner.setClickable(false);
+        mSpinner.setLongClickable(false);
         mSpinner.setOnItemSelectedListener(
                 new AdapterView.OnItemSelectedListener() {
                     @Override
@@ -122,4 +131,12 @@
         }
         mSpinner.setSelection(mSelectedIndex);
     }
+
+    @Override
+    public boolean onPreferenceClick(Preference preference) {
+        if (mSpinner != null) {
+            mSpinner.performClick();
+        }
+        return true;
+    }
 }
diff --git a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
index 0113b41..c79fc44e 100644
--- a/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
+++ b/components/browser_ui/styles/android/java/src/org/chromium/components/browser_ui/styles/SemanticColorUtils.java
@@ -236,4 +236,9 @@
     public static @ColorInt int getColorSurfaceDim(Context context) {
         return resolve(R.attr.colorSurfaceDim, context);
     }
+
+    /** Returns the surface color value of the conceptual floating snackbar background color. */
+    public static @ColorInt int getFloatingSnackbarBackgroundColor(Context context) {
+        return resolve(R.attr.colorSurfaceContainerHigh, context);
+    }
 }
diff --git a/components/content_settings/core/browser/content_settings_default_provider.cc b/components/content_settings/core/browser/content_settings_default_provider.cc
index cf2cd2a..4d550b6b 100644
--- a/components/content_settings/core/browser/content_settings_default_provider.cc
+++ b/components/content_settings/core/browser/content_settings_default_provider.cc
@@ -68,8 +68,6 @@
 // except via enterprise policy, so it is temporarily cleaned up here to revert
 // it to its default value.
 // TODO(https://crbug.com/367181093): clean this up.
-constexpr char kBug364820109DefaultSettingToClear[] =
-    "profile.default_content_setting_values.javascript_jit";
 constexpr char kBug364820109AlreadyWorkedAroundPref[] =
     "profile.did_work_around_bug_364820109_default";
 #endif  // !BUILDFLAG(IS_IOS)
@@ -368,10 +366,7 @@
 
 #if !BUILDFLAG(IS_IOS)
   // TODO(https://crbug.com/367181093): clean this up.
-  if (!prefs_->GetBoolean(kBug364820109AlreadyWorkedAroundPref)) {
-    prefs_->ClearPref(kBug364820109DefaultSettingToClear);
-    prefs_->SetBoolean(kBug364820109AlreadyWorkedAroundPref, true);
-  }
+  prefs_->ClearPref(kBug364820109AlreadyWorkedAroundPref);
 #endif  // !BUILDFLAG(IS_IOS)
 }
 
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc
index c697613..fdcd09a 100644
--- a/components/content_settings/core/browser/content_settings_pref_provider.cc
+++ b/components/content_settings/core/browser/content_settings_pref_provider.cc
@@ -64,8 +64,6 @@
 // except via enterprise policy, so it is temporarily cleaned up here to revert
 // it to its default value.
 // TODO(https://crbug.com/367181093): clean this up.
-constexpr char kBug364820109ExceptionSettingToClear[] =
-    "profile.content_settings.exceptions.javascript_jit";
 constexpr char kBug364820109AlreadyWorkedAroundPref[] =
     "profile.did_work_around_bug_364820109_exceptions";
 #endif  // !BUILDFLAG(IS_IOS)
@@ -447,10 +445,7 @@
 
 #if !BUILDFLAG(IS_IOS)
   // TODO(https://crbug.com/367181093): clean this up.
-  if (!prefs_->GetBoolean(kBug364820109AlreadyWorkedAroundPref)) {
-    prefs_->ClearPref(kBug364820109ExceptionSettingToClear);
-    prefs_->SetBoolean(kBug364820109AlreadyWorkedAroundPref, true);
-  }
+  prefs_->ClearPref(kBug364820109AlreadyWorkedAroundPref);
 #endif  // !BUILDFLAG(IS_IOS)
 }
 
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc
index 3dc6bd2..b52f71e9 100644
--- a/components/password_manager/core/browser/leak_detection_delegate.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -9,6 +9,7 @@
 #include "components/affiliations/core/browser/affiliation_service.h"
 #include "components/autofill/core/common/save_password_progress_logger.h"
 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
+#include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h"
@@ -166,7 +167,9 @@
   } else {
     // Credential saved to the local-or-syncable store.
 #if BUILDFLAG(IS_ANDROID)
+    // After login db deprecation, all users have split stores on Android.
     const bool uses_split_stores_for_sync_users =
+        base::FeatureList::IsEnabled(features::kLoginDbDeprecationAndroid) ||
         UsesSplitStoresAndUPMForLocal(client_->GetPrefs());
 #else
     const bool uses_split_stores_for_sync_users = false;
diff --git a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
index 05c515ad..4a7a786 100644
--- a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
+++ b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -17,6 +17,7 @@
 #include "build/build_config.h"
 #include "components/affiliations/core/browser/mock_affiliation_service.h"
 #include "components/autofill/core/common/save_password_progress_logger.h"
+#include "components/password_manager/core/browser/features/password_features.h"
 #include "components/password_manager/core/browser/form_parsing/form_data_parser.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h"
 #include "components/password_manager/core/browser/leak_detection/leak_detection_request_utils.h"
@@ -438,6 +439,12 @@
 }
 
 TEST_F(LeakDetectionDelegateTest, LeakDetectionDoneForSyncingUser) {
+#if BUILDFLAG(IS_ANDROID)
+  // On Android, syncing passwords from the profile store is only possible
+  // before login db deprecation.
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kLoginDbDeprecationAndroid);
+#endif
   LeakDetectionDelegateInterface* delegate_interface = &delegate();
   const PasswordForm form = CreateTestForm();
 
@@ -551,7 +558,9 @@
 
 #if BUILDFLAG(IS_ANDROID)
 TEST_F(LeakDetectionDelegateTest,
-       LeakDetectionDoneForLocalStoreWithSplitStoresAndUPMForLocal) {
+       LeakDetectionDoneLocalStoreWithUPMSplitStoresBeforeDbDeprecation) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kLoginDbDeprecationAndroid);
   LeakDetectionDelegateInterface* delegate_interface = &delegate();
   const PasswordForm form = CreateTestForm();
 
@@ -593,7 +602,55 @@
 }
 
 TEST_F(LeakDetectionDelegateTest,
-       LeakDetectionDoneForAccountStoreWithSplitStoresAndUPMForLocal) {
+       LeakDetectionDoneLocalStoreWithUPMSplitStoresAfterDbDeprecation) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kLoginDbDeprecationAndroid);
+  LeakDetectionDelegateInterface* delegate_interface = &delegate();
+  const PasswordForm form = CreateTestForm();
+
+  ON_CALL(client(), GetSyncService()).WillByDefault(Return(sync_service()));
+  ON_CALL(client(), GetAccountPasswordStore())
+      .WillByDefault(Return(account_store()));
+  ON_CALL(client(), GetProfilePasswordStore())
+      .WillByDefault(Return(profile_store()));
+
+  // The login db deprecation also stops automatic migration and deprecates
+  // the migration pref, so set it to off to verify that its value doesn't
+  // matter.
+  pref_service()->SetInteger(
+      prefs::kPasswordsUseUPMLocalAndSeparateStores,
+      static_cast<int>(prefs::UseUpmLocalAndSeparateStoresState::kOff));
+
+  ASSERT_EQ(sync_util::GetPasswordSyncState(sync_service()),
+            sync_util::SyncState::kActiveWithNormalEncryption);
+  ASSERT_TRUE(
+      sync_util::IsSyncFeatureEnabledIncludingPasswords(sync_service()));
+
+  ExpectPasswords({}, /*store=*/account_store());
+  ExpectPasswords({form}, /*store=*/profile_store());
+  EXPECT_CALL(factory(), TryCreateLeakCheck)
+      .WillOnce(
+          Return(ByMove(std::make_unique<NiceMock<MockLeakDetectionCheck>>())));
+  delegate().StartLeakCheck(LeakDetectionInitiator::kSignInCheck, form,
+                            GetTestUrl());
+
+  EXPECT_CALL(client(),
+              NotifyUserCredentialsWereLeaked(LeakedPasswordDetails(
+                  password_manager::CreateLeakType(
+                      IsSaved(true), IsReused(false), IsSyncing(false)),
+                  form.url, form.username_value, form.password_value,
+                  /* in_account_store = */ false)));
+  delegate_interface->OnLeakDetectionDone(
+      /*is_leaked=*/true, form.url, form.username_value, form.password_value);
+
+  EXPECT_CALL(*profile_store(), UpdateLogin);
+  WaitForPasswordStore();
+}
+
+TEST_F(LeakDetectionDelegateTest,
+       LeakDetectionDoneAccountStoreWithUPMSplitStoresBeforeDbDeprecation) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndDisableFeature(features::kLoginDbDeprecationAndroid);
   LeakDetectionDelegateInterface* delegate_interface = &delegate();
   const PasswordForm form = CreateTestForm();
 
@@ -633,6 +690,52 @@
   EXPECT_CALL(*account_store(), UpdateLogin);
   WaitForPasswordStore();
 }
+
+TEST_F(LeakDetectionDelegateTest,
+       LeakDetectionDoneAccountStoreWithUPMSplitStoresAfterDbDeprecation) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeature(features::kLoginDbDeprecationAndroid);
+  LeakDetectionDelegateInterface* delegate_interface = &delegate();
+  const PasswordForm form = CreateTestForm();
+
+  ON_CALL(client(), GetSyncService()).WillByDefault(Return(sync_service()));
+  ON_CALL(client(), GetAccountPasswordStore())
+      .WillByDefault(Return(account_store()));
+  ON_CALL(client(), GetProfilePasswordStore())
+      .WillByDefault(Return(profile_store()));
+
+  // The login db deprecation also stops automatic migration and deprecates
+  // the migration pref, so set it to off to verify that its value doesn't
+  // matter.
+  pref_service()->SetInteger(
+      prefs::kPasswordsUseUPMLocalAndSeparateStores,
+      static_cast<int>(prefs::UseUpmLocalAndSeparateStoresState::kOff));
+
+  ASSERT_EQ(sync_util::GetPasswordSyncState(sync_service()),
+            sync_util::SyncState::kActiveWithNormalEncryption);
+  ASSERT_TRUE(
+      sync_util::IsSyncFeatureEnabledIncludingPasswords(sync_service()));
+
+  ExpectPasswords({form}, /*store=*/account_store());
+  ExpectPasswords({}, /*store=*/profile_store());
+  EXPECT_CALL(factory(), TryCreateLeakCheck)
+      .WillOnce(
+          Return(ByMove(std::make_unique<NiceMock<MockLeakDetectionCheck>>())));
+  delegate().StartLeakCheck(LeakDetectionInitiator::kSignInCheck, form,
+                            GetTestUrl());
+
+  EXPECT_CALL(client(),
+              NotifyUserCredentialsWereLeaked(LeakedPasswordDetails(
+                  password_manager::CreateLeakType(
+                      IsSaved(true), IsReused(false), IsSyncing(true)),
+                  form.url, form.username_value, form.password_value,
+                  /* in_account_store = */ true)));
+  delegate_interface->OnLeakDetectionDone(
+      /*is_leaked=*/true, form.url, form.username_value, form.password_value);
+
+  EXPECT_CALL(*account_store(), UpdateLogin);
+  WaitForPasswordStore();
+}
 #endif  // BUILDFLAG(IS_ANDROID)
 
 TEST_F(LeakDetectionDelegateTest, LeakHistoryAddCredentials) {
diff --git a/components/password_manager/core/browser/split_stores_and_local_upm.cc b/components/password_manager/core/browser/split_stores_and_local_upm.cc
index dee05a5..1e64b9c 100644
--- a/components/password_manager/core/browser/split_stores_and_local_upm.cc
+++ b/components/password_manager/core/browser/split_stores_and_local_upm.cc
@@ -30,6 +30,7 @@
 
 }  // namespace
 
+// DEPRECATED: only use if `features::kLoginDbDeprecationAndroid` is disabled.
 bool UsesSplitStoresAndUPMForLocal(const PrefService* pref_service) {
   switch (
       static_cast<UseUpmLocalAndSeparateStoresState>(pref_service->GetInteger(
diff --git a/components/password_manager/core/browser/split_stores_and_local_upm.h b/components/password_manager/core/browser/split_stores_and_local_upm.h
index 3b4d1fb..e232902 100644
--- a/components/password_manager/core/browser/split_stores_and_local_upm.h
+++ b/components/password_manager/core/browser/split_stores_and_local_upm.h
@@ -16,6 +16,10 @@
 //  Checks whether the UPM for local users is activated for this client.
 //  This also means that the single password store has been split in
 //  account and local stores.
+//
+// DEPRECATED: With kLoginDbDeprecationAndroid enabled, the UPM activation
+// pref is no longer set for new users. All users will have split stores, either
+// both empty or both using Google Play Services as storage.
 bool UsesSplitStoresAndUPMForLocal(const PrefService* pref_service);
 
 // Returns whether it is a requirement to update the GMSCore based on the
diff --git a/components/services/storage/public/cpp/buckets/bucket_info.cc b/components/services/storage/public/cpp/buckets/bucket_info.cc
index feb9e68..fa464d6 100644
--- a/components/services/storage/public/cpp/buckets/bucket_info.cc
+++ b/components/services/storage/public/cpp/buckets/bucket_info.cc
@@ -35,10 +35,6 @@
   return lhs.id == rhs.id;
 }
 
-bool operator!=(const BucketInfo& lhs, const BucketInfo& rhs) {
-  return !(lhs == rhs);
-}
-
 bool operator<(const BucketInfo& lhs, const BucketInfo& rhs) {
   return lhs.id < rhs.id;
 }
diff --git a/components/services/storage/public/cpp/buckets/bucket_info.h b/components/services/storage/public/cpp/buckets/bucket_info.h
index 043e989..3ac8016d 100644
--- a/components/services/storage/public/cpp/buckets/bucket_info.h
+++ b/components/services/storage/public/cpp/buckets/bucket_info.h
@@ -46,9 +46,6 @@
   friend bool operator==(const BucketInfo& lhs, const BucketInfo& rhs);
 
   COMPONENT_EXPORT(STORAGE_SERVICE_BUCKETS_SUPPORT)
-  friend bool operator!=(const BucketInfo& lhs, const BucketInfo& rhs);
-
-  COMPONENT_EXPORT(STORAGE_SERVICE_BUCKETS_SUPPORT)
   friend bool operator<(const BucketInfo& lhs, const BucketInfo& rhs);
 
   BucketLocator ToBucketLocator() const {
diff --git a/components/services/storage/public/cpp/buckets/bucket_locator.cc b/components/services/storage/public/cpp/buckets/bucket_locator.cc
index 20808ffc..90d385d 100644
--- a/components/services/storage/public/cpp/buckets/bucket_locator.cc
+++ b/components/services/storage/public/cpp/buckets/bucket_locator.cc
@@ -35,20 +35,6 @@
                                std::tie(other.storage_key, other.is_default)));
 }
 
-bool operator==(const BucketLocator& lhs, const BucketLocator& rhs) {
-  return std::tie(lhs.id, lhs.storage_key, lhs.is_default) ==
-         std::tie(rhs.id, rhs.storage_key, rhs.is_default);
-}
-
-bool operator!=(const BucketLocator& lhs, const BucketLocator& rhs) {
-  return !(lhs == rhs);
-}
-
-bool operator<(const BucketLocator& lhs, const BucketLocator& rhs) {
-  return std::tie(lhs.id, lhs.storage_key, lhs.is_default) <
-         std::tie(rhs.id, rhs.storage_key, rhs.is_default);
-}
-
 bool CompareBucketLocators::operator()(const BucketLocator& a,
                                        const BucketLocator& b) const {
   // In this custom comparator, we make default buckets match regardless
diff --git a/components/services/storage/public/cpp/buckets/bucket_locator.h b/components/services/storage/public/cpp/buckets/bucket_locator.h
index 782d8d9..3613597 100644
--- a/components/services/storage/public/cpp/buckets/bucket_locator.h
+++ b/components/services/storage/public/cpp/buckets/bucket_locator.h
@@ -36,13 +36,10 @@
   bool IsEquivalentTo(const BucketLocator& other) const;
 
   COMPONENT_EXPORT(STORAGE_SERVICE_BUCKETS_SUPPORT)
-  friend bool operator==(const BucketLocator& lhs, const BucketLocator& rhs);
+  friend bool operator==(const BucketLocator&, const BucketLocator&) = default;
 
   COMPONENT_EXPORT(STORAGE_SERVICE_BUCKETS_SUPPORT)
-  friend bool operator!=(const BucketLocator& lhs, const BucketLocator& rhs);
-
-  COMPONENT_EXPORT(STORAGE_SERVICE_BUCKETS_SUPPORT)
-  friend bool operator<(const BucketLocator& lhs, const BucketLocator& rhs);
+  friend auto operator<=>(const BucketLocator&, const BucketLocator&) = default;
 
   // Only positive IDs are valid. A default bucket without a specified bucket ID
   // can be represented by this struct when `id` is zero.
diff --git a/components/services/storage/public/cpp/quota_error_or.h b/components/services/storage/public/cpp/quota_error_or.h
index a9de5b4..3207646 100644
--- a/components/services/storage/public/cpp/quota_error_or.h
+++ b/components/services/storage/public/cpp/quota_error_or.h
@@ -32,13 +32,8 @@
   // NOLINTNEXTLINE(google-explicit-constructor)
   constexpr DetailedQuotaError(QuotaError error) : quota_error(error) {}
 
-  constexpr bool operator==(const DetailedQuotaError& error) const {
-    return std::tie(quota_error, sqlite_error) ==
-           std::tie(error.quota_error, error.sqlite_error);
-  }
-  constexpr bool operator!=(const DetailedQuotaError& error) const {
-    return !operator==(error);
-  }
+  friend constexpr bool operator==(const DetailedQuotaError&,
+                                   const DetailedQuotaError&) = default;
 
   QuotaError quota_error;
   int sqlite_error = 0;
@@ -48,10 +43,6 @@
                           const DetailedQuotaError& detailed_error) {
   return DetailedQuotaError(error) == detailed_error;
 }
-constexpr bool operator!=(QuotaError error,
-                          const DetailedQuotaError& detailed_error) {
-  return !operator==(error, detailed_error);
-}
 
 // Helper for methods which perform database operations which may fail. Objects
 // of this type can on either a QuotaError or a result value of arbitrary type.
diff --git a/components/sync/engine/backoff_delay_provider.cc b/components/sync/engine/backoff_delay_provider.cc
index 3fcd9997..669cf26 100644
--- a/components/sync/engine/backoff_delay_provider.cc
+++ b/components/sync/engine/backoff_delay_provider.cc
@@ -6,6 +6,7 @@
 
 #include <algorithm>
 
+#include "base/feature_list.h"
 #include "base/memory/ptr_util.h"
 #include "base/rand_util.h"
 #include "components/sync/engine/cycle/model_neutral_state.h"
@@ -17,6 +18,12 @@
 
 namespace {
 
+// If enabled, the initial delay on network error will be 1 second instead of
+// 30 seconds.
+BASE_FEATURE(kSyncShortInitialDelayOnNetworkError,
+             "SyncShortInitialDelayOnNetworkError",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // This calculates approx. last_delay * kBackoffMultiplyFactor +/- last_delay
 // * kBackoffJitterFactor. `jitter_sign` must be -1 or 1 and determines whether
 // the jitter in the delay will be positive or negative.
@@ -40,6 +47,10 @@
 // static
 std::unique_ptr<BackoffDelayProvider> BackoffDelayProvider::FromDefaults() {
   // base::WrapUnique() used because the constructor is private.
+  if (base::FeatureList::IsEnabled(kSyncShortInitialDelayOnNetworkError)) {
+    return base::WrapUnique(new BackoffDelayProvider(
+        kInitialBackoffRetryTime, kInitialBackoffShortRetryTime));
+  }
   return base::WrapUnique(new BackoffDelayProvider(
       kInitialBackoffRetryTime, kInitialBackoffImmediateRetryTime));
 }
@@ -76,6 +87,12 @@
   if (state.commit_result.type() == SyncerError::Type::kNetworkError ||
       state.last_download_updates_result.type() ==
           SyncerError::Type::kNetworkError) {
+    if (base::FeatureList::IsEnabled(kSyncShortInitialDelayOnNetworkError)) {
+      // Retry with a short delay on network error. This should be safe because
+      // it shouldn't increase traffic to the server but should help to recover
+      // from the network errors faster.
+      return short_initial_backoff_;
+    }
     return default_initial_backoff_;
   }
 
@@ -92,12 +109,12 @@
           SyncerError::Type::kProtocolError &&
       state.last_download_updates_result.GetProtocolErrorOrDie() ==
           SyncProtocolErrorType::MIGRATION_DONE) {
-    return short_initial_backoff_;
+    return kInitialBackoffImmediateRetryTime;
   }
   if (state.commit_result.type() == SyncerError::Type::kProtocolError &&
       state.commit_result.GetProtocolErrorOrDie() ==
           SyncProtocolErrorType::MIGRATION_DONE) {
-    return short_initial_backoff_;
+    return kInitialBackoffImmediateRetryTime;
   }
 
   // When the server tells us we have a conflict, then we should download the
@@ -111,7 +128,7 @@
   if (state.commit_result.type() == SyncerError::Type::kProtocolError &&
       state.commit_result.GetProtocolErrorOrDie() ==
           SyncProtocolErrorType::CONFLICT) {
-    return short_initial_backoff_;
+    return kInitialBackoffImmediateRetryTime;
   }
 
   return default_initial_backoff_;
diff --git a/components/sync/engine/backoff_delay_provider_unittest.cc b/components/sync/engine/backoff_delay_provider_unittest.cc
index d5409c6..341c18f3 100644
--- a/components/sync/engine/backoff_delay_provider_unittest.cc
+++ b/components/sync/engine/backoff_delay_provider_unittest.cc
@@ -48,7 +48,7 @@
 
   state.last_download_updates_result =
       SyncerError::NetworkError(net::ERR_FAILED);
-  EXPECT_EQ(kInitialBackoffRetryTime, delay->GetInitialDelay(state));
+  EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
 
   state.last_download_updates_result =
       SyncerError::ProtocolError(TRANSIENT_ERROR);
@@ -62,7 +62,7 @@
   EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
 
   state.commit_result = SyncerError::NetworkError(net::ERR_FAILED);
-  EXPECT_EQ(kInitialBackoffRetryTime, delay->GetInitialDelay(state));
+  EXPECT_EQ(kInitialBackoffShortRetryTime, delay->GetInitialDelay(state));
 
   state.commit_result = SyncerError::ProtocolError(CONFLICT);
   EXPECT_EQ(kInitialBackoffImmediateRetryTime, delay->GetInitialDelay(state));
diff --git a/components/system_cpu/pressure_test_support.h b/components/system_cpu/pressure_test_support.h
index 56edbb3..aaf92fd8 100644
--- a/components/system_cpu/pressure_test_support.h
+++ b/components/system_cpu/pressure_test_support.h
@@ -25,8 +25,8 @@
 
 // Test double for platform specific CpuProbe that stores the CpuSample in
 // a TestFuture.
-template <typename T,
-          typename = std::enable_if_t<std::is_base_of_v<CpuProbe, T>>>
+template <typename T>
+  requires(std::is_base_of_v<CpuProbe, T>)
 class FakePlatformCpuProbe : public T {
  public:
   template <typename... Args>
diff --git a/components/vector_icons/BUILD.gn b/components/vector_icons/BUILD.gn
index 5afaf7a..1971cfb9 100644
--- a/components/vector_icons/BUILD.gn
+++ b/components/vector_icons/BUILD.gn
@@ -307,6 +307,7 @@
         "google_chrome/google_sites.icon",
         "google_chrome/google_slides.icon",
         "google_chrome/google_super_g.icon",
+        "google_chrome/google_wallet.icon",
         "google_chrome/gshield.icon",
         "google_chrome/page_insights.icon",
         "google_chrome/page_insights_color.icon",
diff --git a/components/vector_icons/google_chrome b/components/vector_icons/google_chrome
index ecad793..61cf8b1 160000
--- a/components/vector_icons/google_chrome
+++ b/components/vector_icons/google_chrome
@@ -1 +1 @@
-Subproject commit ecad7931572c1f673bf582b785838daadbaadfab
+Subproject commit 61cf8b1548363c9573e5f3c5c5c4170e110edf81
diff --git a/components/visitedlink/core/visited_link.cc b/components/visitedlink/core/visited_link.cc
index 0f93184..b9c1829 100644
--- a/components/visitedlink/core/visited_link.cc
+++ b/components/visitedlink/core/visited_link.cc
@@ -28,18 +28,4 @@
          !frame_origin.opaque();
 }
 
-bool operator==(const VisitedLink& lhs, const VisitedLink& rhs) {
-  return std::tie(lhs.link_url, lhs.top_level_site, lhs.frame_origin) ==
-         std::tie(rhs.link_url, rhs.top_level_site, rhs.frame_origin);
-}
-
-bool operator!=(const VisitedLink& lhs, const VisitedLink& rhs) {
-  return !(lhs == rhs);
-}
-
-bool operator<(const VisitedLink& lhs, const VisitedLink& rhs) {
-  return std::tie(lhs.link_url, lhs.top_level_site, lhs.frame_origin) <
-         std::tie(rhs.link_url, rhs.top_level_site, rhs.frame_origin);
-}
-
 }  // namespace visitedlink
diff --git a/components/visitedlink/core/visited_link.h b/components/visitedlink/core/visited_link.h
index 71674d10..40b7278 100644
--- a/components/visitedlink/core/visited_link.h
+++ b/components/visitedlink/core/visited_link.h
@@ -28,14 +28,13 @@
   // A VisitedLink is valid if its components are valid and not opaque.
   bool IsValid() const;
 
+  friend bool operator==(const VisitedLink&, const VisitedLink&) = default;
+  friend auto operator<=>(const VisitedLink& lhs,
+                          const VisitedLink& rhs) = default;
+
   GURL link_url;
   net::SchemefulSite top_level_site;
   url::Origin frame_origin;
-
- private:
-  friend bool operator==(const VisitedLink& lhs, const VisitedLink& rhs);
-  friend bool operator!=(const VisitedLink& lhs, const VisitedLink& rhs);
-  friend bool operator<(const VisitedLink& lhs, const VisitedLink& rhs);
 };
 
 }  // namespace visitedlink
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
index f930a2d61..683aba7 100644
--- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc
+++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -98,6 +98,15 @@
     // spurious focus events (regardless of what the implementation does).
     property_filters.emplace_back("AutomationFocusChanged on role=region",
                                   AXPropertyFilter::DENY);
+
+    // Various tests are flaky because the following events are sometimes
+    // emitted unexpectedly on mac14.
+    property_filters.emplace_back(
+        "AXValueChanged on AXStaticText AXValue='Back'",
+        AXPropertyFilter::DENY);
+    property_filters.emplace_back(
+        "AXValueChanged on AXStaticText AXValue='Stop'",
+        AXPropertyFilter::DENY);
     return property_filters;
   }
 
diff --git a/content/browser/ai/echo_ai_language_model.cc b/content/browser/ai/echo_ai_language_model.cc
index 7c8678a..b6edcdd 100644
--- a/content/browser/ai/echo_ai_language_model.cc
+++ b/content/browser/ai/echo_ai_language_model.cc
@@ -106,6 +106,14 @@
       base::Seconds(1));
 }
 
+void EchoAILanguageModel::Append(
+    std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+    mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient> client) {
+  mojo::Remote<blink::mojom::AILanguageModelAppendClient> client_remote(
+      std::move(client));
+  client_remote->OnAppendComplete();
+}
+
 void EchoAILanguageModel::Fork(
     mojo::PendingRemote<blink::mojom::AIManagerCreateLanguageModelClient>
         client) {
diff --git a/content/browser/ai/echo_ai_language_model.h b/content/browser/ai/echo_ai_language_model.h
index 069318fbe..baf6343e 100644
--- a/content/browser/ai/echo_ai_language_model.h
+++ b/content/browser/ai/echo_ai_language_model.h
@@ -30,6 +30,9 @@
               on_device_model::mojom::ResponseConstraintPtr constraint,
               mojo::PendingRemote<blink::mojom::ModelStreamingResponder>
                   pending_responder) override;
+  void Append(std::vector<blink::mojom::AILanguageModelPromptPtr> prompts,
+              mojo::PendingRemote<blink::mojom::AILanguageModelAppendClient>
+                  client) override;
   void Fork(
       mojo::PendingRemote<blink::mojom::AIManagerCreateLanguageModelClient>
           client) override;
diff --git a/content/browser/renderer_host/media/media_stream_manager_unittest.cc b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
index 2c18d6a..881a08c 100644
--- a/content/browser/renderer_host/media/media_stream_manager_unittest.cc
+++ b/content/browser/renderer_host/media/media_stream_manager_unittest.cc
@@ -1712,8 +1712,7 @@
   const base::UnguessableToken transfer_id_ = base::UnguessableToken::Create();
   blink::MediaStreamDevice original_device_;
   blink::MediaStreamDevice transferred_device_;
-  blink::mojom::MediaStreamRequestResult result_ =
-      blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS;
+  std::optional<blink::mojom::MediaStreamRequestResult> result_;
 };
 
 TEST_F(MediaStreamManagerTestForTransfers,
diff --git a/content/browser/service_worker/embedded_worker_instance_unittest.cc b/content/browser/service_worker/embedded_worker_instance_unittest.cc
index fb1aab2d..a136b083 100644
--- a/content/browser/service_worker/embedded_worker_instance_unittest.cc
+++ b/content/browser/service_worker/embedded_worker_instance_unittest.cc
@@ -382,7 +382,7 @@
   RegistrationAndVersionPair pair =
       helper_->PrepareRegistrationAndVersion(scope, url);
   // We should set COEP, or cache storage pipe won't be made.
-  pair.second->set_policy_container_host(
+  pair.second->SetPolicyContainerHost(
       base::MakeRefCounted<PolicyContainerHost>());
   auto worker = std::make_unique<EmbeddedWorkerInstance>(pair.second.get());
 
diff --git a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
index 665756f..aac71b3 100644
--- a/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
+++ b/content/browser/service_worker/service_worker_controllee_request_handler_unittest.cc
@@ -195,7 +195,7 @@
         registration_.get(), script_url_, blink::mojom::ScriptType::kClassic,
         1L, mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef>(),
         context()->AsWeakPtr());
-    version_->set_policy_container_host(
+    version_->SetPolicyContainerHost(
         base::MakeRefCounted<PolicyContainerHost>(PolicyContainerPolicies()));
 
     std::vector<storage::mojom::ServiceWorkerResourceRecordPtr> records;
diff --git a/content/browser/service_worker/service_worker_job_unittest.cc b/content/browser/service_worker/service_worker_job_unittest.cc
index 036eb915..1c3da97 100644
--- a/content/browser/service_worker/service_worker_job_unittest.cc
+++ b/content/browser/service_worker/service_worker_job_unittest.cc
@@ -952,7 +952,7 @@
       registration.get(), script_url, blink::mojom::ScriptType::kClassic, 1L,
       mojo::PendingRemote<storage::mojom::ServiceWorkerLiveVersionRef>(),
       helper_->context()->AsWeakPtr());
-  version->set_policy_container_host(
+  version->SetPolicyContainerHost(
       base::MakeRefCounted<PolicyContainerHost>(PolicyContainerPolicies()));
   ASSERT_EQ(blink::ServiceWorkerStatusCode::kOk,
             StartServiceWorker(version.get()));
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
index 64b0e18..c1f0b84 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
@@ -510,7 +510,7 @@
     version_->SetStatus(ServiceWorkerVersion::ACTIVATED);
     PolicyContainerPolicies policies;
     policies.ip_address_space = network::mojom::IPAddressSpace::kPrivate;
-    version_->set_policy_container_host(
+    version_->SetPolicyContainerHost(
         base::MakeRefCounted<PolicyContainerHost>(std::move(policies)));
     registration_->SetActiveVersion(version_);
 
diff --git a/content/browser/service_worker/service_worker_new_script_loader.cc b/content/browser/service_worker/service_worker_new_script_loader.cc
index 513dfe3b..656d452 100644
--- a/content/browser/service_worker/service_worker_new_script_loader.cc
+++ b/content/browser/service_worker/service_worker_new_script_loader.cc
@@ -294,7 +294,7 @@
              ->browser()
              ->ShouldServiceWorkerInheritPolicyContainerFromCreator(
                  request_url_)) {
-      version_->set_policy_container_host(
+      version_->SetPolicyContainerHost(
           base::MakeRefCounted<PolicyContainerHost>(
               // TODO(crbug.com/40235036): Add DCHECK to parsed_headers
               response_head->parsed_headers
diff --git a/content/browser/service_worker/service_worker_register_job.cc b/content/browser/service_worker/service_worker_register_job.cc
index 97701ad..e4471d7 100644
--- a/content/browser/service_worker/service_worker_register_job.cc
+++ b/content/browser/service_worker/service_worker_register_job.cc
@@ -588,7 +588,7 @@
   if (GetContentClient()
           ->browser()
           ->ShouldServiceWorkerInheritPolicyContainerFromCreator(script_url_)) {
-    new_version()->set_policy_container_host(
+    new_version()->SetPolicyContainerHost(
         base::MakeRefCounted<PolicyContainerHost>(
             std::move(creator_policy_container_policies_)));
   }
diff --git a/content/browser/service_worker/service_worker_registry.cc b/content/browser/service_worker/service_worker_registry.cc
index 5e036f6c..b0486de 100644
--- a/content/browser/service_worker/service_worker_registry.cc
+++ b/content/browser/service_worker/service_worker_registry.cc
@@ -1082,10 +1082,9 @@
     version->set_used_features(std::move(used_features));
     // policy_container_host could be null for registration restored from old DB
     if (data.policy_container_policies) {
-      version->set_policy_container_host(
-          base::MakeRefCounted<PolicyContainerHost>(
-              PolicyContainerPolicies(*data.policy_container_policies,
-                                      /*is_web_secure_context=*/true)));
+      version->SetPolicyContainerHost(base::MakeRefCounted<PolicyContainerHost>(
+          PolicyContainerPolicies(*data.policy_container_policies,
+                                  /*is_web_secure_context=*/true)));
     }
     if (data.router_rules) {
       auto error = version->SetupRouterEvaluator(*data.router_rules);
diff --git a/content/browser/service_worker/service_worker_registry_unittest.cc b/content/browser/service_worker/service_worker_registry_unittest.cc
index 04c87715..e387ccc2 100644
--- a/content/browser/service_worker/service_worker_registry_unittest.cc
+++ b/content/browser/service_worker/service_worker_registry_unittest.cc
@@ -808,7 +808,7 @@
       network::mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
   auto policy_container_host = base::MakeRefCounted<PolicyContainerHost>();
   policy_container_host->set_cross_origin_embedder_policy(coep_require_corp);
-  live_version->set_policy_container_host(std::move(policy_container_host));
+  live_version->SetPolicyContainerHost(std::move(policy_container_host));
   live_registration->SetWaitingVersion(live_version);
   live_registration->set_last_update_check(kYesterday);
   EXPECT_EQ(blink::ServiceWorkerStatusCode::kOk,
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc
index 8d5fcf74..5cf4224 100644
--- a/content/browser/service_worker/service_worker_version.cc
+++ b/content/browser/service_worker/service_worker_version.cc
@@ -1206,6 +1206,17 @@
   main_script_load_params_.reset();
 }
 
+void ServiceWorkerVersion::SetPolicyContainerHost(
+    scoped_refptr<PolicyContainerHost> policy_container_host) {
+  policy_container_host_ = std::move(policy_container_host);
+  if (policy_container_host_ &&
+      policy_container_host_->policies()
+              .integrity_policy.blocked_destinations.size() > 0) {
+    CountFeature(
+        blink::mojom::WebFeature::kIntegrityPolicyInServiceWorkerResponse);
+  }
+}
+
 void ServiceWorkerVersion::InitializeGlobalScope() {
   TRACE_EVENT0("ServiceWorker", "ServiceWorkerVersion::InitializeGlobalScope");
   receiver_.reset();
@@ -3009,7 +3020,7 @@
            ->browser()
            ->ShouldServiceWorkerInheritPolicyContainerFromCreator(
                updated_script_url)) {
-    set_policy_container_host(policy_container_host);
+    SetPolicyContainerHost(policy_container_host);
   }
 }
 
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h
index 55c3e6b..7c39b06 100644
--- a/content/browser/service_worker/service_worker_version.h
+++ b/content/browser/service_worker/service_worker_version.h
@@ -674,10 +674,8 @@
     return receiver_;
   }
 
-  void set_policy_container_host(
-      scoped_refptr<PolicyContainerHost> policy_container_host) {
-    policy_container_host_ = std::move(policy_container_host);
-  }
+  void SetPolicyContainerHost(
+      scoped_refptr<PolicyContainerHost> policy_container_host);
 
   // Initializes the global scope of the ServiceWorker on the renderer side.
   void InitializeGlobalScope();
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc
index d122facd..4e1b966e 100644
--- a/content/browser/worker_host/shared_worker_host.cc
+++ b/content/browser/worker_host/shared_worker_host.cc
@@ -68,7 +68,8 @@
 
 // TODO(crbug.com/400473072): revisit the duration.
 // Also, we may want to use the same constant we use for service workers.
-constexpr base::TimeDelta kSharedWorkerDestructionDelay = base::Seconds(30);
+// Current value come from `ServiceWorkerVersion::kRequestTimeout`.
+constexpr base::TimeDelta kSharedWorkerDestructionDelay = base::Minutes(5);
 
 }  // namespace
 
diff --git a/content/public/android/BUILD.gn b/content/public/android/BUILD.gn
index c5c07a25..7af9aa1d 100644
--- a/content/public/android/BUILD.gn
+++ b/content/public/android/BUILD.gn
@@ -366,7 +366,6 @@
     "java/src/org/chromium/content/browser/webcontents/EmptyInternalAccessDelegate.java",
     "java/src/org/chromium/content/browser/webcontents/WebContentsImpl.java",
     "java/src/org/chromium/content/browser/webcontents/WebContentsObserverProxy.java",
-    "java/src/org/chromium/content/browser/webid/DigitalCredentialsCreationDelegate.java",
     "java/src/org/chromium/content_public/browser/ActionModeCallback.java",
     "java/src/org/chromium/content_public/browser/ActionModeCallbackHelper.java",
     "java/src/org/chromium/content_public/browser/AdditionalNavigationParams.java",
diff --git a/content/public/android/java/src/org/chromium/content/browser/webid/DigitalCredentialsCreationDelegate.java b/content/public/android/java/src/org/chromium/content/browser/webid/DigitalCredentialsCreationDelegate.java
deleted file mode 100644
index 90150f27..0000000
--- a/content/public/android/java/src/org/chromium/content/browser/webid/DigitalCredentialsCreationDelegate.java
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2024 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-package org.chromium.content.browser.webid;
-
-import android.app.Activity;
-
-import org.chromium.base.Promise;
-import org.chromium.build.annotations.NullMarked;
-
-/**
- * Delegate interface for calling into GMSCore's private identity credentials.
- *
- * <p>TODO(crbug.com/380039257) delete this once GMSCore publishes this API.
- */
-@NullMarked
-public interface DigitalCredentialsCreationDelegate {
-    public Promise<String> create(Activity window, String origin, String request);
-}
diff --git a/content/test/fuzzer/BUILD.gn b/content/test/fuzzer/BUILD.gn
index 9cb6f8f..897363d 100644
--- a/content/test/fuzzer/BUILD.gn
+++ b/content/test/fuzzer/BUILD.gn
@@ -200,6 +200,7 @@
     ":mojolpm_fuzzer_support",
     "//content/browser:for_content_tests",
     "//content/public/browser:browser_sources",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
   proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
@@ -219,10 +220,11 @@
     ":mojolpm_fuzzer_support",
     "//testing/libfuzzer/proto:url_proto_converter",
     "//third_party/blink/public/common:storage_key_proto_converter",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
   proto_deps = [
-    "//third_party/blink/public/common:storage_key_proto",
+    "//third_party/blink/public/common:storage_key",
     "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 }
@@ -236,6 +238,7 @@
     ":mojolpm_fuzzer_support",
     "//content/browser:for_content_tests",
     "//content/public/browser:browser_sources",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
   proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
@@ -363,6 +366,7 @@
     "//content/browser:browser",
     "//content/browser:for_content_tests",
     "//content/public/browser:browser_sources",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
   proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
@@ -384,6 +388,7 @@
       "//media:test_support",
       "//media/capture:capture_lib",
       "//media/capture:test_support",
+      "//media/capture/mojom:video_capture_mojolpm",
       "//third_party/blink/public/common:common",
     ]
 
@@ -401,6 +406,7 @@
     "//content/browser:for_content_tests",
     "//content/public/browser:browser_sources",
     "//media/capture:capture_lib",
+    "//media/capture/mojom:image_capture_mojolpm",
   ]
 
   proto_deps = [ "//media/capture/mojom:image_capture_mojolpm" ]
@@ -415,11 +421,12 @@
     ":controller_presentation_service_delegate_for_fuzzing",
     ":mojolpm_fuzzer_support",
     "//content/browser:for_content_tests",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
     "//ui/events/devices:devices",
   ]
 
   proto_deps = [
-    ":controller_presentation_service_delegate_for_fuzzing_proto",
+    ":controller_presentation_service_delegate_for_fuzzing",
     "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 }
@@ -434,6 +441,7 @@
     "//content/browser:browser",
     "//content/browser:for_content_tests",
     "//content/public/browser:browser_sources",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
   proto_deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm" ]
@@ -464,11 +472,12 @@
     "//content/public/browser:browser_sources",
     "//content/test:test_support",
     "//services/data_decoder/public/cpp:test_support",
+    "//third_party/blink/public/mojom:mojom_platform_mojolpm",
     "//third_party/metrics_proto",
   ]
 
   proto_deps = [
-    ":ad_auction_service_mojolpm_fuzzer_stringifiers_proto",
+    ":ad_auction_service_mojolpm_fuzzer_stringifiers",
     "//third_party/blink/public/mojom:mojom_platform_mojolpm",
   ]
 
@@ -511,14 +520,7 @@
     sources = [ "controller_presentation_service_delegate_for_fuzzing.proto" ]
     generate_python = false
 
-    proto_deps = [
-      "//third_party/blink/public/mojom:mojom_platform_mojolpm",
-      "//url/mojom:url_mojom_gurl_mojolpm",
-    ]
-    link_deps = [
-      "//third_party/blink/public/mojom:mojom_platform_mojolpm",
-      "//url/mojom:url_mojom_gurl_mojolpm",
-    ]
+    deps = [ "//third_party/blink/public/mojom:mojom_platform_mojolpm_proto" ]
 
     import_dirs = [ root_gen_dir ]
     testonly = true
diff --git a/crypto/unexportable_key_software_unsecure.cc b/crypto/unexportable_key_software_unsecure.cc
index d6fd8a4..562d3b5 100644
--- a/crypto/unexportable_key_software_unsecure.cc
+++ b/crypto/unexportable_key_software_unsecure.cc
@@ -9,7 +9,7 @@
 
 #include "base/check.h"
 #include "build/build_config.h"
-#include "crypto/sha2.h"
+#include "crypto/hash.h"
 #include "crypto/signature_verifier.h"
 #include "crypto/unexportable_key.h"
 #include "third_party/boringssl/src/include/openssl/bn.h"
@@ -64,7 +64,7 @@
   std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override {
     std::vector<uint8_t> ret(ECDSA_size(key_.get()));
-    std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
+    std::array<uint8_t, hash::kSha256Size> digest = hash::Sha256(data);
     unsigned int ret_size;
     CHECK(ECDSA_sign(0, digest.data(), digest.size(), ret.data(), &ret_size,
                      key_.get()));
@@ -109,7 +109,7 @@
   std::optional<std::vector<uint8_t>> SignSlowly(
       base::span<const uint8_t> data) override {
     std::vector<uint8_t> ret(RSA_size(key_.get()));
-    std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
+    std::array<uint8_t, hash::kSha256Size> digest = hash::Sha256(data);
     unsigned int ret_size;
     CHECK(RSA_sign(NID_sha256, digest.data(), digest.size(), ret.data(),
                    &ret_size, key_.get()));
diff --git a/crypto/unexportable_key_win.cc b/crypto/unexportable_key_win.cc
index 79c4ba7c..4384567 100644
--- a/crypto/unexportable_key_win.cc
+++ b/crypto/unexportable_key_win.cc
@@ -28,8 +28,8 @@
 #include "base/threading/scoped_thread_priority.h"
 #include "base/types/expected.h"
 #include "base/types/optional_util.h"
+#include "crypto/hash.h"
 #include "crypto/random.h"
-#include "crypto/sha2.h"
 #include "crypto/unexportable_key.h"
 #include "crypto/unexportable_key_metrics.h"
 #include "third_party/boringssl/src/include/openssl/bn.h"
@@ -293,7 +293,7 @@
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
 
-  std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
+  std::array<uint8_t, hash::kSha256Size> digest = hash::Sha256(data);
   // The signature is written as a pair of big-endian field elements for P-256
   // ECDSA.
   std::vector<uint8_t> sig(64);
@@ -327,7 +327,7 @@
   base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
                                                 base::BlockingType::WILL_BLOCK);
 
-  std::array<uint8_t, kSHA256Length> digest = SHA256Hash(data);
+  std::array<uint8_t, hash::kSha256Size> digest = hash::Sha256(data);
   BCRYPT_PKCS1_PADDING_INFO padding_info = {0};
   padding_info.pszAlgId = NCRYPT_SHA256_ALGORITHM;
 
diff --git a/mojo/core/channel.cc b/mojo/core/channel.cc
index d536cae..e04a1e29 100644
--- a/mojo/core/channel.cc
+++ b/mojo/core/channel.cc
@@ -136,7 +136,7 @@
   size_t NumHandlesForTransit() const override { return handles_.size(); }
 
   const void* data() const override { return data_.get(); }
-  void* mutable_data() const override { NOTREACHED(); }
+  void* mutable_data() override { NOTREACHED(); }
   size_t capacity() const override { return size_; }
 
   bool ExtendPayload(size_t) override { NOTREACHED(); }
@@ -166,7 +166,7 @@
   size_t NumHandlesForTransit() const override;
 
   const void* data() const override { return data_.get(); }
-  void* mutable_data() const override { return data_.get(); }
+  void* mutable_data() override { return data_.get(); }
   size_t capacity() const override;
 
   bool ExtendPayload(size_t new_payload_size) override;
@@ -208,9 +208,7 @@
 
   // Message impl:
   const void* data() const override { return &data_[0]; }
-  void* mutable_data() const override {
-    return const_cast<uint8_t*>(&data_[0]);
-  }
+  void* mutable_data() override { return data_; }
 
   size_t capacity() const override;
 
@@ -503,14 +501,21 @@
   return legacy_header()->message_type == MessageType::NORMAL_LEGACY;
 }
 
-Channel::Message::LegacyHeader* Channel::Message::legacy_header() const {
+Channel::Message::LegacyHeader* Channel::Message::legacy_header() {
   return reinterpret_cast<LegacyHeader*>(mutable_data());
 }
+const Channel::Message::LegacyHeader* Channel::Message::legacy_header() const {
+  return reinterpret_cast<const LegacyHeader*>(data());
+}
 
-Channel::Message::Header* Channel::Message::header() const {
+Channel::Message::Header* Channel::Message::header() {
   DCHECK(!is_legacy_message());
   return reinterpret_cast<Header*>(mutable_data());
 }
+const Channel::Message::Header* Channel::Message::header() const {
+  DCHECK(!is_legacy_message());
+  return reinterpret_cast<const Header*>(data());
+}
 
 ComplexMessage::ComplexMessage(size_t capacity,
                                size_t payload_size,
diff --git a/mojo/core/channel.h b/mojo/core/channel.h
index d990029..421f17b 100644
--- a/mojo/core/channel.h
+++ b/mojo/core/channel.h
@@ -237,7 +237,7 @@
         base::ProcessHandle from_process = base::kNullProcessHandle);
 
     virtual const void* data() const = 0;
-    virtual void* mutable_data() const = 0;
+    virtual void* mutable_data() = 0;
 
     size_t data_num_bytes() const { return size_; }
 
@@ -257,8 +257,10 @@
     bool has_handles() const;
 
     bool is_legacy_message() const;
-    LegacyHeader* legacy_header() const;
-    Header* header() const;
+    LegacyHeader* legacy_header();
+    const LegacyHeader* legacy_header() const;
+    Header* header();
+    const Header* header() const;
 
     // Note: SetHandles() and TakeHandles() invalidate any previous value of
     // handles().
diff --git a/mojo/public/tools/bindings/mojom.gni b/mojo/public/tools/bindings/mojom.gni
index 8a43e0b3..758e3ac 100644
--- a/mojo/public/tools/bindings/mojom.gni
+++ b/mojo/public/tools/bindings/mojom.gni
@@ -1181,10 +1181,8 @@
         import_dirs = [ "//" ]
         proto_in_dir = "${root_gen_dir}"
         proto_out_dir = "."
-        proto_deps = [
-          ":$generator_mojolpm_proto_target_name",
-          "//mojo/public/tools/fuzzers:mojolpm_proto",
-        ]
+        deps = [ "//mojo/public/tools/fuzzers:mojolpm_proto" ]
+        proto_deps = [ ":$generator_mojolpm_proto_target_name" ]
         link_deps = []
 
         foreach(d, all_deps) {
@@ -1192,8 +1190,7 @@
           # //mojo/something:something and we can append mojolpm_proto_suffix
           # to get the proto dependency name.
           full_name = get_label_info("$d", "label_no_toolchain")
-          proto_deps += [ "${full_name}_mojolpm_proto" ]
-          link_deps += [ "${full_name}_mojolpm_proto" ]
+          deps += [ "${full_name}_mojolpm_proto" ]
         }
       }
     } else {
diff --git a/mojo/public/tools/fuzzers/mojolpm.gni b/mojo/public/tools/fuzzers/mojolpm.gni
index 41394c7..4c99521 100644
--- a/mojo/public/tools/fuzzers/mojolpm.gni
+++ b/mojo/public/tools/fuzzers/mojolpm.gni
@@ -30,6 +30,9 @@
 #   proto_deps
 #       List of additional dependencies for compiling proto_source.
 #
+#   proto_gen_deps
+#       List of dependencies for generating proto_source.
+#
 #   proto_in_dir
 #       See documentation at //third_party/protobuf/proto_library.gni.
 #
@@ -97,18 +100,24 @@
       sources = [ invoker.proto_source ]
       generate_python = false
 
-      proto_deps = []
-
       import_dirs = [
         root_gen_dir,
         "//",
       ]
 
-      link_deps = []
-
       if (defined(invoker.proto_deps)) {
-        proto_deps += invoker.proto_deps
-        link_deps += invoker.proto_deps
+        deps = []
+        foreach(proto_dep, invoker.proto_deps) {
+          deps += [ "${proto_dep}_proto" ]
+        }
+      }
+
+      if (defined(invoker.proto_gen_deps)) {
+        proto_deps = invoker.proto_gen_deps
+      }
+
+      if (defined(invoker.proto_gen_deps)) {
+        proto_deps += invoker.proto_gen_deps
       }
 
       testonly = true
@@ -137,7 +146,9 @@
         deps = []
 
         if (defined(invoker.proto_deps)) {
-          deps += invoker.proto_deps
+          foreach(proto_dep, invoker.proto_deps) {
+            deps += [ "${proto_dep}_proto" ]
+          }
         }
 
         testonly = true
@@ -310,14 +321,15 @@
     }
 
     mojolpm_fuzzer_test(target_name) {
-      proto_deps = [ ":${_generate_target_name}" ]
-      deps = [ ":${_generate_target_name}" ]
+      proto_gen_deps = [ ":${_generate_target_name}" ]
       proto_source = "${target_gen_dir}/${_target_name}.proto"
       proto_in_dir = "${root_gen_dir}"
       proto_out_dir = "."
+      deps = []
 
       if (defined(invoker.proto_deps)) {
-        proto_deps += invoker.proto_deps
+        proto_deps = invoker.proto_deps
+        deps += invoker.proto_deps
       }
 
       if (defined(invoker.deps)) {
diff --git a/net/base/features.cc b/net/base/features.cc
index 79cb6df..7041e67 100644
--- a/net/base/features.cc
+++ b/net/base/features.cc
@@ -770,4 +770,8 @@
              "RestrictAbusePorts",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kRestrictAbusePortsOnLocalhost,
+             "RestrictAbusePortsOnLocalhost",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 }  // namespace net::features
diff --git a/net/base/features.h b/net/base/features.h
index 0178b48..91bab060 100644
--- a/net/base/features.h
+++ b/net/base/features.h
@@ -791,6 +791,9 @@
 NET_EXPORT extern const base::FeatureParam<std::string>
     kPortsToRestrictForAbuseMonitorOnly;
 
+// Finch-controlled list of ports that should be blocked on localhost.
+NET_EXPORT BASE_DECLARE_FEATURE(kRestrictAbusePortsOnLocalhost);
+
 }  // namespace net::features
 
 #endif  // NET_BASE_FEATURES_H_
diff --git a/net/base/port_util.cc b/net/base/port_util.cc
index aed5aca..ed3723b 100644
--- a/net/base/port_util.cc
+++ b/net/base/port_util.cc
@@ -20,6 +20,7 @@
 #include "base/strings/string_split.h"
 #include "base/strings/string_util.h"
 #include "net/base/features.h"
+#include "net/base/ip_endpoint.h"
 #include "net/base/parse_number.h"
 #include "url/url_constants.h"
 
@@ -130,9 +131,10 @@
 
 using PortSet = base::flat_set<int>;
 
-PortSet ParseRestrictedPortsFromParam(std::string_view param_name) {
-  const std::string ports_string = base::GetFieldTrialParamValueByFeature(
-      features::kRestrictAbusePorts, std::string(param_name));
+PortSet ParseRestrictedPortsFromFeatureParam(const base::Feature& feature,
+                                             std::string_view param_name) {
+  const std::string ports_string =
+      base::GetFieldTrialParamValueByFeature(feature, std::string(param_name));
   PortSet::container_type ports;
   for (const auto& port_string :
        base::SplitStringPiece(ports_string, ",", base::TRIM_WHITESPACE,
@@ -149,6 +151,8 @@
   return PortSet(std::move(ports));
 }
 
+constinit bool g_need_to_reset_restrict_localhost_ports = false;
+
 }  // namespace
 
 bool IsPortValid(int port) {
@@ -177,21 +181,54 @@
 
   if (base::FeatureList::IsEnabled(features::kRestrictAbusePorts)) {
     static const base::NoDestructor<PortSet> restrict_ports(
-        ParseRestrictedPortsFromParam("restrict_ports"));
+        ParseRestrictedPortsFromFeatureParam(features::kRestrictAbusePorts,
+                                             "restrict_ports"));
     static const base::NoDestructor<PortSet> monitor_ports(
-        ParseRestrictedPortsFromParam("monitor_ports"));
+        ParseRestrictedPortsFromFeatureParam(features::kRestrictAbusePorts,
+                                             "monitor_ports"));
 
     if (restrict_ports->contains(port)) {
       base::UmaHistogramSparse("Net.RestrictedPorts", port);
       return false;
     } else if (monitor_ports->contains(port)) {
       base::UmaHistogramSparse("Net.RestrictedPorts", port);
-    };
+    }
   }
 
   return true;
 }
 
+bool IsPortAllowedForIpEndpoint(const IPEndPoint& endpoint) {
+  if (!base::FeatureList::IsEnabled(features::kRestrictAbusePortsOnLocalhost)) {
+    return true;
+  }
+
+  // This function currently restricts only on localhost.
+  if (!endpoint.address().IsLoopback()) {
+    return true;
+  }
+
+  int port = endpoint.port();
+
+  // Allow explicitly allowed ports.
+  if (g_explicitly_allowed_ports.Get().count(port) > 0) {
+    return true;
+  }
+
+  static base::NoDestructor<PortSet> restrict_localhost_ports(
+      ParseRestrictedPortsFromFeatureParam(
+          features::kRestrictAbusePortsOnLocalhost,
+          "localhost_restrict_ports"));
+
+  if (g_need_to_reset_restrict_localhost_ports) {
+    *restrict_localhost_ports = ParseRestrictedPortsFromFeatureParam(
+        features::kRestrictAbusePortsOnLocalhost, "localhost_restrict_ports");
+    g_need_to_reset_restrict_localhost_ports = false;
+  }
+
+  return !restrict_localhost_ports->contains(port);
+}
+
 size_t GetCountOfExplicitlyAllowedPorts() {
   return g_explicitly_allowed_ports.Get().size();
 }
@@ -238,4 +275,8 @@
   g_scoped_allowable_port = 0;
 }
 
+void ReloadLocalhostRestrictedPortsForTesting() {
+  g_need_to_reset_restrict_localhost_ports = true;
+}
+
 }  // namespace net
diff --git a/net/base/port_util.h b/net/base/port_util.h
index 91f707c..7dd1b9a40 100644
--- a/net/base/port_util.h
+++ b/net/base/port_util.h
@@ -11,6 +11,7 @@
 #include <string_view>
 
 #include "base/containers/span.h"
+#include "net/base/ip_endpoint.h"
 #include "net/base/net_export.h"
 
 namespace net {
@@ -28,6 +29,8 @@
 // considered allowed for any scheme.
 NET_EXPORT bool IsPortAllowedForScheme(int port, std::string_view url_scheme);
 
+NET_EXPORT bool IsPortAllowedForIpEndpoint(const IPEndPoint& endpoint);
+
 // Returns the number of explicitly allowed ports; for testing.
 NET_EXPORT_PRIVATE size_t GetCountOfExplicitlyAllowedPorts();
 
@@ -45,6 +48,10 @@
 // other ports.
 NET_EXPORT bool IsAllowablePort(int port);
 
+// For testing: reloads the restricted ports set by the feature flag
+// `kRestrictAbusePortsOnLocalhost`.
+NET_EXPORT_PRIVATE void ReloadLocalhostRestrictedPortsForTesting();
+
 class NET_EXPORT ScopedPortException {
  public:
   explicit ScopedPortException(int port);
diff --git a/net/base/port_util_unittest.cc b/net/base/port_util_unittest.cc
index 58340cf7..6e8a380 100644
--- a/net/base/port_util_unittest.cc
+++ b/net/base/port_util_unittest.cc
@@ -10,6 +10,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/test/scoped_feature_list.h"
 #include "net/base/features.h"
+#include "net/base/ip_address.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace net {
@@ -47,4 +48,25 @@
   histogram_tester.ExpectBucketCount("Net.RestrictedPorts", 45678, 1);
 }
 
+TEST(NetUtilTest, RestrictedAbusePortsLocalhostTest) {
+  base::test::ScopedFeatureList feature_list;
+  feature_list.InitAndEnableFeatureWithParameters(
+      features::kRestrictAbusePortsOnLocalhost,
+      {{"localhost_restrict_ports", "12345,23456,34567"}});
+  ReloadLocalhostRestrictedPortsForTesting();
+  IPAddress public_address(8, 8, 8, 8);
+  EXPECT_TRUE(IsPortAllowedForIpEndpoint(IPEndPoint(public_address, 12345)));
+  EXPECT_TRUE(IsPortAllowedForIpEndpoint(IPEndPoint(public_address, 443)));
+  EXPECT_TRUE(
+      IsPortAllowedForIpEndpoint(IPEndPoint(IPAddress::IPv4Localhost(), 443)));
+  EXPECT_TRUE(
+      IsPortAllowedForIpEndpoint(IPEndPoint(IPAddress::IPv6Localhost(), 443)));
+  for (int port : {12345, 23456, 34567}) {
+    EXPECT_FALSE(IsPortAllowedForIpEndpoint(
+        IPEndPoint(IPAddress::IPv4Localhost(), port)));
+    EXPECT_FALSE(IsPortAllowedForIpEndpoint(
+        IPEndPoint(IPAddress::IPv6Localhost(), port)));
+  }
+}
+
 }  // namespace net
diff --git a/net/socket/tcp_client_socket.cc b/net/socket/tcp_client_socket.cc
index 1e33649..65ea2378 100644
--- a/net/socket/tcp_client_socket.cc
+++ b/net/socket/tcp_client_socket.cc
@@ -18,6 +18,7 @@
 #include "net/base/io_buffer.h"
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
+#include "net/base/port_util.h"
 #include "net/nqe/network_quality_estimator.h"
 #include "net/socket/socket_performance_watcher.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
@@ -240,6 +241,10 @@
 
   next_connect_state_ = CONNECT_STATE_CONNECT_COMPLETE;
 
+  if (!IsPortAllowedForIpEndpoint(endpoint)) {
+    return ERR_UNSAFE_PORT;
+  }
+
   if (!socket_->IsValid()) {
     int result = OpenSocket(endpoint.GetFamily());
     if (result != OK)
diff --git a/net/socket/tcp_client_socket_unittest.cc b/net/socket/tcp_client_socket_unittest.cc
index 03c1c24f..9503ab329 100644
--- a/net/socket/tcp_client_socket_unittest.cc
+++ b/net/socket/tcp_client_socket_unittest.cc
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "net/base/port_util.h"
 #ifdef UNSAFE_BUFFERS_BUILD
 // TODO(crbug.com/390223051): Remove C-library calls to fix the errors.
 #pragma allow_unsafe_libc_calls
@@ -325,6 +326,29 @@
               testing::ElementsAre("alias1", "alias2", "host"));
 }
 
+TEST_P(TCPClientSocketTest, BlockRestrictedAddress) {
+  base::test::ScopedFeatureList feature_list;
+  IPAddress lo_address = IPAddress::IPv4Localhost();
+  TCPServerSocket server(nullptr, NetLogSource());
+  ASSERT_THAT(
+      server.Listen(IPEndPoint(lo_address, 0), 1, /*ipv6_only=*/std::nullopt),
+      IsOk());
+  IPEndPoint server_address;
+  ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
+  feature_list.InitAndEnableFeatureWithParameters(
+      features::kRestrictAbusePortsOnLocalhost,
+      {{"localhost_restrict_ports",
+        base::NumberToString(server_address.port())}});
+  ReloadLocalhostRestrictedPortsForTesting();
+  TCPClientSocket socket(AddressList(server_address), nullptr, nullptr, nullptr,
+                         NetLogSource());
+
+  TestCompletionCallback connect_callback;
+  int connect_result = socket.Connect(connect_callback.callback());
+  EXPECT_THAT(connect_callback.GetResult(connect_result),
+              IsError(ERR_UNSAFE_PORT));
+}
+
 class TestSocketPerformanceWatcher : public SocketPerformanceWatcher {
  public:
   TestSocketPerformanceWatcher() = default;
diff --git a/net/socket/udp_client_socket.cc b/net/socket/udp_client_socket.cc
index c955d56c..4422c4d2 100644
--- a/net/socket/udp_client_socket.cc
+++ b/net/socket/udp_client_socket.cc
@@ -8,6 +8,7 @@
 #include "build/build_config.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_change_notifier.h"
+#include "net/base/port_util.h"
 #include "net/traffic_annotation/network_traffic_annotation.h"
 
 namespace net {
@@ -65,6 +66,9 @@
 
 int UDPClientSocket::Connect(const IPEndPoint& address) {
   CHECK(!connect_called_);
+  if (!IsPortAllowedForIpEndpoint(address)) {
+    return ERR_UNSAFE_PORT;
+  }
   if (connect_using_network_ != handles::kInvalidNetworkHandle)
     return ConnectUsingNetwork(connect_using_network_, address);
 
diff --git a/net/socket/udp_socket_unittest.cc b/net/socket/udp_socket_unittest.cc
index 274f6f0b..683922a 100644
--- a/net/socket/udp_socket_unittest.cc
+++ b/net/socket/udp_socket_unittest.cc
@@ -25,6 +25,7 @@
 #include "net/base/ip_endpoint.h"
 #include "net/base/net_errors.h"
 #include "net/base/network_interfaces.h"
+#include "net/base/port_util.h"
 #include "net/base/test_completion_callback.h"
 #include "net/log/net_log_event_type.h"
 #include "net/log/net_log_source.h"
@@ -326,6 +327,26 @@
   ConnectTest(false, true);
 }
 
+TEST_F(UDPSocketTest, ConnectRestrictedPort) {
+  base::test::ScopedFeatureList feature_list;
+  // Setup the server to listen.
+  UDPServerSocket server(NetLog::Get(), NetLogSource());
+  server.AllowAddressReuse();
+  ASSERT_THAT(server.Listen(IPEndPoint(IPAddress::IPv4Localhost(), 0)), IsOk());
+  // Get bound port.
+  IPEndPoint server_address;
+  ASSERT_THAT(server.GetLocalAddress(&server_address), IsOk());
+  feature_list.InitAndEnableFeatureWithParameters(
+      features::kRestrictAbusePortsOnLocalhost,
+      {{"localhost_restrict_ports",
+        base::NumberToString(server_address.port())}});
+  ReloadLocalhostRestrictedPortsForTesting();
+  // Setup the client.
+  auto client = std::make_unique<UDPClientSocket>(
+      DatagramSocket::DEFAULT_BIND, NetLog::Get(), NetLogSource());
+  EXPECT_THAT(client->Connect(server_address), IsError(ERR_UNSAFE_PORT));
+}
+
 #if BUILDFLAG(IS_WIN)
 TEST_F(UDPSocketTest, ConnectNonBlocking) {
   ConnectTest(true, false);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index e3f4ca651..f6432d8 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -11934,6 +11934,21 @@
             ]
         }
     ],
+    "IOSPartitionAllocMemoryReclaimer": [
+        {
+            "platforms": [
+                "ios"
+            ],
+            "experiments": [
+                {
+                    "name": "Disabled",
+                    "disable_features": [
+                        "PartitionAllocMemoryReclaimer"
+                    ]
+                }
+            ]
+        }
+    ],
     "IOSPasskeysM2": [
         {
             "platforms": [
@@ -17429,7 +17444,7 @@
                 {
                     "name": "Enabled",
                     "enable_features": [
-                        "NoSamePageFragmentPreloadingAnchorTracking"
+                        "PreloadingNoSamePageFragmentAnchorTracking"
                     ]
                 }
             ]
@@ -19712,6 +19727,25 @@
             ]
         }
     ],
+    "RestrictAbusePortsOnLocalhost": [
+        {
+            "platforms": [
+                "android",
+                "android_webview"
+            ],
+            "experiments": [
+                {
+                    "name": "RestrictAbusePortsOnLocalhost",
+                    "params": {
+                        "localhost_restrict_ports": "30987,30988,30989"
+                    },
+                    "enable_features": [
+                        "RestrictAbusePortsOnLocalhost"
+                    ]
+                }
+            ]
+        }
+    ],
     "RetryGetVideoCaptureDeviceInfos": [
         {
             "platforms": [
diff --git a/third_party/androidx/build.gradle b/third_party/androidx/build.gradle
index 9183abf..79f675ab 100644
--- a/third_party/androidx/build.gradle
+++ b/third_party/androidx/build.gradle
@@ -304,7 +304,7 @@
     google()
     maven {
         // This URL is generated by the fetch_all_androidx.py script.
-        url 'https://androidx.dev/snapshots/builds/13468622/artifacts/repository'
+        url 'https://androidx.dev/snapshots/builds/13470792/artifacts/repository'
     }
     mavenCentral()
 }
diff --git a/third_party/angle b/third_party/angle
index b729fb7..af4c3f9a 160000
--- a/third_party/angle
+++ b/third_party/angle
@@ -1 +1 @@
-Subproject commit b729fb74e68bb2b3db6c95067f4ffc1e0c25bc07
+Subproject commit af4c3f9add49b4477ab429e8e5492930bca15877
diff --git a/third_party/blink/public/common/safe_url_pattern.h b/third_party/blink/public/common/safe_url_pattern.h
index 186041ad..51622e03 100644
--- a/third_party/blink/public/common/safe_url_pattern.h
+++ b/third_party/blink/public/common/safe_url_pattern.h
@@ -8,7 +8,7 @@
 #include <vector>
 
 #include "third_party/blink/public/common/common_export.h"
-#include "third_party/liburlpattern/pattern.h"
+#include "third_party/liburlpattern/part.h"
 
 namespace blink {
 
diff --git a/third_party/blink/public/common/safe_url_pattern_mojom_traits.h b/third_party/blink/public/common/safe_url_pattern_mojom_traits.h
index 153fb71..d0565a5e 100644
--- a/third_party/blink/public/common/safe_url_pattern_mojom_traits.h
+++ b/third_party/blink/public/common/safe_url_pattern_mojom_traits.h
@@ -11,7 +11,7 @@
 #include "third_party/blink/public/common/common_export.h"
 #include "third_party/blink/public/common/safe_url_pattern.h"
 #include "third_party/blink/public/mojom/safe_url_pattern.mojom.h"
-#include "third_party/liburlpattern/pattern.h"
+#include "third_party/liburlpattern/part.h"
 
 namespace mojo {
 namespace internal {
diff --git a/third_party/blink/public/mojom/ai/ai_language_model.mojom b/third_party/blink/public/mojom/ai/ai_language_model.mojom
index 220053d..ad002cb0b 100644
--- a/third_party/blink/public/mojom/ai/ai_language_model.mojom
+++ b/third_party/blink/public/mojom/ai/ai_language_model.mojom
@@ -119,6 +119,25 @@
   OnResult(uint32 number_of_tokens);
 };
 
+// The client interface that receives the state update of the appended prompt.
+// The append operation is only considered finished when `OnAppendComplete()`
+// or `OnError()` is called. After that, there won't be any request sent
+// through this interface and the remote should close the connection.
+interface AILanguageModelAppendClient {
+  // Called when the append operation is completed, this will be called at
+  // most once.
+  OnAppendComplete();
+  // Called when error happens during the append.
+  OnError(ModelStreamingResponseStatus status);
+  // Called when the context overflowed when reserving the space for the prompt
+  // to be appended, so it does not indicate a failure or guarantee the
+  // success.
+  // The behavior is the same as the `OnQuotaOverflow()` from
+  // `ModelStreamingResponder`, no more `OnQuotaOverflow` will happen after
+  // `OnAppendComplete()` or `OnError()`.
+  OnQuotaOverflow();
+};
+
 // A session for prompting a model with inputs to obtain streaming responses.
 interface AILanguageModel {
   // Prompts the model with arbitrary content provided via the JavaScript API.
@@ -129,6 +148,14 @@
          on_device_model.mojom.ResponseConstraint? constraint,
          pending_remote<ModelStreamingResponder> pending_responder);
 
+  // Appends the prompts to the context, but they won't be processed yet until
+  // `Prompt()` is called. This method can be called multiple times before the
+  // `Prompt()`.
+  // TODO(crbug.com/409355678): return the response in an asynchronous callback
+  // instead of through the client (same for `Fork` and `MeasureInputUsage`).
+  Append(array<AILanguageModelPrompt> prompts,
+         pending_remote<AILanguageModelAppendClient> client);
+
   // Creates a new session with the same configuration and existing context
   // as the current session.
   // Note that this method is called by the `AILanguageModel.clone()` method
diff --git a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
index d2e465e..e082ae8 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom
@@ -4857,6 +4857,10 @@
   kEditContextTextFormatUpdateFireEvent = 5553,
   kEditContextTextFormatUpdateTextFormatThicknessOrStyleNotNone = 5554,
   kC2PAManifest = 5555,
+  kLanguageModel_Append = 5556,
+  kIntegrityPolicyInServiceWorkerResponse = 5557,
+  kEditContextTextFormatUnderlineStyle = 5558,
+  kEditContextTextFormatUnderlineThickness = 5559,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots. Also don't add extra
diff --git a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom
index ad952a3..ed656a14 100644
--- a/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom
+++ b/third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom
@@ -391,6 +391,7 @@
   kRequestclose = 333,
   kUint8arrayBase64Hex = 334,
   kLineBreak = 335,
+  kOverflowClip = 336,
 
   // Add new features immediately above this line. Don't change assigned
   // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/renderer/bindings/generated_in_modules.gni b/third_party/blink/renderer/bindings/generated_in_modules.gni
index 05a6b42c..c5089cb 100644
--- a/third_party/blink/renderer/bindings/generated_in_modules.gni
+++ b/third_party/blink/renderer/bindings/generated_in_modules.gni
@@ -692,6 +692,8 @@
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_detector_create_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_detector_detect_options.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_detector_detect_options.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_append_options.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_append_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_clone_options.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_clone_options.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_core_options.cc",
diff --git a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
index 4645e68..0b9b3dd 100644
--- a/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
+++ b/third_party/blink/renderer/core/animation/css/compositor_keyframe_value_factory.cc
@@ -78,7 +78,7 @@
       if (const auto* number_value = DynamicTo<CSSNumericLiteralValue>(value)) {
         if (number_value->IsNumber()) {
           return MakeGarbageCollected<CompositorKeyframeDouble>(
-              number_value->GetDoubleValue());
+              number_value->ClampedDoubleValue());
         }
       }
 
diff --git a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
index 59cd9a3f..ef16ba2 100644
--- a/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_border_image_length_box_interpolation_type.cc
@@ -327,7 +327,7 @@
           if (auto* side_numeric_value =
                   DynamicTo<CSSNumericLiteralValue>(side)) {
             return ConvertBorderImageNumberSide(
-                side_numeric_value->GetDoubleValue());
+                side_numeric_value->ClampedDoubleValue());
           }
           CHECK(side_primitive_value->IsMathFunctionValue());
           return InterpolationValue(
diff --git a/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
index 57fae90..57533fe4 100644
--- a/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_number_interpolation_type.cc
@@ -115,7 +115,7 @@
     const CSSValue& value) const {
   if (const auto* number_value = DynamicTo<CSSNumericLiteralValue>(value)) {
     if (number_value->IsNumber()) {
-      return CreateNumberValue(number_value->GetDoubleValue());
+      return CreateNumberValue(number_value->ClampedDoubleValue());
     }
   }
   return nullptr;
diff --git a/third_party/blink/renderer/core/animation/css_percentage_interpolation_type.cc b/third_party/blink/renderer/core/animation/css_percentage_interpolation_type.cc
index 3c769f0..ceab5a7e8 100644
--- a/third_party/blink/renderer/core/animation/css_percentage_interpolation_type.cc
+++ b/third_party/blink/renderer/core/animation/css_percentage_interpolation_type.cc
@@ -113,7 +113,7 @@
     const CSSValue& value) const {
   if (const auto* percentage_value = DynamicTo<CSSNumericLiteralValue>(value)) {
     if (percentage_value->IsPercentage()) {
-      return CreatePercentageValue(percentage_value->GetDoubleValue());
+      return CreatePercentageValue(percentage_value->ClampedDoubleValue());
     }
   }
   return nullptr;
diff --git a/third_party/blink/renderer/core/animation/effect_stack_test.cc b/third_party/blink/renderer/core/animation/effect_stack_test.cc
index af72301..c4bd2835 100644
--- a/third_party/blink/renderer/core/animation/effect_stack_test.cc
+++ b/third_party/blink/renderer/core/animation/effect_stack_test.cc
@@ -103,7 +103,7 @@
         To<InterpolableLength>(typed_value->GetInterpolableValue());
     return To<CSSNumericLiteralValue>(
                length.CreateCSSValue(Length::ValueRange::kAll))
-        ->GetDoubleValue();
+        ->ClampedDoubleValue();
   }
 
   double GetZIndexValue(const ActiveInterpolationsMap& active_interpolations) {
diff --git a/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc b/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
index 9a544b02..f9c5a88 100644
--- a/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
+++ b/third_party/blink/renderer/core/animation/keyframe_effect_model_test.cc
@@ -101,7 +101,7 @@
     EXPECT_NEAR(expected_value,
                 To<CSSNumericLiteralValue>(
                     length.CreateCSSValue(Length::ValueRange::kAll))
-                    ->GetDoubleValue(),
+                    ->ClampedDoubleValue(),
                 /*abs_error=*/0.02);
   }
 
diff --git a/third_party/blink/renderer/core/css/css_attr_type.cc b/third_party/blink/renderer/core/css/css_attr_type.cc
index aa0257c..525455c 100644
--- a/third_party/blink/renderer/core/css/css_attr_type.cc
+++ b/third_party/blink/renderer/core/css/css_attr_type.cc
@@ -89,7 +89,7 @@
     if (CSSNumericLiteralValue* literal =
             DynamicTo<CSSNumericLiteralValue>(number_value)) {
       return MakeGarbageCollected<CSSNumericLiteralValue>(
-          literal->GetDoubleValue(), *dimension_unit_);
+          literal->ClampedDoubleValue(), *dimension_unit_);
     }
     return nullptr;
   }
diff --git a/third_party/blink/renderer/core/css/css_basic_shape_values.cc b/third_party/blink/renderer/core/css/css_basic_shape_values.cc
index 45332ff..b8616227 100644
--- a/third_party/blink/renderer/core/css/css_basic_shape_values.cc
+++ b/third_party/blink/renderer/core/css/css_basic_shape_values.cc
@@ -659,10 +659,10 @@
   // The spec requires non-negative width and height but we can only validate
   // numeric literals here.
   if (width_->IsNumericLiteralValue()) {
-    DCHECK_GE(To<CSSNumericLiteralValue>(*width_).GetDoubleValue(), 0);
+    DCHECK_GE(To<CSSNumericLiteralValue>(*width_).ClampedDoubleValue(), 0);
   }
   if (height_->IsNumericLiteralValue()) {
-    DCHECK_GE(To<CSSNumericLiteralValue>(*height_).GetDoubleValue(), 0);
+    DCHECK_GE(To<CSSNumericLiteralValue>(*height_).ClampedDoubleValue(), 0);
   }
 }
 
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.cc b/third_party/blink/renderer/core/css/css_gradient_value.cc
index e941c14..2fa2e55b 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.cc
+++ b/third_party/blink/renderer/core/css/css_gradient_value.cc
@@ -134,7 +134,7 @@
 
 scoped_refptr<Image> CSSGradientValue::GetImage(
     const ImageResourceObserver& client,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const ContainerSizes& container_sizes,
     const gfx::SizeF& size) const {
@@ -152,6 +152,15 @@
     }
   }
 
+  const Document& document = node.GetDocument();
+  const Element* element = DynamicTo<Element>(node);
+  if (!element) {
+    element = document.documentElement();
+  }
+  if (!element) {
+    return nullptr;
+  }
+
   // We need to create an image.
   const ComputedStyle* root_style =
       document.documentElement()->GetComputedStyle();
@@ -162,7 +171,7 @@
       style, &style, root_style,
       CSSToLengthConversionData::ViewportSize(document.GetLayoutView()),
       container_sizes, CSSToLengthConversionData::AnchorData(),
-      style.EffectiveZoom(), ignored_flags, /*element=*/nullptr);
+      style.EffectiveZoom(), ignored_flags, element);
 
   scoped_refptr<Gradient> gradient;
   switch (GetClassType()) {
diff --git a/third_party/blink/renderer/core/css/css_gradient_value.h b/third_party/blink/renderer/core/css/css_gradient_value.h
index e08ba5f..60bd7fe1 100644
--- a/third_party/blink/renderer/core/css/css_gradient_value.h
+++ b/third_party/blink/renderer/core/css/css_gradient_value.h
@@ -99,7 +99,7 @@
   using ContainerSizes = CSSToLengthConversionData::ContainerSizes;
 
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle& style,
                                 const ContainerSizes&,
                                 const gfx::SizeF&) const;
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.cc b/third_party/blink/renderer/core/css/css_image_generator_value.cc
index e34fe3c..73fd072c 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.cc
@@ -143,26 +143,26 @@
 
 scoped_refptr<Image> CSSImageGeneratorValue::GetImage(
     const ImageResourceObserver& client,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const ContainerSizes& container_sizes,
     const gfx::SizeF& target_size) {
   switch (GetClassType()) {
     case kLinearGradientClass:
       return To<CSSLinearGradientValue>(this)->GetImage(
-          client, document, style, container_sizes, target_size);
+          client, node, style, container_sizes, target_size);
     case kPaintClass:
-      return To<CSSPaintValue>(this)->GetImage(client, document, style,
+      return To<CSSPaintValue>(this)->GetImage(client, node, style,
                                                target_size);
     case kRadialGradientClass:
       return To<CSSRadialGradientValue>(this)->GetImage(
-          client, document, style, container_sizes, target_size);
+          client, node, style, container_sizes, target_size);
     case kConicGradientClass:
       return To<CSSConicGradientValue>(this)->GetImage(
-          client, document, style, container_sizes, target_size);
+          client, node, style, container_sizes, target_size);
     case kConstantGradientClass:
       return To<CSSConstantGradientValue>(this)->GetImage(
-          client, document, style, container_sizes, target_size);
+          client, node, style, container_sizes, target_size);
     default:
       NOTREACHED();
   }
diff --git a/third_party/blink/renderer/core/css/css_image_generator_value.h b/third_party/blink/renderer/core/css/css_image_generator_value.h
index 23030e5..76544c1 100644
--- a/third_party/blink/renderer/core/css/css_image_generator_value.h
+++ b/third_party/blink/renderer/core/css/css_image_generator_value.h
@@ -45,6 +45,7 @@
 class Image;
 class ComputedStyle;
 class ImageResourceObserver;
+class Node;
 
 // These maps do not contain many objects because we do not expect any
 // particular CSSGeneratedImageValue to have clients at many different
@@ -97,7 +98,7 @@
   // The |target_size| is the desired image size. Background images should not
   // be snapped. In other case the target size must be pixel snapped already.
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const ContainerSizes&,
                                 const gfx::SizeF& target_size);
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
index cb4b789..5fc264f7 100644
--- a/third_party/blink/renderer/core/css/css_image_value.cc
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
@@ -103,10 +103,10 @@
     ImageResourceContent* image_content =
         document.GetStyleEngine().CacheImageContent(params);
     cached_image_ = MakeGarbageCollected<StyleFetchedImage>(
-        image_content, document,
+        image_content, *url_data.MakeResolvedIfDanglingMarkup(document),
+        document,
         params.GetImageRequestBehavior() ==
             FetchParameters::ImageRequestBehavior::kDeferImageLoad,
-        url_data.IsFromOriginCleanStyleSheet(), url_data.IsAdRelated(),
         params.Url(), override_image_resolution);
   }
   return cached_image_.Get();
diff --git a/third_party/blink/renderer/core/css/css_math_expression_node.cc b/third_party/blink/renderer/core/css/css_math_expression_node.cc
index a4290e34..ff36c59 100644
--- a/third_party/blink/renderer/core/css/css_math_expression_node.cc
+++ b/third_party/blink/renderer/core/css/css_math_expression_node.cc
@@ -833,7 +833,7 @@
 
 double CSSMathExpressionNumericLiteral::DoubleValue() const {
   if (HasDoubleValue(ResolvedUnitType())) {
-    return value_->GetDoubleValueWithoutClamping();
+    return value_->DoubleValue();
   }
   DUMP_WILL_BE_NOTREACHED();
   return 0;
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.cc b/third_party/blink/renderer/core/css/css_math_function_value.cc
index 70019c2..88a36e1 100644
--- a/third_party/blink/renderer/core/css/css_math_function_value.cc
+++ b/third_party/blink/renderer/core/css/css_math_function_value.cc
@@ -60,16 +60,6 @@
   return IsRelativeUnit(resolved_type) || resolved_type == UnitType::kUnknown;
 }
 
-double CSSMathFunctionValue::DoubleValue() const {
-#if DCHECK_IS_ON()
-  if (IsPercentage()) {
-    DCHECK(!AllowsNegativePercentageReference() ||
-           !expression_->InvolvesPercentageComparisons());
-  }
-#endif
-  return ClampToPermittedRange(expression_->DoubleValue());
-}
-
 double CSSMathFunctionValue::ComputeDegrees(
     const CSSLengthResolver& length_resolver) const {
   DCHECK_EQ(kCalcAngle, expression_->Category());
diff --git a/third_party/blink/renderer/core/css/css_math_function_value.h b/third_party/blink/renderer/core/css/css_math_function_value.h
index 8c9c9575..603e740f 100644
--- a/third_party/blink/renderer/core/css/css_math_function_value.h
+++ b/third_party/blink/renderer/core/css/css_math_function_value.h
@@ -69,13 +69,6 @@
   bool IsComputationallyIndependent() const;
   bool IsElementDependent() const;
 
-  // TODO(crbug.com/979895): The semantics of this function is still not very
-  // clear. Do not add new callers before further refactoring and cleanups.
-  // |DoubleValue()| can be called only when the math expression can be
-  // resolved into a single numeric value *without any type conversion* (e.g.,
-  // between px and em). Otherwise, it hits a DCHECK.
-  double DoubleValue() const;
-
   double ComputeSeconds(const CSSLengthResolver&) const;
   double ComputeDegrees(const CSSLengthResolver&) const;
   double ComputeLengthPx(const CSSLengthResolver&) const;
diff --git a/third_party/blink/renderer/core/css/css_paint_value.cc b/third_party/blink/renderer/core/css/css_paint_value.cc
index 8cf1dd6..5a3318f 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value.cc
@@ -103,7 +103,7 @@
 
 scoped_refptr<Image> CSSPaintValue::GetImage(
     const ImageResourceObserver& client,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) {
   // https://crbug.com/835589: early exit when paint target is associated with
@@ -112,6 +112,7 @@
     return nullptr;
   }
 
+  const Document& document = node.GetDocument();
   CSSPaintImageGenerator& generator = EnsureGenerator(document);
 
   // If the generator isn't ready yet, we have nothing to paint. Our
diff --git a/third_party/blink/renderer/core/css/css_paint_value.h b/third_party/blink/renderer/core/css/css_paint_value.h
index 4caf2e5..6109e8a8 100644
--- a/third_party/blink/renderer/core/css/css_paint_value.h
+++ b/third_party/blink/renderer/core/css/css_paint_value.h
@@ -33,7 +33,7 @@
   // The |target_size| is container size with subpixel snapping when used
   // in the context of paint images.
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size);
 
diff --git a/third_party/blink/renderer/core/css/css_paint_value_test.cc b/third_party/blink/renderer/core/css/css_paint_value_test.cc
index 93eb45316..ec80602 100644
--- a/third_party/blink/renderer/core/css/css_paint_value_test.cc
+++ b/third_party/blink/renderer/core/css/css_paint_value_test.cc
@@ -99,7 +99,7 @@
   // should happen).
   EXPECT_CALL(*mock_generator, Paint(_, _, _)).Times(0);
   EXPECT_FALSE(
-      paint_value->GetImage(*target, GetDocument(), style, target_size));
+      paint_value->GetImage(*target, *target->GetNode(), style, target_size));
 
   // Now mark the generator as ready - GetImage should then succeed.
   ON_CALL(*mock_generator, IsImageGeneratorReady()).WillByDefault(Return(true));
@@ -112,7 +112,7 @@
   }
 
   EXPECT_TRUE(
-      paint_value->GetImage(*target, GetDocument(), style, target_size));
+      paint_value->GetImage(*target, *target->GetNode(), style, target_size));
 }
 
 // Regression test for crbug.com/998439. The problem is that GetImage is called
@@ -130,7 +130,7 @@
   CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident, true);
 
   EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 0u);
-  paint_value->GetImage(*target, GetDocument(), style, target_size);
+  paint_value->GetImage(*target, *target->GetNode(), style, target_size);
   // A new generator should be created if there is no generator exists.
   EXPECT_EQ(paint_value->NumberOfGeneratorsForTesting(), 1u);
 
@@ -200,18 +200,18 @@
           Return(PaintGeneratedImage::Create(PaintRecord(), target_size)));
 
   ASSERT_TRUE(
-      paint_value->GetImage(*target, GetDocument(), style, target_size));
+      paint_value->GetImage(*target, *target->GetNode(), style, target_size));
 
   // Start printing; our paint should run on the main thread (and thus call
   // Paint).
   GetDocument().SetPrinting(Document::kPrinting);
   ASSERT_TRUE(
-      paint_value->GetImage(*target, GetDocument(), style, target_size));
+      paint_value->GetImage(*target, *target->GetNode(), style, target_size));
 
   // Stop printing; we should return to the compositor.
   GetDocument().SetPrinting(Document::kNotPrinting);
   ASSERT_TRUE(
-      paint_value->GetImage(*target, GetDocument(), style, target_size));
+      paint_value->GetImage(*target, *target->GetNode(), style, target_size));
 }
 
 // Regression test for https://crbug.com/835589.
@@ -233,7 +233,7 @@
   auto* ident =
       MakeGarbageCollected<CSSCustomIdentValue>(AtomicString("linkpainter"));
   CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident, true);
-  EXPECT_FALSE(paint_value->GetImage(*target, GetDocument(), style,
+  EXPECT_FALSE(paint_value->GetImage(*target, *target->GetNode(), style,
                                      gfx::SizeF(100, 100)));
 }
 
@@ -262,7 +262,7 @@
   auto* ident =
       MakeGarbageCollected<CSSCustomIdentValue>(AtomicString("linkpainter"));
   CSSPaintValue* paint_value = MakeGarbageCollected<CSSPaintValue>(ident, true);
-  EXPECT_FALSE(paint_value->GetImage(*target, GetDocument(), style,
+  EXPECT_FALSE(paint_value->GetImage(*target, *target->GetNode(), style,
                                      gfx::SizeF(100, 100)));
 }
 
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.cc b/third_party/blink/renderer/core/css/css_primitive_value.cc
index 24cd7b48..6377eb9 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value.cc
+++ b/third_party/blink/renderer/core/css/css_primitive_value.cc
@@ -557,15 +557,6 @@
   return To<CSSMathFunctionValue>(this)->ConvertToLength(length_resolver);
 }
 
-double CSSPrimitiveValue::GetDoubleValue() const {
-  return CSSValueClampingUtils::ClampDouble(GetDoubleValueWithoutClamping());
-}
-
-double CSSPrimitiveValue::GetDoubleValueWithoutClamping() const {
-  return IsCalculated() ? To<CSSMathFunctionValue>(this)->DoubleValue()
-                        : To<CSSNumericLiteralValue>(this)->DoubleValue();
-}
-
 CSSPrimitiveValue::UnitType CSSPrimitiveValue::CanonicalUnitTypeForCategory(
     UnitCategory category) {
   // The canonical unit type is chosen according to the way
diff --git a/third_party/blink/renderer/core/css/css_primitive_value.h b/third_party/blink/renderer/core/css/css_primitive_value.h
index d8473a6..dae4dab0 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value.h
+++ b/third_party/blink/renderer/core/css/css_primitive_value.h
@@ -426,19 +426,6 @@
   // https://www.w3.org/TR/filter-effects-1/#interpolation-of-filter-functions.
   CSSPrimitiveValue* ConvertLiteralsFromPercentageToNumber() const;
 
-  // TODO(crbug.com/979895): The semantics of these untyped getters are not very
-  // clear if |this| is a math function. Do not add new callers before further
-  // refactoring and cleanups.
-  // These getters can be called only when |this| is a numeric literal or a math
-  // expression can be resolved into a single numeric value *without any type
-  // conversion* (e.g., between px and em). Otherwise, it hits a DCHECK.
-  // In particular, you cannot call this if IsResolvableBeforeLayout()
-  // returns false.
-  double GetDoubleValue() const;
-
-  // Returns Double Value including infinity, -infinity, and NaN.
-  double GetDoubleValueWithoutClamping() const;
-
   template <typename T>
     requires std::integral<T> || std::floating_point<T>
   inline T ConvertTo(const CSSLengthResolver& length_resolver) const {
diff --git a/third_party/blink/renderer/core/css/css_primitive_value_test.cc b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
index fe36833..fba68b6 100644
--- a/third_party/blink/renderer/core/css/css_primitive_value_test.cc
+++ b/third_party/blink/renderer/core/css/css_primitive_value_test.cc
@@ -197,44 +197,42 @@
 }
 
 TEST_F(CSSPrimitiveValueTest, GetDoubleValueWithoutClampingAllowNaN) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({std::numeric_limits<double>::quiet_NaN(), UnitType::kPixels});
-  EXPECT_TRUE(std::isnan(value->GetDoubleValueWithoutClamping()));
+  EXPECT_TRUE(std::isnan(value->DoubleValue()));
 }
 
 TEST_F(CSSPrimitiveValueTest,
        GetDoubleValueWithoutClampingAllowPositveInfinity) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({std::numeric_limits<double>::infinity(), UnitType::kPixels});
-  EXPECT_TRUE(std::isinf(value->GetDoubleValueWithoutClamping()) &&
-              value->GetDoubleValueWithoutClamping() > 0);
+  EXPECT_TRUE(std::isinf(value->DoubleValue()) && value->DoubleValue() > 0);
 }
 
 TEST_F(CSSPrimitiveValueTest,
        GetDoubleValueWithoutClampingAllowNegativeInfinity) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({-std::numeric_limits<double>::infinity(), UnitType::kPixels});
 
-  EXPECT_TRUE(std::isinf(value->GetDoubleValueWithoutClamping()) &&
-              value->GetDoubleValueWithoutClamping() < 0);
+  EXPECT_TRUE(std::isinf(value->DoubleValue()) && value->DoubleValue() < 0);
 }
 
 TEST_F(CSSPrimitiveValueTest, GetDoubleValueClampNaN) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({std::numeric_limits<double>::quiet_NaN(), UnitType::kPixels});
-  EXPECT_EQ(0.0, value->GetDoubleValue());
+  EXPECT_EQ(0.0, value->ClampedDoubleValue());
 }
 
 TEST_F(CSSPrimitiveValueTest, GetDoubleValueClampPositiveInfinity) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({std::numeric_limits<double>::infinity(), UnitType::kPixels});
-  EXPECT_EQ(std::numeric_limits<double>::max(), value->GetDoubleValue());
+  EXPECT_EQ(std::numeric_limits<double>::max(), value->ClampedDoubleValue());
 }
 
 TEST_F(CSSPrimitiveValueTest, GetDoubleValueClampNegativeInfinity) {
-  CSSPrimitiveValue* value =
+  CSSNumericLiteralValue* value =
       Create({-std::numeric_limits<double>::infinity(), UnitType::kPixels});
-  EXPECT_EQ(std::numeric_limits<double>::lowest(), value->GetDoubleValue());
+  EXPECT_EQ(std::numeric_limits<double>::lowest(), value->ClampedDoubleValue());
 }
 
 TEST_F(CSSPrimitiveValueTest, TestCanonicalizingNumberUnitCategory) {
diff --git a/third_party/blink/renderer/core/css/css_unresolved_color_value.cc b/third_party/blink/renderer/core/css/css_unresolved_color_value.cc
index 72d3410..9e22607 100644
--- a/third_party/blink/renderer/core/css/css_unresolved_color_value.cc
+++ b/third_party/blink/renderer/core/css/css_unresolved_color_value.cc
@@ -28,7 +28,7 @@
                           StringBuilder& result) {
   if (value) {
     if (const auto* literal = DynamicTo<CSSNumericLiteralValue>(value)) {
-      double val = literal->GetDoubleValue();
+      double val = literal->ClampedDoubleValue();
       if (value->IsPercentage()) {
         val /= 100.0;
       }
@@ -41,7 +41,8 @@
       const CSSMathFunctionValue* calc = DynamicTo<CSSMathFunctionValue>(value);
       if (calc && calc->ExpressionNode()->IsNumericLiteral() &&
           color_space == Color::ColorSpace::kSRGBLegacy) {
-        result.AppendNumber(ClampChannel(calc->GetDoubleValue()));
+        result.AppendNumber(
+            ClampChannel(calc->ExpressionNode()->DoubleValue()));
       } else {
         result.Append(value->CssText());
       }
@@ -85,14 +86,14 @@
     std::optional<double> alpha;
     if (const auto* literal_alpha =
             DynamicTo<CSSNumericLiteralValue>(*alpha_)) {
-      alpha = literal_alpha->GetDoubleValue();
+      alpha = literal_alpha->ClampedDoubleValue();
     } else {
       // See corresponding code in AppendChannel().
       const CSSMathFunctionValue* calc =
           DynamicTo<CSSMathFunctionValue>(alpha_.Get());
       if (calc && calc->ExpressionNode()->IsNumericLiteral() &&
           color_space_ == Color::ColorSpace::kSRGBLegacy) {
-        alpha = alpha_->GetDoubleValue();
+        alpha = calc->ExpressionNode()->DoubleValue();
       }
     }
     if (alpha.has_value() && alpha_->IsPercentage()) {
diff --git a/third_party/blink/renderer/core/css/css_uri_value_test.cc b/third_party/blink/renderer/core/css/css_uri_value_test.cc
index b3efe7f4..563c072 100644
--- a/third_party/blink/renderer/core/css/css_uri_value_test.cc
+++ b/third_party/blink/renderer/core/css/css_uri_value_test.cc
@@ -16,7 +16,7 @@
   cssvalue::CSSURIValue* rel = MakeGarbageCollected<cssvalue::CSSURIValue>(
       *MakeGarbageCollected<CSSUrlData>(
           AtomicString("a"), KURL("http://foo.com/a"), Referrer(),
-          OriginClean::kTrue, /*is_ad_related=*/false));
+          /*origin_clean=*/true, /*is_ad_related=*/false));
   cssvalue::CSSURIValue* abs =
       rel->ComputedCSSValue(KURL("http://bar.com"), WTF::TextEncoding());
   EXPECT_EQ("url(\"http://bar.com/a\")", abs->CssText());
@@ -26,7 +26,7 @@
   cssvalue::CSSURIValue* rel = MakeGarbageCollected<cssvalue::CSSURIValue>(
       *MakeGarbageCollected<CSSUrlData>(
           AtomicString("http://baz.com/a"), KURL("http://baz.com/a"),
-          Referrer(), OriginClean::kTrue, /*is_ad_related=*/false));
+          Referrer(), /*origin_clean=*/true, /*is_ad_related=*/false));
   cssvalue::CSSURIValue* abs =
       rel->ComputedCSSValue(KURL("http://bar.com"), WTF::TextEncoding());
   EXPECT_EQ("url(\"http://baz.com/a\")", abs->CssText());
@@ -36,7 +36,7 @@
   cssvalue::CSSURIValue* rel = MakeGarbageCollected<cssvalue::CSSURIValue>(
       *MakeGarbageCollected<CSSUrlData>(
           AtomicString("#a"), KURL("http://baz.com/a"), Referrer(),
-          OriginClean::kTrue, /*is_ad_related=*/false));
+          /*origin_clean=*/true, /*is_ad_related=*/false));
   cssvalue::CSSURIValue* abs =
       rel->ComputedCSSValue(KURL("http://bar.com"), WTF::TextEncoding());
   EXPECT_EQ("url(\"#a\")", abs->CssText());
@@ -45,7 +45,7 @@
 TEST(CSSURIValueTest, EmptyComputedCSSValue) {
   cssvalue::CSSURIValue* rel = MakeGarbageCollected<cssvalue::CSSURIValue>(
       *MakeGarbageCollected<CSSUrlData>(g_empty_atom, KURL(), Referrer(),
-                                        OriginClean::kTrue,
+                                        /*origin_clean=*/true,
                                         /*is_ad_related=*/false));
   cssvalue::CSSURIValue* abs =
       rel->ComputedCSSValue(KURL("http://bar.com"), WTF::TextEncoding());
diff --git a/third_party/blink/renderer/core/css/css_url_data.cc b/third_party/blink/renderer/core/css/css_url_data.cc
index ad3ae90e..289521d 100644
--- a/third_party/blink/renderer/core/css/css_url_data.cc
+++ b/third_party/blink/renderer/core/css/css_url_data.cc
@@ -30,21 +30,37 @@
 CSSUrlData::CSSUrlData(const AtomicString& unresolved_url,
                        const KURL& resolved_url,
                        const Referrer& referrer,
-                       OriginClean origin_clean,
+                       bool is_from_origin_clean_style_sheet,
                        bool is_ad_related)
     : relative_url_(unresolved_url),
       absolute_url_(resolved_url.GetString()),
       referrer_(referrer),
-      is_from_origin_clean_style_sheet_(origin_clean == OriginClean::kTrue),
+      is_from_origin_clean_style_sheet_(is_from_origin_clean_style_sheet),
       is_ad_related_(is_ad_related),
       is_local_(unresolved_url.StartsWith('#')),
       potentially_dangling_markup_(resolved_url.PotentiallyDanglingMarkup()) {}
 
+CSSUrlData::CSSUrlData(base::PassKey<CSSUrlData>,
+                       const AtomicString& unresolved_url,
+                       const AtomicString& resolved_url,
+                       const Referrer& referrer,
+                       bool is_from_origin_clean_style_sheet,
+                       bool is_ad_related,
+                       bool is_local,
+                       bool potentially_dangling_markup)
+    : relative_url_(unresolved_url),
+      absolute_url_(resolved_url),
+      referrer_(referrer),
+      is_from_origin_clean_style_sheet_(is_from_origin_clean_style_sheet),
+      is_ad_related_(is_ad_related),
+      is_local_(is_local),
+      potentially_dangling_markup_(potentially_dangling_markup) {}
+
 CSSUrlData::CSSUrlData(const AtomicString& resolved_url)
     : CSSUrlData(resolved_url,
                  KURL(resolved_url),
                  Referrer(),
-                 OriginClean::kTrue,
+                 /*is_from_origin_clean_style_sheet=*/true,
                  /*is_ad_related=*/false) {}
 
 KURL CSSUrlData::ResolveUrl(const Document& document) const {
@@ -86,9 +102,10 @@
   if (relative_url_.empty()) {
     return this;
   }
-  return MakeGarbageCollected<CSSUrlData>(absolute_url_, KURL(absolute_url_),
-                                          Referrer(), GetOriginClean(),
-                                          is_ad_related_);
+  return MakeGarbageCollected<CSSUrlData>(
+      base::PassKey<CSSUrlData>(), absolute_url_, absolute_url_, Referrer(),
+      is_from_origin_clean_style_sheet_, is_ad_related_, is_local_,
+      potentially_dangling_markup_);
 }
 
 const CSSUrlData* CSSUrlData::MakeResolved(
@@ -101,19 +118,29 @@
                                 ? KURL(base_url, relative_url_, charset)
                                 : KURL(base_url, relative_url_);
   if (is_local_) {
-    return MakeGarbageCollected<CSSUrlData>(relative_url_, resolved_url,
-                                            Referrer(), GetOriginClean(),
-                                            is_ad_related_);
+    return MakeGarbageCollected<CSSUrlData>(
+        relative_url_, resolved_url, Referrer(),
+        is_from_origin_clean_style_sheet_, is_ad_related_);
   }
   return MakeGarbageCollected<CSSUrlData>(
       AtomicString(resolved_url.GetString()), resolved_url, Referrer(),
-      GetOriginClean(), is_ad_related_);
+      is_from_origin_clean_style_sheet_, is_ad_related_);
+}
+
+const CSSUrlData* CSSUrlData::MakeResolvedIfDanglingMarkup(
+    const Document& document) const {
+  if (!potentially_dangling_markup_) {
+    return this;
+  }
+  return MakeGarbageCollected<CSSUrlData>(
+      relative_url_, ResolveUrl(document), referrer_,
+      is_from_origin_clean_style_sheet_, is_ad_related_);
 }
 
 const CSSUrlData* CSSUrlData::MakeWithoutReferrer() const {
-  return MakeGarbageCollected<CSSUrlData>(relative_url_, KURL(absolute_url_),
-                                          Referrer(), GetOriginClean(),
-                                          is_ad_related_);
+  return MakeGarbageCollected<CSSUrlData>(
+      relative_url_, KURL(absolute_url_), Referrer(),
+      is_from_origin_clean_style_sheet_, is_ad_related_);
 }
 
 bool CSSUrlData::IsLocal(const Document& document) const {
diff --git a/third_party/blink/renderer/core/css/css_url_data.h b/third_party/blink/renderer/core/css/css_url_data.h
index 1169bbf..8867cde 100644
--- a/third_party/blink/renderer/core/css/css_url_data.h
+++ b/third_party/blink/renderer/core/css/css_url_data.h
@@ -21,8 +21,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_URL_DATA_H_
 #define THIRD_PARTY_BLINK_RENDERER_CORE_CSS_CSS_URL_DATA_H_
 
+#include "base/types/pass_key.h"
 #include "third_party/blink/renderer/core/core_export.h"
-#include "third_party/blink/renderer/core/css/css_origin_clean.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/weborigin/referrer.h"
 #include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -42,8 +42,16 @@
   CSSUrlData(const AtomicString& unresolved_url,
              const KURL& resolved_url,
              const Referrer&,
-             OriginClean,
+             bool is_from_origin_clean_style_sheet,
              bool is_ad_related);
+  CSSUrlData(base::PassKey<CSSUrlData>,
+             const AtomicString& unresolved_url,
+             const AtomicString& resolved_url,
+             const Referrer&,
+             bool is_from_origin_clean_style_sheet,
+             bool is_ad_related,
+             bool is_local,
+             bool potentially_dangling_markup);
 
   // Create URL data with a resolved (absolute) URL. Generally used for
   // computed values - the above should otherwise be preferred.
@@ -65,6 +73,11 @@
   const CSSUrlData* MakeResolved(const KURL& base_url,
                                  const WTF::TextEncoding& charset) const;
 
+  // Returns a copy with the URL (re)resolved against the base URL of the
+  // document if there's is potential risk of "dangling markup". Otherwise
+  // returns itself.
+  const CSSUrlData* MakeResolvedIfDanglingMarkup(const Document&) const;
+
   // Returns a copy where the referrer has been reset.
   const CSSUrlData* MakeWithoutReferrer() const;
 
@@ -80,10 +93,6 @@
   bool IsFromOriginCleanStyleSheet() const {
     return is_from_origin_clean_style_sheet_;
   }
-  OriginClean GetOriginClean() const {
-    return is_from_origin_clean_style_sheet_ ? OriginClean::kTrue
-                                             : OriginClean::kFalse;
-  }
   bool IsAdRelated() const { return is_ad_related_; }
 
   // Returns true if this URL is "local" to the specified Document (either by
diff --git a/third_party/blink/renderer/core/css/cssom/css_unit_value.cc b/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
index e6a1c74..c360193 100644
--- a/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
+++ b/third_party/blink/renderer/core/css/cssom/css_unit_value.cc
@@ -115,7 +115,7 @@
   if (!IsValidUnit(unit)) {
     return nullptr;
   }
-  return MakeGarbageCollected<CSSUnitValue>(value.GetDoubleValue(), unit);
+  return MakeGarbageCollected<CSSUnitValue>(value.ClampedDoubleValue(), unit);
 }
 
 String CSSUnitValue::unit() const {
diff --git a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
index d755731..fc4251eb 100644
--- a/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
+++ b/third_party/blink/renderer/core/css/parser/at_rule_descriptor_parser.cc
@@ -334,6 +334,8 @@
     const CSSParserContext& context) {
   CSSValue* parsed_value = nullptr;
   stream.ConsumeWhitespace();
+  CSSParserContext::ParserModeOverridingScope scope(context,
+                                                    kCSSFontFaceRuleMode);
   switch (id) {
     case AtRuleDescriptorID::FontFamily:
       // In order to avoid confusion, <family-name> does not accept unquoted
@@ -359,14 +361,10 @@
       parsed_value = ConsumeFontDisplay(stream);
       break;
     case AtRuleDescriptorID::FontStretch: {
-      CSSParserContext::ParserModeOverridingScope scope(context,
-                                                        kCSSFontFaceRuleMode);
       parsed_value = css_parsing_utils::ConsumeFontStretch(stream, context);
       break;
     }
     case AtRuleDescriptorID::FontStyle: {
-      CSSParserContext::ParserModeOverridingScope scope(context,
-                                                        kCSSFontFaceRuleMode);
       parsed_value = css_parsing_utils::ConsumeFontStyle(stream, context);
       break;
     }
@@ -374,8 +372,6 @@
       parsed_value = ConsumeFontVariantList(stream);
       break;
     case AtRuleDescriptorID::FontWeight: {
-      CSSParserContext::ParserModeOverridingScope scope(context,
-                                                        kCSSFontFaceRuleMode);
       parsed_value = css_parsing_utils::ConsumeFontWeight(stream, context);
       break;
     }
diff --git a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
index 1d2acbd3..b2cfcbb 100644
--- a/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
+++ b/third_party/blink/renderer/core/css/parser/css_parser_impl.cc
@@ -3080,7 +3080,7 @@
                                .ConvertTo<TimelineOffset::NamedRange>();
         double percent =
             To<CSSNumericLiteralValue>(stream_name_percent->Item(1))
-                .GetDoubleValue();
+                .ClampedDoubleValue();
         result->push_back(KeyframeOffset(stream_name, percent / 100.0));
       }
     } else {
diff --git a/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc b/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc
index 3e27db91..5715427 100644
--- a/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc
+++ b/third_party/blink/renderer/core/css/properties/css_color_function_parser.cc
@@ -471,10 +471,10 @@
       if (value->IsAngle()) {
         return value->ComputeDegrees();
       } else {
-        return value->GetDoubleValueWithoutClamping();
+        return value->DoubleValue();
       }
     case ChannelType::kPercentage:
-      return (value->GetDoubleValue() / 100.0) * percentage_base;
+      return (value->ClampedDoubleValue() / 100.0) * percentage_base;
     default:
       NOTREACHED();
   }
@@ -486,9 +486,9 @@
   using ChannelType = ColorFunctionParser::ChannelType;
   switch (channel_type) {
     case ChannelType::kNumber:
-      return ClampTo<double>(value->GetDoubleValue(), 0.0, 1.0);
+      return ClampTo<double>(value->ClampedDoubleValue(), 0.0, 1.0);
     case ChannelType::kPercentage:
-      return ClampTo<double>(value->GetDoubleValue() / 100.0, 0.0, 1.0);
+      return ClampTo<double>(value->ClampedDoubleValue() / 100.0, 0.0, 1.0);
     default:
       NOTREACHED();
   }
@@ -539,11 +539,9 @@
   auto* literal_value = GetNumericLiteralValue(value);
   switch (To<CSSMathFunctionValue>(value)->Category()) {
     case kCalcNumber:
-      return literal_value->DoubleValue();
+      return literal_value->ClampedDoubleValue();
     case kCalcPercent:
-      return (CSSValueClampingUtils::ClampDouble(literal_value->DoubleValue()) /
-              100) *
-             percentage_base;
+      return literal_value->ClampedDoubleValue() / 100 * percentage_base;
     case kCalcAngle:
       return literal_value->ComputeDegrees();
     default:
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
index a12c93d5..c1521e3 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils.cc
@@ -802,7 +802,7 @@
             filter_type != CSSValueID::kContrast) {
           bool is_percentage = literal_value->IsPercentage();
           double max_allowed = is_percentage ? 100.0 : 1.0;
-          if (literal_value->GetDoubleValue() > max_allowed) {
+          if (literal_value->ClampedDoubleValue() > max_allowed) {
             parsed_value = CSSNumericLiteralValue::Create(
                 max_allowed, is_percentage
                                  ? CSSPrimitiveValue::UnitType::kPercentage
@@ -1670,9 +1670,7 @@
   AtomicString url_string = url.ToAtomicString();
   return MakeGarbageCollected<CSSUrlData>(
       url_string, context.CompleteNonEmptyURL(url_string),
-      context.GetReferrer(),
-      context.IsOriginClean() ? OriginClean::kTrue : OriginClean::kFalse,
-      context.IsAdRelated());
+      context.GetReferrer(), context.IsOriginClean(), context.IsAdRelated());
 }
 
 }  // namespace
@@ -3168,7 +3166,7 @@
   if (const auto* percentage_literal =
           DynamicTo<CSSNumericLiteralValue>(percentage)) {
     percentage = CSSNumericLiteralValue::Create(
-        ClampTo<double>(percentage_literal->GetDoubleValue(), 0, 1),
+        ClampTo<double>(percentage_literal->ClampedDoubleValue(), 0, 1),
         CSSPrimitiveValue::UnitType::kNumber);
   }
 
@@ -3195,7 +3193,7 @@
       }
       if (const auto* literal =
               DynamicTo<CSSNumericLiteralValue>(percent_value)) {
-        double val = literal->GetDoubleValue();
+        double val = literal->ClampedDoubleValue();
         if (!(val >= 0.0 &&
               val <= 100.0)) {  // Includes checks for NaN and infinities.
           return nullptr;
@@ -3715,6 +3713,8 @@
     case CSSPropertyID::kOverflowY:
       if (value_id == CSSValueID::kOverlay) {
         context.Count(WebFeature::kCSSValueOverflowOverlay);
+      } else if (value_id == CSSValueID::kClip) {
+        context.Count(WebDXFeature::kOverflowClip);
       }
       break;
     case CSSPropertyID::kWritingMode:
diff --git a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
index 615c062..1434604a 100644
--- a/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
+++ b/third_party/blink/renderer/core/css/properties/css_parsing_utils_test.cc
@@ -47,6 +47,19 @@
   EXPECT_TRUE(document.IsUseCounted(feature));
 }
 
+TEST(CSSParsingUtilsTest, OverflowClipUseCount) {
+  test::TaskEnvironment task_environment;
+  auto dummy_page_holder =
+      std::make_unique<DummyPageHolder>(gfx::Size(800, 600));
+  Page::InsertOrdinaryPageForTesting(&dummy_page_holder->GetPage());
+  Document& document = dummy_page_holder->GetDocument();
+  WebDXFeature feature = WebDXFeature::kOverflowClip;
+  EXPECT_FALSE(document.IsWebDXFeatureCounted(feature));
+  document.documentElement()->setInnerHTML(
+      "<style>span { overflow: clip; }</style>");
+  EXPECT_TRUE(document.IsWebDXFeatureCounted(feature));
+}
+
 TEST(CSSParsingUtilsTest, Revert) {
   EXPECT_TRUE(css_parsing_utils::IsCSSWideKeyword(CSSValueID::kRevert));
   EXPECT_TRUE(css_parsing_utils::IsCSSWideKeyword("revert"));
diff --git a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
index f8da078d..07afdc7 100644
--- a/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
+++ b/third_party/blink/renderer/core/css/properties/shorthands/shorthands_custom.cc
@@ -1381,7 +1381,7 @@
           flex_shrink = num;
           savepoint.Release();
         } else if (!flex_basis && num->IsNumericLiteralValue() &&
-                   To<CSSNumericLiteralValue>(num)->GetDoubleValue() == 0) {
+                   To<CSSNumericLiteralValue>(num)->ClampedDoubleValue() == 0) {
           // Unitless zero is a valid <'flex-basis'>. All other <length>s
           // must have some unit, and are handled by the other branch.
           flex_basis = CSSNumericLiteralValue::Create(
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
index f8428c1..ef374ae 100644
--- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
+++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.cc
@@ -327,13 +327,6 @@
   return MapAnimationTimingDelay(state.CssToLengthConversionData(), value);
 }
 
-Timing::Delay CSSToStyleMap::MapAnimationDelayEnd(const CSSValue& value) {
-  // Note: using default length resolver here, as this function is only
-  // called from the serialization code.
-  return MapAnimationTimingDelay(CSSToLengthConversionData(/*element=*/nullptr),
-                                 value);
-}
-
 Timing::Delay CSSToStyleMap::MapAnimationDelayEnd(StyleResolverState& state,
                                                   const CSSValue& value) {
   return MapAnimationTimingDelay(state.CssToLengthConversionData(), value);
diff --git a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h
index 94ba2d0d..8439b54 100644
--- a/third_party/blink/renderer/core/css/resolver/css_to_style_map.h
+++ b/third_party/blink/renderer/core/css/resolver/css_to_style_map.h
@@ -69,7 +69,6 @@
 
   static Timing::Delay MapAnimationDelayStart(StyleResolverState&,
                                               const CSSValue&);
-  static Timing::Delay MapAnimationDelayEnd(const CSSValue&);
   static Timing::Delay MapAnimationDelayEnd(StyleResolverState&,
                                             const CSSValue&);
   static Timing::PlaybackDirection MapAnimationDirection(StyleResolverState&,
diff --git a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
index 28a10cb..bbb80ad 100644
--- a/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
+++ b/third_party/blink/renderer/core/css/resolver/style_adjuster.cc
@@ -696,7 +696,7 @@
 // g-issues.chromium.org/issues/349835587
 // https://github.com/WICG/canvas-place-element
 static bool IsCanvasPlaceOrDrawElement(const Element* element) {
-  if (RuntimeEnabledFeatures::CanvasElementDrawImageEnabled() && element &&
+  if (RuntimeEnabledFeatures::CanvasElementDrawElementEnabled() && element &&
       element->IsInCanvasSubtree()) {
     // Placed elements are always immediate children of the canvas.
     if (const auto* canvas =
@@ -709,7 +709,7 @@
 }
 
 static bool IsCanvasWithPlaceOrDrawElements(const Element* element) {
-  if (!RuntimeEnabledFeatures::CanvasElementDrawImageEnabled() || !element) {
+  if (!RuntimeEnabledFeatures::CanvasElementDrawElementEnabled() || !element) {
     return false;
   }
 
diff --git a/third_party/blink/renderer/core/editing/build.gni b/third_party/blink/renderer/core/editing/build.gni
index aa7e993..8e0ca95 100644
--- a/third_party/blink/renderer/core/editing/build.gni
+++ b/third_party/blink/renderer/core/editing/build.gni
@@ -56,6 +56,8 @@
   "commands/insert_list_command.h",
   "commands/insert_node_before_command.cc",
   "commands/insert_node_before_command.h",
+  "commands/insert_node_list_before_command.cc",
+  "commands/insert_node_list_before_command.h",
   "commands/insert_paragraph_separator_command.cc",
   "commands/insert_paragraph_separator_command.h",
   "commands/insert_text_command.cc",
diff --git a/third_party/blink/renderer/core/editing/commands/append_node_command.cc b/third_party/blink/renderer/core/editing/commands/append_node_command.cc
index 375fb853..fada44e 100644
--- a/third_party/blink/renderer/core/editing/commands/append_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/append_node_command.cc
@@ -53,6 +53,10 @@
   node_->remove(IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String AppendNodeCommand::ToString() const {
+  return "AppendNodeCommand";
+}
+
 void AppendNodeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(parent_);
   visitor->Trace(node_);
diff --git a/third_party/blink/renderer/core/editing/commands/append_node_command.h b/third_party/blink/renderer/core/editing/commands/append_node_command.h
index 4e11cd1..0a7e0ef 100644
--- a/third_party/blink/renderer/core/editing/commands/append_node_command.h
+++ b/third_party/blink/renderer/core/editing/commands/append_node_command.h
@@ -39,6 +39,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<ContainerNode> parent_;
   Member<Node> node_;
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
index dc90234..2660b52b 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.cc
@@ -44,6 +44,7 @@
 #include "third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h"
 #include "third_party/blink/renderer/core/editing/commands/insert_line_break_command.h"
 #include "third_party/blink/renderer/core/editing/commands/insert_node_before_command.h"
+#include "third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.h"
 #include "third_party/blink/renderer/core/editing/commands/insert_paragraph_separator_command.h"
 #include "third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h"
 #include "third_party/blink/renderer/core/editing/commands/remove_css_property_command.h"
@@ -347,6 +348,20 @@
   }
 }
 
+void CompositeEditCommand::InsertNodeListAfter(Node& insert_first_child,
+                                               Node& ref_child,
+                                               EditingState* editing_state) {
+  ContainerNode* parent = ref_child.parentNode();
+  ABORT_EDITING_COMMAND_IF(!parent);
+  ABORT_EDITING_COMMAND_IF(GetDocument().body() == &ref_child);
+  ABORT_EDITING_COMMAND_IF(!IsEditable(*parent) && parent->InActiveDocument());
+  DCHECK(!parent->IsShadowRoot()) << parent;
+  ApplyCommandToComposite(
+      MakeGarbageCollected<InsertNodeListBeforeCommand>(
+          insert_first_child, *parent, ref_child.nextSibling()),
+      editing_state);
+}
+
 void CompositeEditCommand::InsertNodeAt(Node* insert_child,
                                         const Position& editing_position,
                                         EditingState* editing_state) {
diff --git a/third_party/blink/renderer/core/editing/commands/composite_edit_command.h b/third_party/blink/renderer/core/editing/commands/composite_edit_command.h
index 88302a5..04811b78 100644
--- a/third_party/blink/renderer/core/editing/commands/composite_edit_command.h
+++ b/third_party/blink/renderer/core/editing/commands/composite_edit_command.h
@@ -106,6 +106,10 @@
   virtual void DeleteTextFromNode(Text*, unsigned offset, unsigned count);
   bool IsRemovableBlock(const Node*);
   void InsertNodeAfter(Node*, Node* ref_child, EditingState*);
+  // Insert nodes starting `insert_first_child` after `ref_child`.
+  void InsertNodeListAfter(Node& insert_first_child,
+                           Node& ref_child,
+                           EditingState* editing_state);
   void InsertNodeAt(Node*, const Position&, EditingState*);
   void InsertNodeAtTabSpanPosition(Node*, const Position&, EditingState*);
   void InsertNodeBefore(Node*,
diff --git a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
index 2360fdc..5773b83 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.cc
@@ -28,6 +28,7 @@
 #include "third_party/blink/renderer/core/dom/text.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -67,6 +68,12 @@
   node_->insertData(offset_, text_, IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String DeleteFromTextNodeCommand::ToString() const {
+  return WTF::StrCat(
+      {"DeleteFromTextNodeCommand {offset:", String::Number(offset_),
+       ", count:", String::Number(count_), "}"});
+}
+
 void DeleteFromTextNodeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(node_);
   SimpleEditCommand::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.h b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.h
index 4df0636..d12be83 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.h
+++ b/third_party/blink/renderer/core/editing/commands/delete_from_text_node_command.h
@@ -41,6 +41,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Text> node_;
   unsigned offset_;
diff --git a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
index 7c202910..712b6622 100644
--- a/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/delete_selection_command.cc
@@ -37,6 +37,7 @@
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/editor.h"
 #include "third_party/blink/renderer/core/editing/ephemeral_range.h"
+#include "third_party/blink/renderer/core/editing/frame_selection.h"
 #include "third_party/blink/renderer/core/editing/local_caret_rect.h"
 #include "third_party/blink/renderer/core/editing/relocatable_position.h"
 #include "third_party/blink/renderer/core/editing/selection_template.h"
@@ -849,15 +850,38 @@
         downstream_end_.IsConnected() &&
         downstream_end_.ComputeEditingOffset() >=
             CaretMinOffset(downstream_end_.AnchorNode())) {
-      bool is_node_fully_selected =
-          downstream_end_.AtLastEditingPositionForNode() &&
-          !CanHaveChildrenForEditing(downstream_end_.AnchorNode());
-      // Even though `downstream_end_` has children, it can be fully selected.
-      // Update `is_node_fully_selected` if the selection includes the first
-      // position of the node.
-      if (!is_node_fully_selected &&
-          downstream_end_.AtLastEditingPositionForNode()) {
-        is_node_fully_selected = end_node_is_selected_from_first_position;
+      bool is_node_fully_selected = false;
+      if (downstream_end_.AtLastEditingPositionForNode()) {
+        if (!CanHaveChildrenForEditing(downstream_end_.AnchorNode())) {
+          is_node_fully_selected = true;
+        } else if (end_node_is_selected_from_first_position) {
+          // If the selection includes the first position of the
+          // node, the node may be considered fully selected.
+          if (RuntimeEnabledFeatures::
+                  RemoveNodeDetermineNodeFullySelectedEnabled()) {
+            if (downstream_end_.AnchorNode()->IsDescendantOf(
+                    upstream_start_.AnchorNode())) {
+              // The node is a child of the `upstream_start_.AnchorNode()`,
+              // the node be fully selected.
+              // See https://issues.chromium.org/issues/331074432.
+              is_node_fully_selected = true;
+            } else if (ComparePositions(downstream_end_,
+                                        GetDocument()
+                                            .GetFrame()
+                                            ->Selection()
+                                            .GetSelectionInDOMTree()
+                                            .Focus()) <= 0) {
+              // `downstream_end_` in FrameSelection(Use FrameSelection because
+              // we need non-visual selection), the node be fully selected.
+              // FrameSelection can be used to delete the node that is
+              // invisible, such as `<span></span>`.
+              // See https://issues.chromium.org/issues/415911524.
+              is_node_fully_selected = true;
+            }
+          } else {
+            is_node_fully_selected = true;
+          }
+        }
       }
       if (is_node_fully_selected) {
         // The node itself is fully selected, not just its contents.  Delete it.
diff --git a/third_party/blink/renderer/core/editing/commands/edit_command.h b/third_party/blink/renderer/core/editing/commands/edit_command.h
index 90c8606..fab95c8 100644
--- a/third_party/blink/renderer/core/editing/commands/edit_command.h
+++ b/third_party/blink/renderer/core/editing/commands/edit_command.h
@@ -85,6 +85,8 @@
   virtual void DoUnapply() = 0;
   virtual void DoReapply();  // calls doApply()
 
+  virtual String ToString() const = 0;
+
  protected:
   explicit SimpleEditCommand(Document& document) : EditCommand(document) {}
 
diff --git a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
index faaa1f96..43c74f1 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.cc
@@ -31,6 +31,7 @@
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -74,6 +75,12 @@
   node_->deleteData(offset_, text_.length(), IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String InsertIntoTextNodeCommand::ToString() const {
+  return WTF::StrCat(
+      {"InsertIntoTextNodeCommand {offset:", String::Number(offset_),
+       ", text:", text_.EncodeForDebugging(), "}"});
+}
+
 void InsertIntoTextNodeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(node_);
   SimpleEditCommand::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h
index fb40fba6..cd9299b 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h
+++ b/third_party/blink/renderer/core/editing/commands/insert_into_text_node_command.h
@@ -41,6 +41,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Text> node_;
   unsigned offset_;
diff --git a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
index 5601d58..3058437 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.cc
@@ -80,6 +80,10 @@
   insert_child_->remove(IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String InsertNodeBeforeCommand::ToString() const {
+  return "InsertNodeBeforeCommand";
+}
+
 void InsertNodeBeforeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(insert_child_);
   visitor->Trace(ref_child_);
diff --git a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.h b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.h
index 489d056..5be22ef 100644
--- a/third_party/blink/renderer/core/editing/commands/insert_node_before_command.h
+++ b/third_party/blink/renderer/core/editing/commands/insert_node_before_command.h
@@ -41,6 +41,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Node> insert_child_;
   Member<Node> ref_child_;
diff --git a/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.cc b/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.cc
new file mode 100644
index 0000000..14ed169
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.cc
@@ -0,0 +1,68 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.h"
+
+#include "third_party/blink/renderer/core/editing/commands/editing_state.h"
+#include "third_party/blink/renderer/core/editing/editing_utilities.h"
+#include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
+
+namespace blink {
+
+InsertNodeListBeforeCommand::InsertNodeListBeforeCommand(
+    Node& first_insert_child,
+    Node& parent,
+    Node* ref_child)
+    : SimpleEditCommand(parent.GetDocument()),
+      parent_(parent),
+      ref_child_(ref_child) {
+  DCHECK(IsEditable(parent) || !parent.InActiveDocument()) << parent;
+  wtf_size_t count = 0;
+  for (Node* child = &first_insert_child; child; child = child->nextSibling()) {
+    ++count;
+  }
+  insert_children_.reserve(count);
+  for (Node* child = &first_insert_child; child; child = child->nextSibling()) {
+    insert_children_.push_back(child);
+  }
+}
+
+void InsertNodeListBeforeCommand::DoApply(EditingState* editing_state) {
+  GetDocument().UpdateStyleAndLayoutTree();
+  if (!IsEditable(*parent_)) {
+    return;
+  }
+
+  DummyExceptionStateForTesting exception_state;
+  for (auto& child : insert_children_) {
+    parent_->insertBefore(child.Get(), ref_child_.Get(), exception_state);
+    ABORT_EDITING_COMMAND_IF(exception_state.HadException());
+    ABORT_EDITING_COMMAND_IF(child->parentNode() != parent_);
+  }
+}
+
+void InsertNodeListBeforeCommand::DoUnapply() {
+  GetDocument().UpdateStyleAndLayoutTree();
+  if (!IsEditable(*parent_)) {
+    return;
+  }
+  for (auto& child : insert_children_) {
+    child->remove(IGNORE_EXCEPTION_FOR_TESTING);
+  }
+}
+
+String InsertNodeListBeforeCommand::ToString() const {
+  return WTF::StrCat({"InsertNodeListBeforeCommand {insert_children:[",
+                      String::Number(insert_children_.size()), " nodes]}"});
+}
+
+void InsertNodeListBeforeCommand::Trace(Visitor* visitor) const {
+  visitor->Trace(insert_children_);
+  visitor->Trace(parent_);
+  visitor->Trace(ref_child_);
+  SimpleEditCommand::Trace(visitor);
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.h b/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.h
new file mode 100644
index 0000000..654b67e7
--- /dev/null
+++ b/third_party/blink/renderer/core/editing/commands/insert_node_list_before_command.h
@@ -0,0 +1,32 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_NODE_LIST_BEFORE_COMMAND_H_
+#define THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_NODE_LIST_BEFORE_COMMAND_H_
+
+#include "third_party/blink/renderer/core/editing/commands/edit_command.h"
+
+namespace blink {
+
+class InsertNodeListBeforeCommand final : public SimpleEditCommand {
+ public:
+  InsertNodeListBeforeCommand(Node& first_insert_child,
+                              Node& parent,
+                              Node* ref_child);
+
+  void Trace(Visitor* visitor) const override;
+
+ private:
+  void DoApply(EditingState* editing_stae) override;
+  void DoUnapply() override;
+  String ToString() const override;
+
+  HeapVector<Member<Node>> insert_children_;
+  Member<Node> parent_;
+  Member<Node> ref_child_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_CORE_EDITING_COMMANDS_INSERT_NODE_LIST_BEFORE_COMMAND_H_
diff --git a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
index 08b13b3..7e94924 100644
--- a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.cc
@@ -84,6 +84,10 @@
     element1_->AppendChild(child.Release(), exception_state);
 }
 
+String MergeIdenticalElementsCommand::ToString() const {
+  return "MergeIdenticalElementsCommand";
+}
+
 void MergeIdenticalElementsCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element1_);
   visitor->Trace(element2_);
diff --git a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h
index aa65712..1a1a9fc 100644
--- a/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h
+++ b/third_party/blink/renderer/core/editing/commands/merge_identical_elements_command.h
@@ -39,6 +39,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Element> element1_;
   Member<Element> element2_;
diff --git a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
index 894559f..aebdf7ae 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/execution_context/execution_context.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -69,6 +70,11 @@
       IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String RemoveCSSPropertyCommand::ToString() const {
+  return WTF::StrCat({"RemoveCSSPropertyCommand {",
+                      CSSPropertyName(property_).ToAtomicString(), "}"});
+}
+
 void RemoveCSSPropertyCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element_);
   SimpleEditCommand::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h
index def9c50..c0eb80a 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h
+++ b/third_party/blink/renderer/core/editing/commands/remove_css_property_command.h
@@ -43,6 +43,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Element> element_;
   CSSPropertyID property_;
diff --git a/third_party/blink/renderer/core/editing/commands/remove_node_command.cc b/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
index 2ebb1298..aa961ce 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/remove_node_command.cc
@@ -29,6 +29,7 @@
 #include "third_party/blink/renderer/core/editing/commands/editing_state.h"
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -73,6 +74,10 @@
   parent->InsertBefore(node_.Get(), ref_child, IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String RemoveNodeCommand::ToString() const {
+  return WTF::StrCat({"RemoveNodeCommand {node:", node_->ToString(), "}"});
+}
+
 void RemoveNodeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(node_);
   visitor->Trace(parent_);
diff --git a/third_party/blink/renderer/core/editing/commands/remove_node_command.h b/third_party/blink/renderer/core/editing/commands/remove_node_command.h
index 2b6d06b3..fe3895c 100644
--- a/third_party/blink/renderer/core/editing/commands/remove_node_command.h
+++ b/third_party/blink/renderer/core/editing/commands/remove_node_command.h
@@ -39,6 +39,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Node> node_;
   Member<ContainerNode> parent_;
diff --git a/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc b/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
index 08cce41..23e9cd1 100644
--- a/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.cc
@@ -81,6 +81,10 @@
                                             *span_element_);
 }
 
+String ReplaceNodeWithSpanCommand::ToString() const {
+  return "ReplaceNodeWithSpanCommand";
+}
+
 void ReplaceNodeWithSpanCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element_to_replace_);
   visitor->Trace(span_element_);
diff --git a/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.h b/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.h
index 61963cf1..b294320b 100644
--- a/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.h
+++ b/third_party/blink/renderer/core/editing/commands/replace_node_with_span_command.h
@@ -51,6 +51,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<HTMLElement> element_to_replace_;
   Member<HTMLSpanElement> span_element_;
diff --git a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
index d2dc9be4..0c5765f 100644
--- a/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/replace_selection_command.cc
@@ -1513,22 +1513,45 @@
 
   bool plain_text_fragment = IsPlainTextMarkup(inserted_nodes.RefNode());
 
-  while (node) {
-    Node* next = node->nextSibling();
-    fragment.RemoveNode(node);
-    InsertNodeAfter(node, inserted_nodes.RefNode(), editing_state);
-    if (editing_state->IsAborted())
-      return;
-    inserted_nodes.RespondToNodeInsertion(*node);
+  if (RuntimeEnabledFeatures::EditingFastRichReplaceEnabled()) {
+    for (Node* plain_node = node; plain_text_fragment && plain_node;
+         plain_node = plain_node->nextSibling()) {
+      plain_text_fragment = IsPlainTextMarkup(plain_node);
+    }
+    Node* ref_node = inserted_nodes.RefNode();
+    if (Node* last_node = fragment.LastChild()) {
+      DCHECK(node);
+      InsertNodeListAfter(*node, *ref_node, editing_state);
+      if (editing_state->IsAborted()) {
+        return;
+      }
+      DCHECK(!fragment.FirstChild()) << fragment.FirstChild();
+      inserted_nodes.RespondToNodeInsertion(*node);
+      inserted_nodes.RespondToNodeInsertion(*last_node);
+      inserted_nodes.SetRefNode(last_node);
+    }
+  } else {
+    while (node) {
+      Node* next = node->nextSibling();
+      fragment.RemoveNode(node);
+      InsertNodeAfter(node, inserted_nodes.RefNode(), editing_state);
+      if (editing_state->IsAborted()) {
+        return;
+      }
+      inserted_nodes.RespondToNodeInsertion(*node);
 
-    // Mutation events (bug 22634) may have already removed the inserted content
-    if (!node->isConnected())
-      return;
+      // Mutation events (bug 22634) may have already removed the inserted
+      // content
+      if (!node->isConnected()) {
+        return;
+      }
 
-    inserted_nodes.SetRefNode(node);
-    if (node && plain_text_fragment)
-      plain_text_fragment = IsPlainTextMarkup(node);
-    node = next;
+      inserted_nodes.SetRefNode(node);
+      if (node && plain_text_fragment) {
+        plain_text_fragment = IsPlainTextMarkup(node);
+      }
+      node = next;
+    }
   }
 
   if (IsRichlyEditablePosition(insertion_pos)) {
diff --git a/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc b/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
index 5ba4913..4deeb6a 100644
--- a/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/set_character_data_command.cc
@@ -7,6 +7,7 @@
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/frame/settings.h"
 #include "third_party/blink/renderer/core/layout/layout_text.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -65,6 +66,11 @@
                      IGNORE_EXCEPTION_FOR_TESTING);
 }
 
+String SetCharacterDataCommand::ToString() const {
+  return WTF::StrCat({"SetCharacterDataCommand {new_text:",
+                      new_text_.EncodeForDebugging(), "}"});
+}
+
 void SetCharacterDataCommand::Trace(Visitor* visitor) const {
   visitor->Trace(node_);
   SimpleEditCommand::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/commands/set_character_data_command.h b/third_party/blink/renderer/core/editing/commands/set_character_data_command.h
index fa040b7..777c4f5 100644
--- a/third_party/blink/renderer/core/editing/commands/set_character_data_command.h
+++ b/third_party/blink/renderer/core/editing/commands/set_character_data_command.h
@@ -23,6 +23,7 @@
   // EditCommand implementation
   void DoApply(EditingState*) final;
   void DoUnapply() final;
+  String ToString() const final;
 
   const Member<Text> node_;
   const unsigned offset_;
diff --git a/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.cc b/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.cc
index dff8e5d8..eed35a2 100644
--- a/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.cc
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/core/editing/commands/set_node_attribute_command.h"
 
 #include "third_party/blink/renderer/core/dom/element.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -49,6 +50,11 @@
   old_value_ = g_null_atom;
 }
 
+String SetNodeAttributeCommand::ToString() const {
+  return WTF::StrCat(
+      {"SetNodeAttributeCommand {attribute:", attribute_.ToString(), "}"});
+}
+
 void SetNodeAttributeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element_);
   SimpleEditCommand::Trace(visitor);
diff --git a/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.h b/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.h
index 1919d31..bd74b79e 100644
--- a/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.h
+++ b/third_party/blink/renderer/core/editing/commands/set_node_attribute_command.h
@@ -42,6 +42,7 @@
  private:
   void DoApply(EditingState*) override;
   void DoUnapply() override;
+  String ToString() const override;
 
   Member<Element> element_;
   QualifiedName attribute_;
diff --git a/third_party/blink/renderer/core/editing/commands/split_element_command.cc b/third_party/blink/renderer/core/editing/commands/split_element_command.cc
index 1b4d9db..7c5670f9 100644
--- a/third_party/blink/renderer/core/editing/commands/split_element_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/split_element_command.cc
@@ -105,6 +105,10 @@
   ExecuteApply();
 }
 
+String SplitElementCommand::ToString() const {
+  return "SplitElementCommand";
+}
+
 void SplitElementCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element1_);
   visitor->Trace(element2_);
diff --git a/third_party/blink/renderer/core/editing/commands/split_element_command.h b/third_party/blink/renderer/core/editing/commands/split_element_command.h
index 988ea13..687dfec 100644
--- a/third_party/blink/renderer/core/editing/commands/split_element_command.h
+++ b/third_party/blink/renderer/core/editing/commands/split_element_command.h
@@ -42,6 +42,7 @@
   void DoUnapply() override;
   void DoReapply() override;
   void ExecuteApply();
+  String ToString() const override;
 
   Member<Element> element1_;
   Member<Element> element2_;
diff --git a/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc b/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
index 33450e3bb..214b5d9 100644
--- a/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/split_text_node_command.cc
@@ -30,6 +30,7 @@
 #include "third_party/blink/renderer/core/editing/editing_utilities.h"
 #include "third_party/blink/renderer/core/editing/markers/document_marker_controller.h"
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
+#include "third_party/blink/renderer/platform/wtf/text/strcat.h"
 
 namespace blink {
 
@@ -102,6 +103,11 @@
   GetDocument().UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
 }
 
+String SplitTextNodeCommand::ToString() const {
+  return WTF::StrCat(
+      {"SplitTextNodeCommand {offset:", String::Number(offset_), "}"});
+}
+
 void SplitTextNodeCommand::Trace(Visitor* visitor) const {
   visitor->Trace(text1_);
   visitor->Trace(text2_);
diff --git a/third_party/blink/renderer/core/editing/commands/split_text_node_command.h b/third_party/blink/renderer/core/editing/commands/split_text_node_command.h
index 6a562d5e..971d524 100644
--- a/third_party/blink/renderer/core/editing/commands/split_text_node_command.h
+++ b/third_party/blink/renderer/core/editing/commands/split_text_node_command.h
@@ -44,6 +44,7 @@
   void DoUnapply() override;
   void DoReapply() override;
   void InsertText1AndTrimText2();
+  String ToString() const override;
 
   Member<Text> text1_;
   Member<Text> text2_;
diff --git a/third_party/blink/renderer/core/editing/commands/undo_stack.cc b/third_party/blink/renderer/core/editing/commands/undo_stack.cc
index 9c5f4643..d051b22 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_stack.cc
+++ b/third_party/blink/renderer/core/editing/commands/undo_stack.cc
@@ -29,6 +29,7 @@
 #include "base/auto_reset.h"
 #include "third_party/blink/renderer/core/dom/container_node.h"
 #include "third_party/blink/renderer/core/editing/commands/undo_step.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
 
@@ -139,4 +140,23 @@
   element->SetHasUndoStack(false);
 }
 
+String UndoStack::ToString() const {
+  StringBuilder builder;
+  builder.Append("UndoStack {undo_stack:[");
+  const char* delimiter = "\n  ";
+  for (const auto& step : UndoSteps()) {
+    builder.Append(delimiter);
+    builder.Append(step->ToString());
+  }
+  builder.Append("], redo_stack:[");
+  delimiter = "\n  ";
+  for (const auto& step : RedoSteps()) {
+    builder.Append(delimiter);
+    builder.Append(step->ToString());
+    delimiter = ",\n  ";
+  }
+  builder.Append("]}");
+  return builder.ReleaseString();
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/editing/commands/undo_stack.h b/third_party/blink/renderer/core/editing/commands/undo_stack.h
index aaa9365..3d501be1 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_stack.h
+++ b/third_party/blink/renderer/core/editing/commands/undo_stack.h
@@ -84,6 +84,7 @@
   // should be root editable element and be in undo/redo stack.
   void ElementRemoved(Element* element);
 
+  String ToString() const;
   void Trace(Visitor*) const;
 
  private:
diff --git a/third_party/blink/renderer/core/editing/commands/undo_step.cc b/third_party/blink/renderer/core/editing/commands/undo_step.cc
index 0e245ca5..c9dff2c 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_step.cc
+++ b/third_party/blink/renderer/core/editing/commands/undo_step.cc
@@ -15,6 +15,7 @@
 #include "third_party/blink/renderer/core/editing/set_selection_options.h"
 #include "third_party/blink/renderer/core/frame/local_dom_window.h"
 #include "third_party/blink/renderer/core/frame/local_frame.h"
+#include "third_party/blink/renderer/platform/wtf/text/string_builder.h"
 
 namespace blink {
 
@@ -145,6 +146,19 @@
   ending_selection_ = selection;
 }
 
+String UndoStep::ToString() const {
+  StringBuilder builder;
+  builder.Append("UndoStep {commands:[");
+  String delimiter = "\n    ";
+  for (const auto& command : commands_) {
+    builder.Append(delimiter);
+    builder.Append(command->ToString());
+    delimiter = ",\n    ";
+  }
+  builder.Append("]}");
+  return builder.ReleaseString();
+}
+
 void UndoStep::Trace(Visitor* visitor) const {
   visitor->Trace(document_);
   visitor->Trace(starting_selection_);
diff --git a/third_party/blink/renderer/core/editing/commands/undo_step.h b/third_party/blink/renderer/core/editing/commands/undo_step.h
index bded1cf..d8232de 100644
--- a/third_party/blink/renderer/core/editing/commands/undo_step.h
+++ b/third_party/blink/renderer/core/editing/commands/undo_step.h
@@ -76,6 +76,8 @@
 
   void Trace(Visitor*) const;
 
+  String ToString() const;
+
  private:
   Member<Document> document_;
   SelectionForUndoStep starting_selection_;
diff --git a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
index 6a909b9..a12806c8 100644
--- a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
+++ b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.cc
@@ -78,6 +78,10 @@
   ExecuteApply();
 }
 
+String WrapContentsInDummySpanCommand::ToString() const {
+  return "WrapContentsInDummySpanCommand";
+}
+
 void WrapContentsInDummySpanCommand::Trace(Visitor* visitor) const {
   visitor->Trace(element_);
   visitor->Trace(dummy_span_);
diff --git a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.h b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.h
index 1798435..2b155598 100644
--- a/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.h
+++ b/third_party/blink/renderer/core/editing/commands/wrap_contents_in_dummy_span_command.h
@@ -43,6 +43,7 @@
   void DoUnapply() override;
   void DoReapply() override;
   void ExecuteApply();
+  String ToString() const override;
 
   Member<Element> element_;
   Member<HTMLSpanElement> dummy_span_;
diff --git a/third_party/blink/renderer/core/editing/ime/text_format.idl b/third_party/blink/renderer/core/editing/ime/text_format.idl
index ab6f5665..586ff58 100644
--- a/third_party/blink/renderer/core/editing/ime/text_format.idl
+++ b/third_party/blink/renderer/core/editing/ime/text_format.idl
@@ -21,6 +21,6 @@
     // https://crbug.com/354497121 These should be UnderlineStyle and
     // UnderlineThickness enumerations but the values returned by the
     // implementation do not match what the IDL defines.
-    readonly attribute DOMString underlineStyle;
-    readonly attribute DOMString underlineThickness;
+    [MeasureAs=EditContextTextFormatUnderlineStyle] readonly attribute DOMString underlineStyle;
+    [MeasureAs=EditContextTextFormatUnderlineThickness] readonly attribute DOMString underlineThickness;
 };
diff --git a/third_party/blink/renderer/core/frame/integrity_policy.cc b/third_party/blink/renderer/core/frame/integrity_policy.cc
index ad8a852..0984d90 100644
--- a/third_party/blink/renderer/core/frame/integrity_policy.cc
+++ b/third_party/blink/renderer/core/frame/integrity_policy.cc
@@ -69,8 +69,14 @@
     network::mojom::RequestMode request_mode,
     const IntegrityMetadataSet& integrity_metadata,
     const KURL& url) {
-  if (!context ||
-      (!integrity_metadata.empty() &&
+  if (!context) {
+    return true;
+  }
+  const DOMWrapperWorld* world = context->GetCurrentWorld();
+  if (world && world->IsIsolatedWorld()) {
+    return true;
+  }
+  if ((!integrity_metadata.empty() &&
        request_mode != network::mojom::RequestMode::kNoCors) ||
       url.ProtocolIsData() || url.ProtocolIs("blob")) {
     return true;
diff --git a/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl b/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
index e0eca764..06d3214 100644
--- a/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
+++ b/third_party/blink/renderer/core/html/canvas/html_canvas_element.idl
@@ -36,7 +36,7 @@
     [RaisesException=Setter, CEReactions] attribute unsigned long width;
     [RaisesException=Setter, CEReactions] attribute unsigned long height;
 
-    [RuntimeEnabled=CanvasElementDrawImage] attribute boolean layoutSubtree;
+    [RuntimeEnabled=CanvasElementDrawElement] attribute boolean layoutSubtree;
 
     [HighEntropy, MeasureAs=CanvasToDataURL, RaisesException] DOMString toDataURL(optional DOMString type = "image/png", optional any quality);
 
diff --git a/third_party/blink/renderer/core/html/html_element.cc b/third_party/blink/renderer/core/html/html_element.cc
index c72d9a7..a78d967 100644
--- a/third_party/blink/renderer/core/html/html_element.cc
+++ b/third_party/blink/renderer/core/html/html_element.cc
@@ -2821,7 +2821,7 @@
           AtomicString(url), GetDocument().CompleteURL(url),
           Referrer(GetExecutionContext()->OutgoingReferrer(),
                    GetExecutionContext()->GetReferrerPolicy()),
-          OriginClean::kTrue, false /* is_ad_related */));
+          /*origin_clean=*/true, /*is_ad_related=*/false));
   if (initiator_name) {
     image_value->SetInitiator(initiator_name);
   }
diff --git a/third_party/blink/renderer/core/layout/forms/layout_text_control_inner_editor.h b/third_party/blink/renderer/core/layout/forms/layout_text_control_inner_editor.h
index 010192b..31858f20 100644
--- a/third_party/blink/renderer/core/layout/forms/layout_text_control_inner_editor.h
+++ b/third_party/blink/renderer/core/layout/forms/layout_text_control_inner_editor.h
@@ -25,6 +25,13 @@
     return true;
   }
 
+  // Returns true if the host is a <textarea> and TextareaMultipleIfcs flag
+  // is enabled.
+  bool IsMultiline() const {
+    NOT_DESTROYED();
+    return is_multiline_;
+  }
+
   void AddChild(LayoutObject* new_child,
                 LayoutObject* before_child = nullptr) override;
 
@@ -32,6 +39,13 @@
   const bool is_multiline_;
 };
 
+template <>
+struct DowncastTraits<LayoutTextControlInnerEditor> {
+  static bool AllowFrom(const LayoutObject& object) {
+    return object.IsTextControlInnerEditor();
+  }
+};
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_FORMS_LAYOUT_TEXT_CONTROL_INNER_EDITOR_H_
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc
index d0c38dd..3a8e663 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -43,6 +43,7 @@
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/html/shadow/shadow_element_names.h"
 #include "third_party/blink/renderer/core/layout/absolute_utils.h"
+#include "third_party/blink/renderer/core/layout/forms/layout_text_control_inner_editor.h"
 #include "third_party/blink/renderer/core/layout/fragmentation_utils.h"
 #include "third_party/blink/renderer/core/layout/hit_test_location.h"
 #include "third_party/blink/renderer/core/layout/inline/inline_cursor.h"
@@ -80,8 +81,10 @@
 // returned, and there are inline children, an anonymous block wrapper needs to
 // be created.
 bool AllowsInlineChildren(const LayoutBlockFlow& block) {
+  const auto* inner_editor = DynamicTo<LayoutTextControlInnerEditor>(block);
   return !IsA<LayoutMultiColumnFlowThread>(block) &&
-         !block.IsScrollMarkerGroup();
+         !block.IsScrollMarkerGroup() &&
+         !(inner_editor && inner_editor->IsMultiline());
 }
 
 bool IsInnerEditorChild(const LayoutBlockFlow& block) {
@@ -310,9 +313,7 @@
 
   if (FirstChild() && !BeingDestroyed() &&
       !old_child->IsFloatingOrOutOfFlowPositioned() &&
-      !old_child->IsAnonymousBlockFlow() &&
-      !(RuntimeEnabledFeatures::TextareaMultipleIfcsEnabled() &&
-        IsTextControlInnerEditor())) {
+      !old_child->IsAnonymousBlockFlow()) {
     // If the child we're removing means that we can now treat all children as
     // inline without the need for anonymous blocks, then do that.
     MakeChildrenInlineIfPossible();
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc b/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc
index 8bba592..d2199bc 100644
--- a/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc
+++ b/third_party/blink/renderer/core/layout/layout_block_flow_hot.cc
@@ -30,7 +30,7 @@
     return true;
   }
 
-  if (RuntimeEnabledFeatures::CanvasElementDrawImageEnabled() &&
+  if (RuntimeEnabledFeatures::CanvasElementDrawElementEnabled() &&
       Parent()->IsCanvas()) {
     return true;
   }
diff --git a/third_party/blink/renderer/core/layout/layout_html_canvas.h b/third_party/blink/renderer/core/layout/layout_html_canvas.h
index 26de855..3cc28ae 100644
--- a/third_party/blink/renderer/core/layout/layout_html_canvas.h
+++ b/third_party/blink/renderer/core/layout/layout_html_canvas.h
@@ -96,7 +96,7 @@
   }
   bool CanHaveChildren() const final {
     NOT_DESTROYED();
-    return RuntimeEnabledFeatures::CanvasElementDrawImageEnabled();
+    return RuntimeEnabledFeatures::CanvasElementDrawElementEnabled();
   }
   bool IsChildAllowed(LayoutObject*, const ComputedStyle&) const final;
 
diff --git a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
index a7dc6136..aebaca2 100644
--- a/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
+++ b/third_party/blink/renderer/core/layout/layout_image_resource_style_image.cc
@@ -63,9 +63,14 @@
     const gfx::SizeF& size) const {
   // Generated content may trigger calls to image() while we're still pending,
   // don't assert but gracefully exit.
-  if (style_image_->IsPendingImage())
+  if (style_image_->IsPendingImage()) {
     return nullptr;
-  return style_image_->GetImage(*layout_object_, layout_object_->GetDocument(),
+  }
+  const Node* node = layout_object_->GetNode();
+  if (!node) {
+    node = &layout_object_->GetDocument();
+  }
+  return style_image_->GetImage(*layout_object_, *node,
                                 layout_object_->StyleRef(), size);
 }
 
diff --git a/third_party/blink/renderer/core/layout/replaced_layout_algorithm.cc b/third_party/blink/renderer/core/layout/replaced_layout_algorithm.cc
index 1dfa1044..981c1da 100644
--- a/third_party/blink/renderer/core/layout/replaced_layout_algorithm.cc
+++ b/third_party/blink/renderer/core/layout/replaced_layout_algorithm.cc
@@ -28,7 +28,7 @@
   }
 
   if (Node().IsCanvas() &&
-      RuntimeEnabledFeatures::CanvasElementDrawImageEnabled()) {
+      RuntimeEnabledFeatures::CanvasElementDrawElementEnabled()) {
     LayoutCanvasChildren();
   }
 
diff --git a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
index 79dfd0b..8e616ac 100644
--- a/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
+++ b/third_party/blink/renderer/core/layout/shapes/shape_outside_info.cc
@@ -32,6 +32,7 @@
 #include <memory>
 
 #include "base/auto_reset.h"
+#include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/frame/web_feature.h"
 #include "third_party/blink/renderer/core/inspector/console_message.h"
 #include "third_party/blink/renderer/core/layout/geometry/logical_rect.h"
@@ -232,9 +233,12 @@
   gfx::Rect image_rect =
       ToPixelSnappedLogicalRect(converter.ToLogical(image_physical_rect));
 
-  scoped_refptr<Image> image =
-      style_image->GetImage(*layout_box_, layout_box_->GetDocument(),
-                            layout_box_->StyleRef(), image_size);
+  const Node* node = layout_box_->GetNode();
+  if (!node) {
+    node = &layout_box_->GetDocument();
+  }
+  scoped_refptr<Image> image = style_image->GetImage(
+      *layout_box_, *node, layout_box_->StyleRef(), image_size);
 
   return Shape::CreateRasterShape(
       image.get(), shape_image_threshold,
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc b/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc
index 7ad667c..16e2c15 100644
--- a/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc
+++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_test.cc
@@ -144,7 +144,7 @@
  public:
   AnchorElementInteractionFragmentTest()
       : base::test::WithFeatureOverride(
-            blink::kNoSamePageFragmentPreloadingAnchorTracking) {}
+            blink::kPreloadingNoSamePageFragmentAnchorTracking) {}
 };
 
 INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE(AnchorElementInteractionFragmentTest);
@@ -166,7 +166,7 @@
   EXPECT_EQ(url_received.has_value(), !IsParamFeatureEnabled());
 }
 
-TEST_F(AnchorElementInteractionTest, OtherPageFragment) {
+TEST_P(AnchorElementInteractionFragmentTest, OtherPageFragment) {
   String source("https://example.com/p1");
   SimRequest main_resource(source, "text/html");
   LoadURL(source);
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc
index c0071048..8442356dc 100644
--- a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc
+++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.cc
@@ -28,8 +28,8 @@
 
 namespace blink {
 
-BASE_FEATURE(kNoSamePageFragmentPreloadingAnchorTracking,
-             "NoSamePageFragmentPreloadingAnchorTracking",
+BASE_FEATURE(kPreloadingNoSamePageFragmentAnchorTracking,
+             "PreloadingNoSamePageFragmentAnchorTracking",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
 namespace {
@@ -489,7 +489,7 @@
     return KURL();
   }
   if (base::FeatureList::IsEnabled(
-          kNoSamePageFragmentPreloadingAnchorTracking) &&
+          kPreloadingNoSamePageFragmentAnchorTracking) &&
       url.HasFragmentIdentifier()) {
     const KURL& document_url = anchor.GetDocument().Url();
     if (EqualIgnoringFragmentIdentifier(url, document_url)) {
diff --git a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h
index b974aeb..180ddf3 100644
--- a/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h
+++ b/third_party/blink/renderer/core/loader/anchor_element_interaction_tracker.h
@@ -24,7 +24,7 @@
 class Node;
 class PointerEvent;
 
-CORE_EXPORT BASE_DECLARE_FEATURE(kNoSamePageFragmentPreloadingAnchorTracking);
+CORE_EXPORT BASE_DECLARE_FEATURE(kPreloadingNoSamePageFragmentAnchorTracking);
 
 // Tracks pointerdown events anywhere on a document.  On receiving a pointerdown
 // event, the tracker will retrieve the valid href from the anchor element from
diff --git a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
index f381ca4d..fd44637 100644
--- a/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
+++ b/third_party/blink/renderer/core/loader/resource/font_resource_test.cc
@@ -257,7 +257,7 @@
       *MakeGarbageCollected<CSSUrlData>(
           AtomicString(url.GetString()), url,
           Referrer(document.Url(), document.GetReferrerPolicy()),
-          OriginClean::kTrue, false /* is_ad_related */));
+          /*origin_clean=*/true, /*is_ad_related=*/false));
   auto* src_value =
       CSSFontFaceSrcValue::Create(src_uri_value, nullptr /* world */);
 
diff --git a/third_party/blink/renderer/core/paint/box_painter_base.cc b/third_party/blink/renderer/core/paint/box_painter_base.cc
index 71e68a3..da7762a7 100644
--- a/third_party/blink/renderer/core/paint/box_painter_base.cc
+++ b/third_party/blink/renderer/core/paint/box_painter_base.cc
@@ -1283,9 +1283,10 @@
     geometry.Calculate(bg_layer, bg_paint_context, scrolled_paint_rect,
                        paint_info);
 
-    image = fill_layer_info.image->GetImage(bg_paint_context.ImageClient(),
-                                            document_, image_style,
-                                            gfx::SizeF(geometry.TileSize()));
+    const Node* node = node_;
+    image = fill_layer_info.image->GetImage(
+        bg_paint_context.ImageClient(), node ? *node : document_, image_style,
+        gfx::SizeF(geometry.TileSize()));
 
     image_rendering_settings_context.emplace(context,
                                              style_.GetInterpolationQuality(),
diff --git a/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc b/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
index ed7ff5a..858e491 100644
--- a/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
+++ b/third_party/blink/renderer/core/paint/nine_piece_image_painter.cc
@@ -213,10 +213,15 @@
   const gfx::SizeF default_object_size(border_image_rect.size);
   gfx::SizeF image_size = style_image->ImageSize(
       style.EffectiveZoom(), default_object_size, respect_orientation);
+  const Node* ref_node = node;
+  if (!node) {
+    ref_node = &document;
+  }
   scoped_refptr<Image> image =
-      style_image->GetImage(observer, document, style, image_size);
-  if (!image)
+      style_image->GetImage(observer, *ref_node, style, image_size);
+  if (!image) {
     return true;
+  }
 
   // Resolve the image size again, this time with a size-multiplier of one, to
   // yield the size in CSS pixels. This is the unit/scale we expect the
diff --git a/third_party/blink/renderer/core/paint/svg_mask_painter.cc b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
index 7d40662..83a1288 100644
--- a/third_party/blink/renderer/core/paint/svg_mask_painter.cc
+++ b/third_party/blink/renderer/core/paint/svg_mask_painter.cc
@@ -142,8 +142,10 @@
   }
 
   const Document& document = object.GetDocument();
-  scoped_refptr<Image> image = style_image->GetImage(
-      observer, document, style, gfx::SizeF(geometry.TileSize()));
+  const Node* node = object.GetNode();
+  scoped_refptr<Image> image =
+      style_image->GetImage(observer, node ? *node : document, style,
+                            gfx::SizeF(geometry.TileSize()));
   if (!image) {
     return;
   }
diff --git a/third_party/blink/renderer/core/style/style_crossfade_image.cc b/third_party/blink/renderer/core/style/style_crossfade_image.cc
index bd58264..4634fabd 100644
--- a/third_party/blink/renderer/core/style/style_crossfade_image.cc
+++ b/third_party/blink/renderer/core/style/style_crossfade_image.cc
@@ -251,7 +251,7 @@
 
 scoped_refptr<Image> StyleCrossfadeImage::GetImage(
     const ImageResourceObserver& observer,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) const {
   if (target_size.IsEmpty()) {
@@ -269,7 +269,7 @@
   DCHECK_EQ(images_.size(), weights_.size());
   for (unsigned i = 0; i < images_.size(); ++i) {
     scoped_refptr<Image> image =
-        images_[i]->GetImage(*proxy_observer, document, style, target_size);
+        images_[i]->GetImage(*proxy_observer, node, style, target_size);
     images.push_back(
         CrossfadeGeneratedImage::WeightedImage{std::move(image), weights_[i]});
   }
diff --git a/third_party/blink/renderer/core/style/style_crossfade_image.h b/third_party/blink/renderer/core/style/style_crossfade_image.h
index 190923a..27df1530 100644
--- a/third_party/blink/renderer/core/style/style_crossfade_image.h
+++ b/third_party/blink/renderer/core/style/style_crossfade_image.h
@@ -55,7 +55,7 @@
   void RemoveClient(ImageResourceObserver*) override;
 
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override;
 
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.cc b/third_party/blink/renderer/core/style/style_fetched_image.cc
index 18fbf0c..1f6bba7 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.cc
+++ b/third_party/blink/renderer/core/style/style_fetched_image.cc
@@ -37,17 +37,15 @@
 namespace blink {
 
 StyleFetchedImage::StyleFetchedImage(ImageResourceContent* image,
+                                     const CSSUrlData& url_data,
                                      const Document& document,
                                      bool is_lazyload_possibly_deferred,
-                                     bool is_from_origin_clean_style_sheet,
-                                     bool is_ad_related,
                                      const KURL& url,
                                      const float override_image_resolution)
-    : document_(document),
+    : url_data_(url_data),
+      document_(document),
       url_(url),
-      override_image_resolution_(override_image_resolution),
-      is_from_origin_clean_style_sheet_(is_from_origin_clean_style_sheet),
-      is_ad_related_(is_ad_related) {
+      override_image_resolution_(override_image_resolution) {
   is_image_resource_ = true;
   is_lazyload_possibly_deferred_ = is_lazyload_possibly_deferred;
 
@@ -71,10 +69,8 @@
   if (!other.IsImageResource()) {
     return false;
   }
-
   const auto& other_image = To<StyleFetchedImage>(other);
-
-  return image_ == other_image.image_ && url_ == other_image.url_ &&
+  return image_ == other_image.image_ && *url_data_ == *other_image.url_data_ &&
          EqualResolutions(override_image_resolution_,
                           other_image.override_image_resolution_);
 }
@@ -101,12 +97,7 @@
 
 CSSValue* StyleFetchedImage::CssValue() const {
   return MakeGarbageCollected<CSSImageValue>(
-      *MakeGarbageCollected<CSSUrlData>(
-          AtomicString(url_.GetString()), url_, Referrer(),
-          is_from_origin_clean_style_sheet_ ? OriginClean::kTrue
-                                            : OriginClean::kFalse,
-          is_ad_related_),
-      const_cast<StyleFetchedImage*>(this));
+      *url_data_->MakeAbsolute(), const_cast<StyleFetchedImage*>(this));
 }
 
 CSSValue* StyleFetchedImage::ComputedCSSValue(const ComputedStyle&,
@@ -140,6 +131,10 @@
   return false;
 }
 
+bool StyleFetchedImage::IsFromOriginCleanStyleSheet() const {
+  return url_data_->IsFromOriginCleanStyleSheet();
+}
+
 float StyleFetchedImage::ApplyImageResolution(float multiplier) const {
   const Image& image = *image_->GetImage();
   if (image.IsBitmapImage() && override_image_resolution_ > 0.0f) {
@@ -242,7 +237,7 @@
 
 scoped_refptr<Image> StyleFetchedImage::GetImage(
     const ImageResourceObserver&,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) const {
   Image* image = image_->GetImage();
@@ -254,7 +249,8 @@
       SVGImageForContainer::CreateViewInfo(*svg_image, url_);
   return SVGImageForContainer::Create(
       *svg_image, target_size, style.EffectiveZoom(), view_info,
-      document.GetStyleEngine().ResolveColorSchemeForEmbedding(&style));
+      node.GetDocument().GetStyleEngine().ResolveColorSchemeForEmbedding(
+          &style));
 }
 
 bool StyleFetchedImage::KnownToBeOpaque(const Document&,
@@ -299,6 +295,7 @@
 
 void StyleFetchedImage::Trace(Visitor* visitor) const {
   visitor->Trace(image_);
+  visitor->Trace(url_data_);
   visitor->Trace(document_);
   StyleImage::Trace(visitor);
   ImageResourceObserver::Trace(visitor);
diff --git a/third_party/blink/renderer/core/style/style_fetched_image.h b/third_party/blink/renderer/core/style/style_fetched_image.h
index 89992cb..03946672 100644
--- a/third_party/blink/renderer/core/style/style_fetched_image.h
+++ b/third_party/blink/renderer/core/style/style_fetched_image.h
@@ -34,6 +34,7 @@
 
 namespace blink {
 
+class CSSUrlData;
 class Document;
 
 // This class represents an <image> that loads a single image resource (the
@@ -44,10 +45,9 @@
 
  public:
   StyleFetchedImage(ImageResourceContent* image,
+                    const CSSUrlData& url_data,
                     const Document& document,
                     bool is_lazyload_possibly_deferred,
-                    bool is_from_origin_clean_style_sheet,
-                    bool is_ad_related,
                     const KURL& url,
                     const float override_image_resolution = 0.0f);
   ~StyleFetchedImage() override;
@@ -66,6 +66,7 @@
   bool IsLoading() const override;
   bool ErrorOccurred() const override;
   bool IsAccessAllowed(String&) const override;
+  bool IsFromOriginCleanStyleSheet() const override;
 
   NaturalSizingInfo GetNaturalSizingInfo(
       float multiplier,
@@ -78,7 +79,7 @@
   void RemoveClient(ImageResourceObserver*) override;
   String DebugName() const override { return "StyleFetchedImage"; }
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override;
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
@@ -91,10 +92,6 @@
 
   void Trace(Visitor*) const override;
 
-  bool IsFromOriginCleanStyleSheet() const override {
-    return is_from_origin_clean_style_sheet_;
-  }
-
  private:
   bool IsEqual(const StyleImage&) const override;
   void Prefinalize();
@@ -109,6 +106,7 @@
   bool CanBeSpeculativelyDecoded() const override;
 
   Member<ImageResourceContent> image_;
+  Member<const CSSUrlData> url_data_;
   Member<const Document> document_;
 
   const KURL url_;
@@ -116,11 +114,6 @@
   // This overrides an images natural resolution.
   // A value of zero indicates no override.
   const float override_image_resolution_;
-
-  const bool is_from_origin_clean_style_sheet_;
-
-  // Whether this was created by an ad-related CSSParserContext.
-  const bool is_ad_related_;
 };
 
 template <>
diff --git a/third_party/blink/renderer/core/style/style_generated_image.cc b/third_party/blink/renderer/core/style/style_generated_image.cc
index abfe10bb..423ce6e 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.cc
+++ b/third_party/blink/renderer/core/style/style_generated_image.cc
@@ -102,10 +102,10 @@
 
 scoped_refptr<Image> StyleGeneratedImage::GetImage(
     const ImageResourceObserver& observer,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) const {
-  return image_generator_value_->GetImage(observer, document, style,
+  return image_generator_value_->GetImage(observer, node, style,
                                           container_sizes_, target_size);
 }
 
diff --git a/third_party/blink/renderer/core/style/style_generated_image.h b/third_party/blink/renderer/core/style/style_generated_image.h
index ffb769d..512bd189 100644
--- a/third_party/blink/renderer/core/style/style_generated_image.h
+++ b/third_party/blink/renderer/core/style/style_generated_image.h
@@ -67,7 +67,7 @@
   void RemoveClient(ImageResourceObserver*) override;
   // The |target_size| is the desired image size
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override;
   bool KnownToBeOpaque(const Document&, const ComputedStyle&) const override;
diff --git a/third_party/blink/renderer/core/style/style_image.h b/third_party/blink/renderer/core/style/style_image.h
index de1d9e3..1c1b39e 100644
--- a/third_party/blink/renderer/core/style/style_image.h
+++ b/third_party/blink/renderer/core/style/style_image.h
@@ -46,6 +46,7 @@
 class Document;
 class ComputedStyle;
 class ImageResourceObserver;
+class Node;
 enum class CSSValuePhase;
 
 // A const pointer to either an ImageResource or a CSSImageGeneratorValue. It is
@@ -145,7 +146,7 @@
   // `target_size` is not zoomed.
   virtual scoped_refptr<Image> GetImage(
       const ImageResourceObserver&,
-      const Document&,
+      const Node&,
       const ComputedStyle&,
       const gfx::SizeF& target_size) const = 0;
 
diff --git a/third_party/blink/renderer/core/style/style_image_set.cc b/third_party/blink/renderer/core/style/style_image_set.cc
index e3eae94..3692bc0 100644
--- a/third_party/blink/renderer/core/style/style_image_set.cc
+++ b/third_party/blink/renderer/core/style/style_image_set.cc
@@ -134,13 +134,12 @@
 
 scoped_refptr<Image> StyleImageSet::GetImage(
     const ImageResourceObserver& image_resource_observer,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) const {
-  return best_fit_image_
-             ? best_fit_image_->GetImage(image_resource_observer, document,
-                                         style, target_size)
-             : nullptr;
+  return best_fit_image_ ? best_fit_image_->GetImage(image_resource_observer,
+                                                     node, style, target_size)
+                         : nullptr;
 }
 
 float StyleImageSet::ImageScaleFactor() const {
diff --git a/third_party/blink/renderer/core/style/style_image_set.h b/third_party/blink/renderer/core/style/style_image_set.h
index 350fe49..cdec33f 100644
--- a/third_party/blink/renderer/core/style/style_image_set.h
+++ b/third_party/blink/renderer/core/style/style_image_set.h
@@ -71,7 +71,7 @@
   void RemoveClient(ImageResourceObserver*) override;
 
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override;
 
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.cc b/third_party/blink/renderer/core/style/style_mask_source_image.cc
index 4eabef3..a7767757 100644
--- a/third_party/blink/renderer/core/style/style_mask_source_image.cc
+++ b/third_party/blink/renderer/core/style/style_mask_source_image.cc
@@ -114,13 +114,13 @@
 
 scoped_refptr<Image> StyleMaskSourceImage::GetImage(
     const ImageResourceObserver& observer,
-    const Document& document,
+    const Node& node,
     const ComputedStyle& style,
     const gfx::SizeF& target_size) const {
   if (!image_) {
     return Image::NullImage();
   }
-  return image_->GetImage(observer, document, style, target_size);
+  return image_->GetImage(observer, node, style, target_size);
 }
 
 float StyleMaskSourceImage::ImageScaleFactor() const {
diff --git a/third_party/blink/renderer/core/style/style_mask_source_image.h b/third_party/blink/renderer/core/style/style_mask_source_image.h
index 5b16a41..a053a1e 100644
--- a/third_party/blink/renderer/core/style/style_mask_source_image.h
+++ b/third_party/blink/renderer/core/style/style_mask_source_image.h
@@ -64,7 +64,7 @@
   void RemoveClient(ImageResourceObserver*) override;
 
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override;
   float ImageScaleFactor() const override;
diff --git a/third_party/blink/renderer/core/style/style_pending_image.h b/third_party/blink/renderer/core/style/style_pending_image.h
index 1b11ac6..c6e6e9d 100644
--- a/third_party/blink/renderer/core/style/style_pending_image.h
+++ b/third_party/blink/renderer/core/style/style_pending_image.h
@@ -74,7 +74,7 @@
   void AddClient(ImageResourceObserver*) override {}
   void RemoveClient(ImageResourceObserver*) override {}
   scoped_refptr<Image> GetImage(const ImageResourceObserver&,
-                                const Document&,
+                                const Node&,
                                 const ComputedStyle&,
                                 const gfx::SizeF& target_size) const override {
     DUMP_WILL_BE_NOTREACHED();
diff --git a/third_party/blink/renderer/core/svg/svg_length.h b/third_party/blink/renderer/core/svg/svg_length.h
index 8549962c..b8a8679 100644
--- a/third_party/blink/renderer/core/svg/svg_length.h
+++ b/third_party/blink/renderer/core/svg/svg_length.h
@@ -83,7 +83,8 @@
   float Value(const SVGLengthConversionData&, float dimension) const;
   float Value(const SVGLengthContext&) const;
   float ValueInSpecifiedUnits() const {
-    return ClampTo<float>(To<CSSNumericLiteralValue>(*value_).GetDoubleValue());
+    return ClampTo<float>(
+        To<CSSNumericLiteralValue>(*value_).ClampedDoubleValue());
   }
 
   void SetValueAsNumber(float);
diff --git a/third_party/blink/renderer/modules/ai/language_model.cc b/third_party/blink/renderer/modules/ai/language_model.cc
index 66f10d1b..86ef282 100644
--- a/third_party/blink/renderer/modules/ai/language_model.cc
+++ b/third_party/blink/renderer/modules/ai/language_model.cc
@@ -11,8 +11,10 @@
 #include "base/types/expected_macros.h"
 #include "base/types/pass_key.h"
 #include "services/on_device_model/public/mojom/on_device_model.mojom-blink.h"
+#include "third_party/blink/public/mojom/ai/ai_language_model.mojom-blink-forward.h"
 #include "third_party/blink/public/mojom/ai/ai_language_model.mojom-blink.h"
 #include "third_party/blink/public/mojom/ai/model_streaming_responder.mojom-blink.h"
+#include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_create_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_prompt_dict.h"
@@ -172,6 +174,72 @@
       receiver_;
 };
 
+class AppendClient : public GarbageCollected<AppendClient>,
+                     public mojom::blink::AILanguageModelAppendClient,
+                     public AIContextObserver<IDLUndefined> {
+ public:
+  AppendClient(ScriptState* script_state,
+               LanguageModel* language_model,
+               ScriptPromiseResolver<IDLUndefined>* resolver,
+               WTF::Vector<mojom::blink::AILanguageModelPromptPtr> prompts,
+               AbortSignal* signal,
+               base::RepeatingClosure overflow_callback,
+               base::PassKey<LanguageModel>)
+      : AIContextObserver(script_state, language_model, resolver, signal),
+        language_model_(language_model),
+        overflow_callback_(overflow_callback),
+        receiver_(this, language_model->GetExecutionContext()) {
+    mojo::PendingRemote<mojom::blink::AILanguageModelAppendClient>
+        client_remote;
+    receiver_.Bind(client_remote.InitWithNewPipeAndPassReceiver(),
+                   language_model->GetTaskRunner());
+    language_model_->GetAILanguageModelRemote()->Append(
+        std::move(prompts), std::move(client_remote));
+  }
+  ~AppendClient() override = default;
+
+  AppendClient(const AppendClient&) = delete;
+  AppendClient& operator=(const AppendClient&) = delete;
+
+  void Trace(Visitor* visitor) const override {
+    AIContextObserver::Trace(visitor);
+    visitor->Trace(language_model_);
+    visitor->Trace(receiver_);
+  }
+
+  // mojom::blink::AILanguageModelAppendClient implementation.
+  void OnAppendComplete() override {
+    if (!GetResolver()) {
+      return;
+    }
+
+    GetResolver()->Resolve();
+    Cleanup();
+  }
+
+  void OnQuotaOverflow() override {
+    if (overflow_callback_) {
+      overflow_callback_.Run();
+    }
+  }
+
+  void OnError(ModelStreamingResponseStatus status) override {
+    if (GetResolver()) {
+      GetResolver()->Reject(
+          ConvertModelStreamingResponseErrorToDOMException(status));
+    }
+    Cleanup();
+  }
+
+  void ResetReceiver() override { receiver_.reset(); }
+
+ private:
+  Member<LanguageModel> language_model_;
+  base::RepeatingClosure overflow_callback_;
+  HeapMojoReceiver<mojom::blink::AILanguageModelAppendClient, AppendClient>
+      receiver_;
+};
+
 // Parses `constraint` from `options` if available. On success or if no
 // constraint is present returns true, returns false and throws an exception on
 // failure.
@@ -413,6 +481,54 @@
   };
 }
 
+ScriptPromise<IDLUndefined> LanguageModel::append(
+    ScriptState* script_state,
+    const V8LanguageModelPromptInput* input,
+    const LanguageModelAppendOptions* options,
+    ExceptionState& exception_state) {
+  if (!script_state->ContextIsValid()) {
+    ThrowInvalidContextException(exception_state);
+    return ScriptPromise<IDLUndefined>();
+  }
+
+  ScriptPromiseResolver<IDLUndefined>* resolver =
+      MakeGarbageCollected<ScriptPromiseResolver<IDLUndefined>>(script_state);
+  auto promise = resolver->Promise();
+
+  // The API impl only accepts a string by default for now, more to come soon!
+  if (!input->IsString() &&
+      !RuntimeEnabledFeatures::AIPromptAPIMultimodalInputEnabled()) {
+    exception_state.ThrowTypeError("Input type not supported");
+    return promise;
+  }
+
+  auto prompts = BuildPrompts(input, script_state, exception_state,
+                              GetExecutionContext(), input_types_);
+  if (!prompts.has_value()) {
+    // `BuildPrompts` will throw the exception if it fails.
+    resolver->Reject();
+    return promise;
+  }
+
+  if (!language_model_remote_) {
+    ThrowSessionDestroyedException(exception_state);
+    return promise;
+  }
+
+  AbortSignal* signal = options->getSignalOr(nullptr);
+  if (HandleAbortSignal(signal, script_state, exception_state)) {
+    return promise;
+  }
+
+  MakeGarbageCollected<AppendClient>(
+      script_state, this, resolver, std::move(prompts).value(), signal,
+      WTF::BindRepeating(&LanguageModel::OnQuotaOverflow,
+                         WrapWeakPersistent(this)),
+      base::PassKey<LanguageModel>());
+
+  return promise;
+}
+
 ScriptPromise<LanguageModel> LanguageModel::clone(
     ScriptState* script_state,
     const LanguageModelCloneOptions* options,
diff --git a/third_party/blink/renderer/modules/ai/language_model.h b/third_party/blink/renderer/modules/ai/language_model.h
index b3a7dae3..84ef58c 100644
--- a/third_party/blink/renderer/modules/ai/language_model.h
+++ b/third_party/blink/renderer/modules/ai/language_model.h
@@ -9,6 +9,7 @@
 #include "third_party/blink/public/mojom/ai/ai_language_model.mojom-blink-forward.h"
 #include "third_party/blink/renderer/bindings/core/v8/idl_types.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
+#include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_append_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_clone_options.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_expected_input.h"
 #include "third_party/blink/renderer/bindings/modules/v8/v8_language_model_prompt_options.h"
@@ -70,6 +71,10 @@
                                   const V8LanguageModelPromptInput* input,
                                   const LanguageModelPromptOptions* options,
                                   ExceptionState& exception_state);
+  ScriptPromise<IDLUndefined> append(ScriptState* script_state,
+                                     const V8LanguageModelPromptInput* input,
+                                     const LanguageModelAppendOptions* options,
+                                     ExceptionState& exception_state);
   ScriptPromise<IDLDouble> measureInputUsage(
       ScriptState* script_state,
       const V8LanguageModelPromptInput* input,
diff --git a/third_party/blink/renderer/modules/ai/language_model.idl b/third_party/blink/renderer/modules/ai/language_model.idl
index 95f846e..fe080b9 100644
--- a/third_party/blink/renderer/modules/ai/language_model.idl
+++ b/third_party/blink/renderer/modules/ai/language_model.idl
@@ -13,6 +13,10 @@
   AbortSignal signal;
 };
 
+dictionary LanguageModelAppendOptions {
+  AbortSignal signal;
+};
+
 [
   Exposed(Window AIPromptAPI, Worker AIPromptAPIForWorkers),
   RuntimeEnabled=AIPromptAPI,
@@ -59,6 +63,15 @@
     LanguageModelPromptInput input,
     optional LanguageModelPromptOptions options = {}
   );
+  [
+    MeasureAs=LanguageModel_Append,
+    CallWith=ScriptState,
+    RaisesException
+  ]
+  Promise<undefined> append(
+    LanguageModelPromptInput input,
+    optional LanguageModelAppendOptions options = {}
+  );
 
   [
     MeasureAs=LanguageModel_MeasureInputUsage,
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
index 033c742a..d8737b8 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.cc
@@ -712,7 +712,7 @@
     std::optional<double> dwidth,
     std::optional<double> dheight,
     ExceptionState& exception_state) {
-  CHECK(RuntimeEnabledFeatures::CanvasElementDrawImageEnabled());
+  CHECK(RuntimeEnabledFeatures::CanvasElementDrawElementEnabled());
   if (!IsDrawElementEligible(element, exception_state)) {
     return;
   }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
index c96df43..e3e1f583 100644
--- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
+++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d.idl
@@ -58,10 +58,10 @@
     [RuntimeEnabled=CanvasPlaceElement, RaisesException] void placeElement(Element element, unrestricted double x,
                                         unrestricted double y);
 
-    [RuntimeEnabled=CanvasElementDrawImage, RaisesException]
+    [RuntimeEnabled=CanvasElementDrawElement, RaisesException]
     void drawElement(Element element, unrestricted double x, unrestricted double y);
 
-    [RuntimeEnabled=CanvasElementDrawImage, RaisesException]
+    [RuntimeEnabled=CanvasElementDrawElement, RaisesException]
     void drawElement(Element element, unrestricted double x, unrestricted double y,
                      unrestricted double dwidth, unrestricted double dheight);
 
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index 1c541dc..293db85 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -752,7 +752,7 @@
     },
     {
       // https://github.com/WICG/html-in-canvas/blob/main/README.md
-      name: "CanvasElementDrawImage",
+      name: "CanvasElementDrawElement",
       status: "test",
       implied_by: ["CanvasPlaceElement"],
     },
@@ -1882,6 +1882,11 @@
       status: {"Android": "stable"},
     },
     {
+      // crbug.com/341564372
+      name: "EditingFastRichReplace",
+      status: "stable",
+    },
+    {
       name: "ElementCapture",
       status: {"Android": "", "default": "stable"},
     },
@@ -3809,6 +3814,12 @@
       status: "stable",
     },
     {
+      // This feature was shipped in M138, so this flag can be removed in M140.
+      // See https://issues.chromium.org/issues/415911524.
+      name: "RemoveNodeDetermineNodeFullySelected",
+      status: "stable",
+    },
+    {
       // crbug.com/41047725
       name: "RemovePlaceholderBRForDisplayInline",
       status: "stable",
@@ -4653,6 +4664,7 @@
       // crbug.com/341564372
       name: "TextareaLineEndingsAsBr",
       status: "experimental",
+      depends_on: ["EditingFastRichReplace"],
     },
     {
       // crbug.com/341564372
diff --git a/third_party/blink/renderer/platform/wtf/forward.h b/third_party/blink/renderer/platform/wtf/forward.h
index 8ac0b58..05a52d6 100644
--- a/third_party/blink/renderer/platform/wtf/forward.h
+++ b/third_party/blink/renderer/platform/wtf/forward.h
@@ -44,6 +44,7 @@
 class OrdinalNumber;
 class SegmentedBuffer;
 class SharedBuffer;
+class String;
 class StringBuilder;
 class StringImpl;
 class StringView;
@@ -57,6 +58,7 @@
 using WTF::CaseMap;
 using WTF::SegmentedBuffer;
 using WTF::SharedBuffer;
+using WTF::String;
 using WTF::StringBuffer;
 using WTF::StringBuilder;
 using WTF::StringImpl;
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 4df48eab..1ab1486d 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -736,6 +736,10 @@
 crbug.com/378046059 virtual/gpu-rasterization/external/wpt/css/css-images/object-fit-fill-png-001c.html [ Failure ]
 crbug.com/378046059 virtual/gpu-rasterization/external/wpt/css/css-images/object-fit-fill-png-002c.html [ Failure ]
 
+# Gradients are computed at paint time and backgrounds propagated from body to
+# viewport uses the root element index for resolving sibling-index()
+crbug.com/40620723 external/wpt/css/css-images/linear-gradient-body-sibling-index.html [ Failure ]
+
 # [css-backgrounds]
 crbug.com/1042783 external/wpt/css/css-backgrounds/background-size/background-size-near-zero-png.html [ Failure ]
 crbug.com/1042783 external/wpt/css/css-backgrounds/background-size/background-size-near-zero-svg.html [ Failure ]
@@ -8944,7 +8948,6 @@
 crbug.com/365127791 [ Win11 ] fast/canvas/fillText-emoji.html [ Failure Pass ]
 crbug.com/365127791 [ Win11 ] fast/forms/file/file-appearance-bidi-filenames.html [ Failure Pass ]
 crbug.com/365127791 [ Win11 ] fast/loader/json-document-appearance.html [ Failure Pass ]
-crbug.com/365127791 [ Win11 ] fast/ruby/base-shorter-than-text.html [ Failure Pass ]
 crbug.com/365127791 [ Win11 ] fast/ruby/nested-ruby.html [ Failure Pass ]
 crbug.com/365127791 [ Win11 ] inspector-protocol/layout-fonts/languages-emoji-rare-glyphs.js [ Failure Pass ]
 crbug.com/365127791 [ Win11 ] media/track/track-cue-rendering-ruby.html [ Failure Pass ]
@@ -9194,7 +9197,6 @@
 crbug.com/393175977 [ Debug Mac14 ] http/tests/devtools/sources/debugger-breakpoints/event-listener-breakpoints-xhr.js [ Failure Pass Timeout ]
 
 # Gardener 2025-01-21
-crbug.com/391126821 [ Win11-arm64 ] fast/ruby/base-shorter-than-text.html [ Failure Pass ]
 crbug.com/390565845 [ Win ] virtual/media-foundation-for-clear-dcomp/external/wpt/media-source/waiting-for-audio.html [ Crash Failure Pass Timeout ]
 
 # Gardener 2025-02-04
diff --git a/third_party/blink/web_tests/editing/deleting/delete-element-with-fully-selected.html b/third_party/blink/web_tests/editing/deleting/delete-element-with-fully-selected.html
new file mode 100644
index 0000000..225b8263
--- /dev/null
+++ b/third_party/blink/web_tests/editing/deleting/delete-element-with-fully-selected.html
@@ -0,0 +1,61 @@
+<!doctype html>
+<script src="../../resources/testharness.js"></script>
+<script src="../../resources/testharnessreport.js"></script>
+<script src="../assert_selection.js"></script>
+<script>
+selection_test(
+    [
+      '<div contenteditable>Test\u200B|<span></span></div>',
+    ],
+    'delete',
+    [
+      '<div contenteditable>Test|<span></span></div>',
+    ], 'The span node is not deleted because it is not selected');
+
+selection_test(
+    [
+      '<div contenteditable>Test\u200B|<span></span></div>',
+    ],
+    selection => {
+      const document = selection.document;
+      document.execCommand('delete');
+      document.execCommand('undo');
+      // The selection is selected on macOS, and other platform are not.
+      document.getSelection().removeAllRanges();
+    },
+    [
+      '<div contenteditable>Test\u200B<span></span></div>',
+    ], 'The undo command works as expected');
+
+selection_test(
+    [
+      '<div contenteditable>Test\u200B|<span></span></div>',
+    ],
+    selection => {
+      const document = selection.document;
+      document.execCommand('delete');
+      document.execCommand('undo');
+      document.execCommand('redo');
+    },
+    [
+      '<div contenteditable>Test|<span></span></div>',
+    ], 'The redo command works as expected');
+
+selection_test(
+  [
+    '<div contenteditable>Test\u200B<span>|</span></div>',
+  ],
+  'delete',
+  [
+    '<div contenteditable>Test|</div>',
+  ], 'The span node is deleted because it is fully selected');
+
+selection_test(
+    [
+      '<div contenteditable>Test\u200B<span>|1</span></div>',
+    ],
+    'delete',
+    [
+      '<div contenteditable>Test|<span>1</span></div>',
+    ], 'The span node with text is not deleted because it is not fully selected');
+</script>
diff --git a/third_party/blink/web_tests/editing/input/edit-context.html b/third_party/blink/web_tests/editing/input/edit-context.html
index ff97b4eab..eca41ba5 100644
--- a/third_party/blink/web_tests/editing/input/edit-context.html
+++ b/third_party/blink/web_tests/editing/input/edit-context.html
@@ -720,12 +720,17 @@
   const kEditContextTextFormatUpdateAddListener = 5552;
   const kEditContextTextFormatUpdateFireEvent = 5553;
   const kEditContextTextFormatUpdateTextFormatThicknessOrStyleNotNone = 5554;
+  const kEditContextTextFormatUnderlineStyle = 5558;
+  const kEditContextTextFormatUnderlineThickness = 5559;
   internals.clearUseCounter(document, kEditContextTextFormatUpdateAddListener);
   internals.clearUseCounter(document, kEditContextTextFormatUpdateFireEvent);
   internals.clearUseCounter(document, kEditContextTextFormatUpdateTextFormatThicknessOrStyleNotNone);
+  internals.clearUseCounter(document, kEditContextTextFormatUnderlineStyle);
+  internals.clearUseCounter(document, kEditContextTextFormatUnderlineThickness);
 
   const editContext = new EditContext();
   const test = document.createElement("div");
+  let textFormats = [];
   document.body.appendChild(test);
   test.editContext = editContext;
   test.focus();
@@ -733,9 +738,9 @@
 
   assert_false(internals.isUseCounted(document, kEditContextTextFormatUpdateAddListener));
   assert_false(internals.isUseCounted(document, kEditContextTextFormatUpdateFireEvent));
-
-  editContext.addEventListener("textformatupdate", e => {});
-
+  editContext.addEventListener("textformatupdate", e => {
+    textFormats = e.getTextFormats();
+  });
   assert_true(internals.isUseCounted(document, kEditContextTextFormatUpdateAddListener));
   assert_false(internals.isUseCounted(document, kEditContextTextFormatUpdateFireEvent));
 
@@ -743,6 +748,14 @@
 
   assert_true(internals.isUseCounted(document, kEditContextTextFormatUpdateFireEvent));
   assert_true(internals.isUseCounted(document, kEditContextTextFormatUpdateTextFormatThicknessOrStyleNotNone));
+  assert_false(internals.isUseCounted(document, kEditContextTextFormatUnderlineStyle));
+  assert_false(internals.isUseCounted(document, kEditContextTextFormatUnderlineThickness));
+
+  assert_equals(textFormats.length, 1);
+  assert_equals(textFormats[0].underlineStyle, "Solid");
+  assert_equals(textFormats[0].underlineThickness, "Thin");
+  assert_true(internals.isUseCounted(document, kEditContextTextFormatUnderlineStyle));
+  assert_true(internals.isUseCounted(document, kEditContextTextFormatUnderlineThickness));
 
   test.remove();
 }, 'Testing UseCounter for textformatupdate event.');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index-ref.html
new file mode 100644
index 0000000..7325685
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<title>CSS Test Reference</title>
+<style>
+  body {
+    background-position: top left;
+    background-repeat: no-repeat;
+    background-size: 100px 100px;
+    background-image: linear-gradient(blue 40px, yellow);
+  }
+</style>
+<body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index.html b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index.html
new file mode 100644
index 0000000..299b86d
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-body-sibling-index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<title>CSS Images Test: Linear gradient with sibling-index()</title>
+<link rel="help" href="https://drafts.csswg.org/css-images/#linear-gradients">
+<link rel="help" href="https://drafts.csswg.org/css-values-5/#tree-counting">
+<link rel="match" href="linear-gradient-body-sibling-index-ref.html">
+<link rel="assert" content"sibling-index() is 2 for body">
+<style>
+  body {
+    background-position: top left;
+    background-repeat: no-repeat;
+    background-size: 100px 100px;
+    background-image: linear-gradient(blue calc(20px * sibling-index()), yellow);
+  }
+</style>
+<body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index-ref.html b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index-ref.html
new file mode 100644
index 0000000..eea8518
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index-ref.html
@@ -0,0 +1,7 @@
+<!DOCTYPE html>
+<title>CSS Test Reference</title>
+<style>
+  div { width: 100px; height: 100px; }
+</style>
+<div style="background: linear-gradient(blue 20px, yellow)"></div>
+<div style="background: linear-gradient(blue 50px, yellow)"></div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index.html b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index.html
new file mode 100644
index 0000000..b92897e
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-images/linear-gradient-sibling-index.html
@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<title>CSS Images Test: Linear gradient with sibling-index()</title>
+<link rel="help" href="https://drafts.csswg.org/css-images/#linear-gradients">
+<link rel="help" href="https://drafts.csswg.org/css-values-5/#tree-counting">
+<link rel="match" href="linear-gradient-sibling-index-ref.html">
+<style>
+  .grad {
+    width: 100px;
+    height: 100px;
+    background: linear-gradient(blue calc(10px * sibling-index()), yellow);
+  }
+</style>
+<div>
+  <div></div>
+  <div class="grad"></div>
+  <div></div>
+  <div></div>
+  <div class="grad"></div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-descriptors.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-descriptors.tentative.html
index d31d4acf..4987eff9 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-descriptors.tentative.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-values/tree-counting/sibling-function-descriptors.tentative.html
@@ -17,11 +17,15 @@
     font-family: my-font;
     font-weight: 300;
     font-weight: calc(max(0 * sibling-index(), 400));
+    font-feature-settings: "vert" 2;
+    font-feature-settings: "vert" calc(max(sibling-index(), 1));
   }
   @font-face {
     font-family: my-font;
     font-weight: 300;
     font-weight: calc(max(0 * sibling-count(), 400));
+    font-feature-settings: "vert" 2;
+    font-feature-settings: "vert" calc(max(sibling-count(), 1));
   }
 </style>
 <script>
@@ -37,9 +41,11 @@
 
   test(() => {
     assert_equals(rules[2].style.fontWeight, "300");
+    assert_equals(rules[2].style.fontFeatureSettings, "\"vert\" 2");
   }, "sibling-index() should not be allowed in @font-face descriptors");
 
   test(() => {
     assert_equals(rules[3].style.fontWeight, "300");
+    assert_equals(rules[3].style.fontFeatureSettings, "\"vert\" 2");
   }, "sibling-count() should not be allowed in @font-face descriptors");
 </script>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/resources/integrity-policy-worker.php b/third_party/blink/web_tests/http/tests/serviceworker/resources/integrity-policy-worker.php
new file mode 100644
index 0000000..2969df1
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/serviceworker/resources/integrity-policy-worker.php
@@ -0,0 +1,5 @@
+<?php
+require_once '../../resources/portabilityLayer.php';
+header('Integrity-Policy: blocked-destinations=(script)');
+header('Content-Type: application/javascript');
+?>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/usecounter.html b/third_party/blink/web_tests/http/tests/serviceworker/usecounter.html
index 600c518..13fc11da 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/usecounter.html
+++ b/third_party/blink/web_tests/http/tests/serviceworker/usecounter.html
@@ -289,6 +289,22 @@
   assert_true(isUseCounted(win, kServiceWorkerFrameType));
 }, 'Client.frameType is counted');
 
+promise_test(async t => {
+  const kIntegrityPolicyInServiceWorkerResponse = 5557;  // from web_feature.mojom
+  const kUrl = 'resources/integrity-policy-worker.php';
+  const kScope = 'resources/usecounter-window.html?integrityPolicy';
+
+  const registration =
+      await service_worker_unregister_and_register(t, kUrl, kScope);
+  add_result_callback(() => registration.unregister());
+  const worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+
+  const win = await openWindow(kScope);
+  await observeUseCounter(win, kIntegrityPolicyInServiceWorkerResponse);
+  assert_true(isUseCounted(win, kIntegrityPolicyInServiceWorkerResponse));
+}, 'Integrity-Policy is counted');
+
 // TODO(nhiroki): Test a case where ServiceWorker controls SharedWorker that is
 // connected from multiple windows. In such a case, API use on ServiceWorker
 // should be propagated to all connecting windows via SharedWorker.
diff --git a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
index eaab99e..cdf8796 100644
--- a/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
+++ b/third_party/blink/web_tests/platform/win/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
diff --git a/third_party/blink/web_tests/platform/win11-arm64/fast/ruby/base-shorter-than-text-expected.png b/third_party/blink/web_tests/platform/win11-arm64/fast/ruby/base-shorter-than-text-expected.png
index 6b60b7a4..98ebe20 100644
--- a/third_party/blink/web_tests/platform/win11-arm64/fast/ruby/base-shorter-than-text-expected.png
+++ b/third_party/blink/web_tests/platform/win11-arm64/fast/ruby/base-shorter-than-text-expected.png
Binary files differ
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 d9f0605..bce2e54c 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
@@ -5730,6 +5730,7 @@
     getter onquotaoverflow
     getter temperature
     getter topK
+    method append
     method clone
     method constructor
     method destroy
diff --git a/third_party/blink/web_tests/wpt_internal/subresource-integrity/integrity-policy-isolated-world.https.html b/third_party/blink/web_tests/wpt_internal/subresource-integrity/integrity-policy-isolated-world.https.html
new file mode 100644
index 0000000..3110b5b
--- /dev/null
+++ b/third_party/blink/web_tests/wpt_internal/subresource-integrity/integrity-policy-isolated-world.https.html
@@ -0,0 +1,39 @@
+<!doctype html>
+<meta name="timeout" content="long">
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/dispatcher/dispatcher.js"></script>
+<script src="/common/utils.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="/reporting/resources/report-helper.js"></script>
+
+<body>
+<script>
+
+  promise_test(async () => {
+    const {ORIGIN} = get_host_info();
+    const REMOTE_EXECUTOR =
+      `/common/dispatcher/remote-executor.html?pipe=`;
+    const iframe_uuid = token();
+
+    let header =
+      `header(Integrity-Policy,blocked-destinations=\\(script\\)\\, endpoints=\\(integrity-endpoint-1 integrity-endpoint-2\\))`;
+    const iframe_url = `${REMOTE_EXECUTOR}${encodeURIComponent(header)}&uuid=${iframe_uuid}`;
+
+    const iframe = document.createElement('iframe');
+    iframe.src = iframe_url;
+    document.body.appendChild(iframe);
+
+    // Execute code directly from the iframe.
+    const ctx = new RemoteContext(iframe_uuid);
+    const result = await ctx.execute_script(async (ORIGIN) => {
+      const isolatedWorldId = 1;
+      const value = await testRunner.evaluateScriptInIsolatedWorldAndReturnValue(
+          isolatedWorldId,
+          String(`(async()=>{window.ran = false;await import('${ORIGIN}/content-security-policy/resources/ran.js');return window.ran;})()`));
+      return value;
+    }, [ORIGIN]);
+    assert_true(result);
+  }, "Extension based fetch is not blocked by Integrity-Policy");
+</script>
+
diff --git a/third_party/boringssl/src b/third_party/boringssl/src
index f371c85..45cab55 160000
--- a/third_party/boringssl/src
+++ b/third_party/boringssl/src
@@ -1 +1 @@
-Subproject commit f371c85a8d58bf911cba6073bcca6d497af81dc9
+Subproject commit 45cab558a838e1a546391406e7cbe1eec9b6e643
diff --git a/third_party/catapult b/third_party/catapult
index 74f545d..168822b 160000
--- a/third_party/catapult
+++ b/third_party/catapult
@@ -1 +1 @@
-Subproject commit 74f545d009ceef464f840938ae079ffbc112a102
+Subproject commit 168822b896c38f7d0079a2483c81f3d5cbc1d933
diff --git a/third_party/dawn b/third_party/dawn
index 19a7153..52a8b5a6 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit 19a7153574fe7506f098586a12ac21edf0944849
+Subproject commit 52a8b5a67e5c425a174cd6874a13b8b11fe190af
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index 6d3155a..a35ef62 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit 6d3155a3c0b50687e4f417e19d4491e66d56ef3c
+Subproject commit a35ef623edc69b2863da7b1fd596b64160ff73f9
diff --git a/third_party/libunwind/src b/third_party/libunwind/src
index 81e2cb4..4acde98 160000
--- a/third_party/libunwind/src
+++ b/third_party/libunwind/src
@@ -1 +1 @@
-Subproject commit 81e2cb40a70de2b6978e6d8658891ded9a77f7e3
+Subproject commit 4acde988c52e6a325e3ce2ac761284f295f2ab39
diff --git a/third_party/liburlpattern/BUILD.gn b/third_party/liburlpattern/BUILD.gn
index 74cc405..f68354922 100644
--- a/third_party/liburlpattern/BUILD.gn
+++ b/third_party/liburlpattern/BUILD.gn
@@ -26,6 +26,8 @@
     "options.h",
     "parse.cc",
     "parse.h",
+    "part.cc",
+    "part.h",
     "pattern.cc",
     "pattern.h",
     "tokenize.cc",
diff --git a/third_party/liburlpattern/part.cc b/third_party/liburlpattern/part.cc
new file mode 100644
index 0000000..0f406698
--- /dev/null
+++ b/third_party/liburlpattern/part.cc
@@ -0,0 +1,55 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/liburlpattern/part.h"
+
+#include <cctype>
+#include <ostream>
+#include <string>
+
+#include "third_party/abseil-cpp/absl/base/macros.h"
+
+namespace liburlpattern {
+
+std::ostream& operator<<(std::ostream& o, const Part& part) {
+  o << "{ type:" << static_cast<int>(part.type) << ", name:" << part.name
+    << ", prefix:" << part.prefix << ", value:" << part.value
+    << ", suffix:" << part.suffix
+    << ", modifier:" << static_cast<int>(part.modifier) << " }";
+  return o;
+}
+
+Part::Part(PartType t, std::string v, Modifier m)
+    : type(t), value(std::move(v)), modifier(m) {
+  ABSL_ASSERT(type == PartType::kFixed);
+}
+
+Part::Part(PartType t,
+           std::string n,
+           std::string p,
+           std::string v,
+           std::string s,
+           Modifier m)
+    : type(t),
+      name(std::move(n)),
+      prefix(std::move(p)),
+      value(std::move(v)),
+      suffix(std::move(s)),
+      modifier(m) {
+  ABSL_ASSERT(type != PartType::kFixed);
+  ABSL_ASSERT(!name.empty());
+  if (type == PartType::kFullWildcard || type == PartType::kSegmentWildcard) {
+    ABSL_ASSERT(value.empty());
+  }
+}
+
+bool Part::HasCustomName() const {
+  // Determine if the part name was custom, like `:foo`, or an
+  // automatically assigned numeric value.  Since custom group
+  // names follow javascript identifier rules the first character
+  // cannot be a digit, so that is all we need to check here.
+  return !name.empty() && !std::isdigit(name[0]);
+}
+
+}  // namespace liburlpattern
diff --git a/third_party/liburlpattern/part.h b/third_party/liburlpattern/part.h
new file mode 100644
index 0000000..521dc04
--- /dev/null
+++ b/third_party/liburlpattern/part.h
@@ -0,0 +1,106 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_LIBURLPATTERN_PART_H_
+#define THIRD_PARTY_LIBURLPATTERN_PART_H_
+
+#include <ostream>
+#include <string>
+
+#include "base/component_export.h"
+
+namespace liburlpattern {
+
+// Numeric values are set such that more restrictive values come last.  This
+// is important for comparison routines in calling code, like URLPattern.
+enum class PartType {
+  // A part that matches any character to the end of the input string.
+  kFullWildcard = 0,
+
+  // A part that matches any character to the next segment separator.
+  kSegmentWildcard = 1,
+
+  // A part with a custom regular expression.
+  kRegex = 2,
+
+  // A fixed, non-variable part of the pattern.  Consists of kChar and
+  // kEscapedChar Tokens.
+  kFixed = 3,
+};
+
+// Numeric values are set such that more restrictive values come last.  This
+// is important for comparison routines in calling code, like URLPattern.
+enum class Modifier {
+  // The `*` modifier.
+  kZeroOrMore = 0,
+
+  // The `?` modifier.
+  kOptional = 1,
+
+  // The `+` modifier.
+  kOneOrMore = 2,
+
+  // No modifier.
+  kNone = 3,
+};
+
+// A structure representing one part of a parsed Pattern.  A full Pattern
+// consists of an ordered sequence of Part objects.
+struct COMPONENT_EXPORT(LIBURLPATTERN) Part {
+  // The type of the Part.
+  PartType type = PartType::kFixed;
+
+  // The name of the Part.  Only kRegex, kSegmentWildcard, and kFullWildcard
+  // parts may have a |name|.  kFixed parts must have an empty |name|.
+  std::string name;
+
+  // A fixed string prefix that is expected before any regex or wildcard match.
+  // kFixed parts must have an empty |prefix|.
+  std::string prefix;
+
+  // The meaning of the |value| depends on the |type| of the Part.  For kFixed
+  // parts the |value| contains the fixed string to match.  For kRegex parts
+  // the |value| contains a regular expression to match.  The |value| is empty
+  // for kSegmentWildcard and kFullWildcard parts since the |type| encodes what
+  // to match.
+  std::string value;
+
+  // A fixed string prefix that is expected after any regex or wildcard match.
+  // kFixed parts must have an empty |suffix|.
+  std::string suffix;
+
+  // A |modifier| indicating whether the Part is optional and/or repeated.  Any
+  // Part type may have a |modifier|.
+  Modifier modifier = Modifier::kNone;
+
+  Part(PartType type, std::string value, Modifier modifier);
+  Part(PartType type,
+       std::string name,
+       std::string prefix,
+       std::string value,
+       std::string suffix,
+       Modifier modifier);
+  Part() = default;
+
+  // Returns true if the `name` member is a custom name; e.g. for a `:foo`
+  // group.
+  bool HasCustomName() const;
+};
+
+COMPONENT_EXPORT(LIBURLPATTERN)
+inline bool operator==(const Part& lh, const Part& rh) {
+  return lh.name == rh.name && lh.prefix == rh.prefix && lh.value == rh.value &&
+         lh.suffix == rh.suffix && lh.modifier == rh.modifier;
+}
+
+inline bool operator!=(const Part& lh, const Part& rh) {
+  return !(lh == rh);
+}
+
+COMPONENT_EXPORT(LIBURLPATTERN)
+std::ostream& operator<<(std::ostream& o, const Part& part);
+
+}  // namespace liburlpattern
+
+#endif  // THIRD_PARTY_LIBURLPATTERN_PART_H_
diff --git a/third_party/liburlpattern/pattern.cc b/third_party/liburlpattern/pattern.cc
index d8f1b29..89354fc 100644
--- a/third_party/liburlpattern/pattern.cc
+++ b/third_party/liburlpattern/pattern.cc
@@ -6,6 +6,7 @@
 #include "third_party/liburlpattern/pattern.h"
 
 #include <optional>
+#include <string>
 #include <string_view>
 
 #include "third_party/abseil-cpp/absl/base/macros.h"
@@ -46,45 +47,6 @@
 
 }  // namespace
 
-std::ostream& operator<<(std::ostream& o, Part part) {
-  o << "{ type:" << static_cast<int>(part.type) << ", name:" << part.name
-    << ", prefix:" << part.prefix << ", value:" << part.value
-    << ", suffix:" << part.suffix
-    << ", modifier:" << static_cast<int>(part.modifier) << " }";
-  return o;
-}
-
-Part::Part(PartType t, std::string v, Modifier m)
-    : type(t), value(std::move(v)), modifier(m) {
-  ABSL_ASSERT(type == PartType::kFixed);
-}
-
-Part::Part(PartType t,
-           std::string n,
-           std::string p,
-           std::string v,
-           std::string s,
-           Modifier m)
-    : type(t),
-      name(std::move(n)),
-      prefix(std::move(p)),
-      value(std::move(v)),
-      suffix(std::move(s)),
-      modifier(m) {
-  ABSL_ASSERT(type != PartType::kFixed);
-  ABSL_ASSERT(!name.empty());
-  if (type == PartType::kFullWildcard || type == PartType::kSegmentWildcard)
-    ABSL_ASSERT(value.empty());
-}
-
-bool Part::HasCustomName() const {
-  // Determine if the part name was custom, like `:foo`, or an
-  // automatically assigned numeric value.  Since custom group
-  // names follow javascript identifier rules the first character
-  // cannot be a digit, so that is all we need to check here.
-  return !name.empty() && !std::isdigit(name[0]);
-}
-
 Pattern::Pattern(std::vector<Part> part_list,
                  Options options,
                  std::string segment_wildcard_regex)
diff --git a/third_party/liburlpattern/pattern.h b/third_party/liburlpattern/pattern.h
index 6e91b90..7bd1c5fb 100644
--- a/third_party/liburlpattern/pattern.h
+++ b/third_party/liburlpattern/pattern.h
@@ -14,98 +14,10 @@
 
 #include "base/component_export.h"
 #include "third_party/liburlpattern/options.h"
+#include "third_party/liburlpattern/part.h"
 
 namespace liburlpattern {
 
-// Numeric values are set such that more restrictive values come last.  This
-// is important for comparison routines in calling code, like URLPattern.
-enum class PartType {
-  // A part that matches any character to the end of the input string.
-  kFullWildcard = 0,
-
-  // A part that matches any character to the next segment separator.
-  kSegmentWildcard = 1,
-
-  // A part with a custom regular expression.
-  kRegex = 2,
-
-  // A fixed, non-variable part of the pattern.  Consists of kChar and
-  // kEscapedChar Tokens.
-  kFixed = 3,
-};
-
-// Numeric values are set such that more restrictive values come last.  This
-// is important for comparison routines in calling code, like URLPattern.
-enum class Modifier {
-  // The `*` modifier.
-  kZeroOrMore = 0,
-
-  // The `?` modifier.
-  kOptional = 1,
-
-  // The `+` modifier.
-  kOneOrMore = 2,
-
-  // No modifier.
-  kNone = 3,
-};
-
-// A structure representing one part of a parsed Pattern.  A full Pattern
-// consists of an ordered sequence of Part objects.
-struct COMPONENT_EXPORT(LIBURLPATTERN) Part {
-  // The type of the Part.
-  PartType type = PartType::kFixed;
-
-  // The name of the Part.  Only kRegex, kSegmentWildcard, and kFullWildcard
-  // parts may have a |name|.  kFixed parts must have an empty |name|.
-  std::string name;
-
-  // A fixed string prefix that is expected before any regex or wildcard match.
-  // kFixed parts must have an empty |prefix|.
-  std::string prefix;
-
-  // The meaning of the |value| depends on the |type| of the Part.  For kFixed
-  // parts the |value| contains the fixed string to match.  For kRegex parts
-  // the |value| contains a regular expression to match.  The |value| is empty
-  // for kSegmentWildcard and kFullWildcard parts since the |type| encodes what
-  // to match.
-  std::string value;
-
-  // A fixed string prefix that is expected after any regex or wildcard match.
-  // kFixed parts must have an empty |suffix|.
-  std::string suffix;
-
-  // A |modifier| indicating whether the Part is optional and/or repeated.  Any
-  // Part type may have a |modifier|.
-  Modifier modifier = Modifier::kNone;
-
-  Part(PartType type, std::string value, Modifier modifier);
-  Part(PartType type,
-       std::string name,
-       std::string prefix,
-       std::string value,
-       std::string suffix,
-       Modifier modifier);
-  Part() = default;
-
-  // Returns true if the `name` member is a custom name; e.g. for a `:foo`
-  // group.
-  bool HasCustomName() const;
-};
-
-COMPONENT_EXPORT(LIBURLPATTERN)
-inline bool operator==(const Part& lh, const Part& rh) {
-  return lh.name == rh.name && lh.prefix == rh.prefix && lh.value == rh.value &&
-         lh.suffix == rh.suffix && lh.modifier == rh.modifier;
-}
-
-inline bool operator!=(const Part& lh, const Part& rh) {
-  return !(lh == rh);
-}
-
-COMPONENT_EXPORT(LIBURLPATTERN)
-std::ostream& operator<<(std::ostream& o, Part part);
-
 // This class represents a successfully parsed pattern string.  It will contain
 // an intermediate representation that can be used to generate either a regular
 // expression string or to directly match against input strings.  Not all
diff --git a/third_party/llvm-libc/src b/third_party/llvm-libc/src
index e3e030e..61d7ed3 160000
--- a/third_party/llvm-libc/src
+++ b/third_party/llvm-libc/src
@@ -1 +1 @@
-Subproject commit e3e030ec6ee1674bf2195d0cfd0a4bf5fee16537
+Subproject commit 61d7ed30110f97d6842304bc9035ee9cdae6b5e5
diff --git a/third_party/skia b/third_party/skia
index 0d16b74..84e461a 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit 0d16b74f74a5018c20fdaa753b41103bb08d08fd
+Subproject commit 84e461a91558ab09fa70d1c8076d08ac5348bb86
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index 9d02147..72604f0 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit 9d021471f38e15ccd4d7087f4cf05292e6e671b0
+Subproject commit 72604f04b9576fcda814d388673d7530d95a9a5a
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 17cf818..6ae58a2 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 17cf8188d8b49bafb6c2f8ecede238f8d2dec5bf
+Subproject commit 6ae58a2b17b2bcebdc5377995007391b85ffa10f
diff --git a/tools/metrics/histograms/metadata/blink/enums.xml b/tools/metrics/histograms/metadata/blink/enums.xml
index ac59ea0a..39b194d 100644
--- a/tools/metrics/histograms/metadata/blink/enums.xml
+++ b/tools/metrics/histograms/metadata/blink/enums.xml
@@ -6181,6 +6181,10 @@
   <int value="5554"
       label="EditContextTextFormatUpdateTextFormatThicknessOrStyleNotNone"/>
   <int value="5555" label="C2PAManifest"/>
+  <int value="5556" label="LanguageModel_Append"/>
+  <int value="5557" label="IntegrityPolicyInServiceWorkerResponse"/>
+  <int value="5558" label="EditContextTextFormatUnderlineStyle"/>
+  <int value="5559" label="EditContextTextFormatUnderlineThickness"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/web_feature.mojom:WebFeature) -->
@@ -8199,6 +8203,7 @@
   <int value="333" label="Requestclose"/>
   <int value="334" label="Uint8arrayBase64Hex"/>
   <int value="335" label="LineBreak"/>
+  <int value="336" label="OverflowClip"/>
 </enum>
 
 <!-- LINT.ThenChange(//third_party/blink/public/mojom/use_counter/metrics/webdx_feature.mojom:WebDXFeature) -->
diff --git a/tools/metrics/histograms/metadata/web_rtc/enums.xml b/tools/metrics/histograms/metadata/web_rtc/enums.xml
index 9e46441..5a05346 100644
--- a/tools/metrics/histograms/metadata/web_rtc/enums.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/enums.xml
@@ -208,6 +208,11 @@
   <int value="12" label="SetPreferredSinkId"/>
 </enum>
 
+<enum name="SdpMungingOutcome">
+  <int value="0" label="Accepted"/>
+  <int value="1" label="Rejected"/>
+</enum>
+
 <enum name="SdpMungingType">
   <int value="0" label="NoModification"/>
   <int value="1" label="UnknownModification"/>
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
index 90396dc..c4668a34 100644
--- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml
+++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -1513,6 +1513,32 @@
   </summary>
 </histogram>
 
+<histogram name="WebRTC.PeerConnection.SdpMunging.Outcome"
+    enum="SdpMungingOutcome" expires_after="2025-12-31">
+  <owner>hta@chromium.org</owner>
+  <owner>webrtc-dev@chromium.org</owner>
+  <summary>
+    Classifies the outcome when a local description is set; either no SDP
+    munging is detected, it is detected and rejected, or it is detected and
+    accepted. Captured for every local description that is set.
+  </summary>
+</histogram>
+
+<histogram name="WebRTC.PeerConnection.SdpMunging.SdpOutcome.{Outcome}"
+    enum="SdpMungingType" expires_after="2025-12-31">
+  <owner>hta@chromium.org</owner>
+  <owner>webrtc-dev@chromium.org</owner>
+  <summary>
+    Classifies the outcome for each SDP munging type when a local description is
+    set and SDP munging has been detected. This is either accepted or rejected.
+    Captured for every local description that is set.
+  </summary>
+  <token key="Outcome">
+    <variant name="Accepted"/>
+    <variant name="Rejected"/>
+  </token>
+</histogram>
+
 <histogram name="WebRTC.PeerConnection.SdpMunging.{DescriptionType}.{Stage}"
     enum="SdpMungingType" expires_after="2025-12-31">
   <owner>hta@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/webapps/enums.xml b/tools/metrics/histograms/metadata/webapps/enums.xml
index f4e17057..66d3206 100644
--- a/tools/metrics/histograms/metadata/webapps/enums.xml
+++ b/tools/metrics/histograms/metadata/webapps/enums.xml
@@ -327,6 +327,13 @@
   <int value="17" label="kIgnorePreviouslyUninstalledByUser"/>
 </enum>
 
+<enum name="RewriteIconResult">
+  <int value="0" label="The app's state was changed unexpectedly"/>
+  <int value="1" label="Icon successfully rewritten with mask"/>
+  <int value="2" label="Failed to fetch shortcut info"/>
+  <int value="3" label="Failed to update shortcuts"/>
+</enum>
+
 <enum name="RunOnOSLoginCommandCompletionState">
   <int value="0" label="Run On OS Login command successfully completed"/>
   <int value="1"
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml
index 19d337d..d623619 100644
--- a/tools/metrics/histograms/metadata/webapps/histograms.xml
+++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -469,6 +469,19 @@
   </summary>
 </histogram>
 
+<histogram name="WebApp.DIY.IconMigrationResult" enum="RewriteIconResult"
+    expires_after="2026-04-17">
+  <owner>dmurph@chromium.org</owner>
+  <owner>dibyapal@chromium.org</owner>
+  <owner>pwa-team@google.com</owner>
+  <summary>
+    Records the result of rewriting DIY app icon for apps that need icon
+    migration due to https://crbug.com/372688523. This is logged after the
+    RewriteDiyIconsCommand command completes, which occurs on a best-effort task
+    runner, 1 minutes after profile startup.
+  </summary>
+</histogram>
+
 <histogram name="WebApp.DiyAppsInstalledCount.ByUser" units="count"
     expires_after="2026-03-21">
   <owner>dibyapal@chromium.org</owner>
diff --git a/ui/android/java/res/values/semantic_colors_non_adaptive.xml b/ui/android/java/res/values/semantic_colors_non_adaptive.xml
index 74795b3..6f91282c 100644
--- a/ui/android/java/res/values/semantic_colors_non_adaptive.xml
+++ b/ui/android/java/res/values/semantic_colors_non_adaptive.xml
@@ -153,6 +153,7 @@
 
     <!-- Snackbar colors -->
     <color name="snackbar_background_color_baseline_dark">@color/baseline_neutral_10_with_surface_tint_dark_alpha_12</color>
+    <color name="floating_snackbar_background_incognito">@color/gm3_baseline_surface_container_high_dark</color>
 
     <!-- Rating star colors -->
     <color name="rating_star_yellow_dark">@color/modern_yellow_500</color>
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index 92f2c53..328028f 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -91,7 +91,6 @@
 const char kPakFileExtension[] = ".pak";
 #endif
 
-#if BUILDFLAG(IS_CHROMEOS)
 // Pointers to the functions |lottie::ParseLottieAsStillImage| and
 // |lottie::ParseLottieAsThemedStillImage|, so that dependencies used by those
 // functions do not need to be included directly in ui/base.
@@ -99,7 +98,6 @@
     nullptr;
 ResourceBundle::LottieThemedImageParseFunction
     g_parse_lottie_as_themed_still_image_ = nullptr;
-#endif
 
 ResourceBundle* g_shared_instance_ = nullptr;
 
@@ -353,7 +351,6 @@
   return *g_shared_instance_;
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
 // static
 void ResourceBundle::SetLottieParsingFunctions(
     LottieImageParseFunction parse_lottie_as_still_image,
@@ -361,7 +358,6 @@
   g_parse_lottie_as_still_image_ = parse_lottie_as_still_image;
   g_parse_lottie_as_themed_still_image_ = parse_lottie_as_themed_still_image;
 }
-#endif
 
 void ResourceBundle::LoadSecondaryLocaleDataWithPakFileRegion(
     base::File pak_file,
@@ -623,7 +619,6 @@
   return result;
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
 const ui::ImageModel& ResourceBundle::GetThemedLottieImageNamed(
     int resource_id) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -643,7 +638,6 @@
   DCHECK(inserted.second);
   return inserted.first->second;
 }
-#endif
 
 constexpr uint8_t ResourceBundle::kBrotliConst[];
 
@@ -1071,11 +1065,13 @@
 
 gfx::ImageSkia ResourceBundle::CreateImageSkia(int resource_id) {
   DCHECK(!resource_handles_.empty()) << "Missing call to SetResourcesDataDLL?";
-#if BUILDFLAG(IS_CHROMEOS)
+
   std::optional<LottieData> data = GetLottieData(resource_id);
   if (data) {
     return (*g_parse_lottie_as_still_image_)(std::move(*data));
   }
+
+#if BUILDFLAG(IS_CHROMEOS)
   const ResourceScaleFactor scale_factor_to_load = GetMaxResourceScaleFactor();
 #elif BUILDFLAG(IS_WIN)
   const ResourceScaleFactor scale_factor_to_load =
@@ -1084,6 +1080,7 @@
 #else
   const ResourceScaleFactor scale_factor_to_load = ui::k100Percent;
 #endif
+
   // TODO(oshima): Consider reading the image size from png IHDR chunk and
   // skip decoding here and remove #ifdef below.
   // |ResourceBundle::GetSharedInstance()| is destroyed after the
diff --git a/ui/base/resource/resource_bundle.h b/ui/base/resource/resource_bundle.h
index 5c91532..94f30ddf83 100644
--- a/ui/base/resource/resource_bundle.h
+++ b/ui/base/resource/resource_bundle.h
@@ -23,14 +23,11 @@
 #include "base/memory/raw_ptr.h"
 #include "base/sequence_checker.h"
 #include "build/build_config.h"
+#include "ui/base/models/image_model.h"
 #include "ui/base/resource/resource_scale_factor.h"
 #include "ui/gfx/font_list.h"
 #include "ui/gfx/image/image.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "ui/base/models/image_model.h"
-#endif
-
 class SkBitmap;
 
 namespace base {
@@ -160,10 +157,8 @@
   };
 
   using LottieData = std::vector<uint8_t>;
-#if BUILDFLAG(IS_CHROMEOS)
   using LottieImageParseFunction = gfx::ImageSkia (*)(LottieData);
   using LottieThemedImageParseFunction = ui::ImageModel (*)(LottieData);
-#endif
 
   // Initialize the ResourceBundle for this process. Does not take ownership of
   // the |delegate| value. Returns the language selected or an empty string if
@@ -211,11 +206,11 @@
   // Return the global resource loader instance.
   static ResourceBundle& GetSharedInstance();
 
-#if BUILDFLAG(IS_CHROMEOS)
+  // TODO(crbug.com/415384540): Simplify the injection after enabling lottie
+  // on all platforms.
   static void SetLottieParsingFunctions(
       LottieImageParseFunction parse_lottie_as_still_image,
       LottieThemedImageParseFunction parse_lottie_as_themed_still_image);
-#endif
 
   // Exposed for testing, otherwise use GetSharedInstance().
   explicit ResourceBundle(Delegate* delegate);
@@ -292,11 +287,9 @@
   // `SkottieWrapper`.
   std::optional<LottieData> GetLottieData(int resource_id) const;
 
-#if BUILDFLAG(IS_CHROMEOS)
   // Gets a themed Lottie image (not animated) with the specified |resource_id|
   // from the current module data. |ResourceBundle| owns the result.
   const ui::ImageModel& GetThemedLottieImageNamed(int resource_id);
-#endif
 
   // Returns true if LoadDataResourceBytes would return non-null data for the
   // specified |resource_id|.
@@ -510,9 +503,7 @@
   // Returns an empty image for when a resource cannot be loaded. This is a
   // bright red bitmap.
   gfx::Image& GetEmptyImage();
-#if BUILDFLAG(IS_CHROMEOS)
   const ui::ImageModel& GetEmptyImageModel();
-#endif
 
   const base::FilePath& GetOverriddenPakPath() const;
 
@@ -547,15 +538,11 @@
   // ownership of the pointers.
   using ImageMap = std::map<int, gfx::Image>;
   ImageMap images_;
-#if BUILDFLAG(IS_CHROMEOS)
   using ImageModelMap = std::map<int, ui::ImageModel>;
   ImageModelMap image_models_;
-#endif
 
   gfx::Image empty_image_;
-#if BUILDFLAG(IS_CHROMEOS)
   ui::ImageModel empty_image_model_;
-#endif
 
   // The various font lists used, as a map from a signed size delta from the
   // platform base font size, plus style, to the FontList. Cached to avoid
diff --git a/ui/base/resource/resource_bundle_unittest.cc b/ui/base/resource/resource_bundle_unittest.cc
index 67d2d70..0ef4fc0 100644
--- a/ui/base/resource/resource_bundle_unittest.cc
+++ b/ui/base/resource/resource_bundle_unittest.cc
@@ -72,7 +72,6 @@
 // The contents after the prefix has been removed.
 constexpr uint8_t kLottieExpected[] = {'t', 'e', 's', 't'};
 
-#if BUILDFLAG(IS_CHROMEOS)
 // Mock of |lottie::ParseLottieAsStillImage|. Checks that |kLottieData| is
 // properly stripped of the "LOTTIE" prefix.
 gfx::ImageSkia ParseLottieAsStillImageForTesting(std::vector<uint8_t> data) {
@@ -82,7 +81,6 @@
   return gfx::ImageSkia(
       gfx::ImageSkiaRep(gfx::Size(kDimension, kDimension), 0.f));
 }
-#endif
 
 // Returns |bitmap_data| with |custom_chunk| inserted after the IHDR chunk.
 void AddCustomChunk(std::string_view custom_chunk,
@@ -722,7 +720,6 @@
   ASSERT_TRUE(data.has_value());
   EXPECT_TRUE(std::ranges::equal(*data, kLottieExpected));
 
-#if BUILDFLAG(IS_CHROMEOS)
   ui::ResourceBundle::SetLottieParsingFunctions(
       &ParseLottieAsStillImageForTesting,
       /*parse_lottie_as_themed_still_image=*/nullptr);
@@ -738,7 +735,6 @@
 
   // Lottie resource should be 'unscaled'.
   EXPECT_TRUE(image_skia->image_reps()[0].unscaled());
-#endif
 }
 
 }  // namespace ui
diff --git a/ui/lottie/BUILD.gn b/ui/lottie/BUILD.gn
index 116c35f..08493bf 100644
--- a/ui/lottie/BUILD.gn
+++ b/ui/lottie/BUILD.gn
@@ -18,13 +18,8 @@
   deps = [
     "//base",
     "//cc/paint",
+    "//ui/base",
+    "//ui/color",
     "//ui/gfx",
   ]
-
-  if (is_chromeos) {
-    deps += [
-      "//ui/base",
-      "//ui/color",
-    ]
-  }
 }
diff --git a/ui/lottie/resource.cc b/ui/lottie/resource.cc
index 0724ad32..6bd75263 100644
--- a/ui/lottie/resource.cc
+++ b/ui/lottie/resource.cc
@@ -15,6 +15,9 @@
 #include "cc/paint/skottie_color_map.h"
 #include "cc/paint/skottie_wrapper.h"
 #include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/models/image_model.h"
+#include "ui/color/color_id.h"
+#include "ui/color/color_provider.h"
 #include "ui/gfx/canvas.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/image/image_skia.h"
@@ -22,12 +25,6 @@
 #include "ui/gfx/image/image_skia_source.h"
 #include "ui/lottie/animation.h"
 
-#if BUILDFLAG(IS_CHROMEOS)
-#include "ui/base/models/image_model.h"  // nogncheck
-#include "ui/color/color_id.h"           // nogncheck
-#include "ui/color/color_provider.h"     // nogncheck
-#endif
-
 namespace lottie {
 
 namespace {
@@ -67,9 +64,9 @@
                         rep.pixel_size());
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
 // Creates a |cc::SkottieColorMap| with theme colors from a |ui::ColorProvider|.
 cc::SkottieColorMap CreateColorMap(const ui::ColorProvider* color_provider) {
+#if BUILDFLAG(IS_CHROMEOS)
   return {
       cc::SkottieMapColor("cros.sys.illo.color1",
                           color_provider->GetColor(ui::kColorNativeColor1)),
@@ -134,6 +131,10 @@
       cc::SkottieMapColor(
           "_CrOS_SecondaryColor",
           color_provider->GetColor(ui::kColorNativeSecondaryColor))};
+#else
+  // TODO(crbug.com/414416729): Add color mapping for other platform.
+  return {};
+#endif
 }
 
 // Used for a |ui::ImageModel::ImageGenerator|.
@@ -145,7 +146,6 @@
       CreateColorMap(color_provider));
   return CreateImageSkia(content.get());
 }
-#endif
 
 }  // namespace
 
@@ -155,7 +155,6 @@
   return CreateImageSkia(content.get());
 }
 
-#if BUILDFLAG(IS_CHROMEOS)
 ui::ImageModel ParseLottieAsThemedStillImage(std::vector<uint8_t> data) {
   const gfx::Size size = std::make_unique<Animation>(
                              cc::SkottieWrapper::UnsafeCreateSerializable(data))
@@ -164,6 +163,5 @@
       base::BindRepeating(&CreateImageSkiaWithCurrentTheme, std::move(data)),
       size);
 }
-#endif
 
 }  // namespace lottie
diff --git a/ui/lottie/resource.h b/ui/lottie/resource.h
index f18bb6b..9b5a9bc 100644
--- a/ui/lottie/resource.h
+++ b/ui/lottie/resource.h
@@ -26,13 +26,11 @@
 COMPONENT_EXPORT(UI_LOTTIE)
 gfx::ImageSkia ParseLottieAsStillImage(std::vector<uint8_t> data);
 
-#if BUILDFLAG(IS_CHROMEOS)
 // Used for loading a Lottie asset intended as a still image (not animated),
 // with support for using different colors in light mode, dark mode, and
 // "elevated" dark mode (see |views::Widget::InitParams::background_elevation|).
 COMPONENT_EXPORT(UI_LOTTIE)
 ui::ImageModel ParseLottieAsThemedStillImage(std::vector<uint8_t> data);
-#endif  // BUILDFLAG(IS_CHROMEOS)
 
 }  // namespace lottie
 
diff --git a/v8 b/v8
index a469663..66ae14d 160000
--- a/v8
+++ b/v8
@@ -1 +1 @@
-Subproject commit a46966388bbd892ee59d5d2688287704d1844302
+Subproject commit 66ae14d8c1caeae3b2b64da4822d4f647b2d5cc7