diff --git a/DEPS b/DEPS
index b117ed1c..bf9ad791 100644
--- a/DEPS
+++ b/DEPS
@@ -306,7 +306,7 @@
   # 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': 'fb66e398427555675a4c616f184fde655a3f14e5',
+  'skia_revision': '466b248469e852daebce53871dc88295c5ecb212',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
@@ -394,7 +394,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': 'b2274b582648b9f295fb8bf1c4726eb5e0079dd9',
+  'devtools_frontend_revision': 'fa037075c43e9fcc6543d7fa001cffa58e7e0abf',
   # 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.
@@ -418,7 +418,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': 'ce4c6d59514cbba545859dc5788eb8e154c1db31',
+  'dawn_revision': '3143cb32483ee3226a4665661957650a0ab54ea7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -526,7 +526,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling llvm-libc
   # and whatever else without interference from each other.
-  'compiler_rt_revision': '361e87916c9c4822c77ea70d4723823e2b6574c1',
+  'compiler_rt_revision': 'c4d9ab5e7cf25d4a8dfe1159267036a6eb2648a4',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling clusterfuzz-data
   # and whatever else without interference from each other.
@@ -1198,7 +1198,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm',
-              'version': 'zN10Ty5me73qMcryjQMsZ7Ci5M3Nq1aTxP_Mt58plVIC',
+              'version': 'DCTUvcy0or3BCZa9h87v-BKCsUZctQByXfDEYW30VAIC',
           },
       ],
       'condition': 'checkout_android',
@@ -1209,7 +1209,7 @@
       'packages': [
           {
               'package': 'chromium/chrome/android/orderfiles/arm64',
-              'version': 'CY9jvc051YNKGvISarnDBJJjLwZQwPmU4gchx7LS-oEC',
+              'version': 'XgS9TyKJlNMRlm-h91FCRy7pIowIq_t_bqoIhVlYqZUC',
           },
       ],
       'condition': 'checkout_android',
@@ -1610,7 +1610,7 @@
 
   'src/clank': {
     'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' +
-    '2075075ba567da319b267a73482bf9d7de4b9d9a',
+    '581b055fda53c19ff49b49b0b444e8f1aeb40930',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -1831,7 +1831,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/error_prone',
-               'version': 'R8e42R2txro2We-fzwv-mCywXVgBpacnAx2ln84t9ZkC',
+               'version': '47nFaUKq3UemCr0EHmMYPJ63Y9hRnNII7iNn5zYK9qsC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -1853,7 +1853,7 @@
       'packages': [
           {
                'package': 'chromium/third_party/android_build_tools/lint',
-               'version': 'Oz9g86ZQTZl8f7FpHv7iYW2rKpIsfz6CnI0td417x3EC',
+               'version': 'KBlDDgCi2ePqd60Cg-MkB6N_YRqkgcJ0ldkVj8OW_I4C',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2341,7 +2341,7 @@
       'packages': [
           {
               'package': 'chromium/third_party/kotlin_stdlib',
-              'version': 'MM50Ron8nItK5SmgAfdy5JZXPui-jkg_Fa8DgpTM4uYC',
+              'version': 'yvQWpghyvahxBY39Wf-J0BlhSCKm66GR8qatP1sh_-IC',
           },
       ],
       'condition': 'checkout_android and non_git_source',
@@ -2957,16 +2957,16 @@
       'dep_type': 'cipd',
   },
 
-  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@e1c9d596803856d1f67833d1e1d29081e26298d1',
+  'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@dd883ffe3224c33ad5d1303764a1583bd37777d8',
   'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@3289b1d61b69a6c66c4b7cd2c6d3ab2a6df031e5',
   '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@3397e1e4fe0a9964e1837c2934b81835093494b8',
-  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@d0bcfb229123d542e9fda847bf2f3d90e8d38721',
+  'src/third_party/spirv-tools/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Tools@392b4893c4955125c1873c33a97f2a8ee8363bd3',
   'src/third_party/vulkan-headers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Headers@d1cd37e925510a167d4abef39340dbdea47d8989',
   'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@fe92c7d7e54664b1d3f3a0d734fd6f2ffd92e485',
   'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@8ce6f121d1fcbdf60f0f4264e23fbcd247b9101d',
   'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@a528f95dc2f92bdd83c0c32efe2d13c806428c9d',
-  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@20c577e6e0e90f9e531d044816c15c48f0b5f913',
+  'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@3682d20aecdb4e005cd2785a0429cc357047ad12',
 
   'src/third_party/vulkan_memory_allocator':
     Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + 'cb0597213b0fcb999caa9ed08c2f88dc45eb7d50',
@@ -3009,7 +3009,7 @@
     Var('chromium_git') + '/webpagereplay.git' + '@' + Var('webpagereplay_revision'),
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'b12e03f7671717aedaf04e598d4da88011e0542e',
+    Var('webrtc_git') + '/src.git' + '@' + '620b3a2805f198ef797bb78098883d9cf3c17604',
 
   # Wuffs' canonical repository is at github.com/google/wuffs, but we use
   # Skia's mirror of Wuffs, the same as in upstream Skia's DEPS file.
@@ -3197,7 +3197,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': 'YVnXYUrZ1snUZBMkCJkbIiATa3obPmdnMa1zTydkA1oC',
+        'version': 'uLNnvxGxQz7MfvtTF5RaAusR0L6Mj3-qAp2Rq9idCuMC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -3790,7 +3790,7 @@
 
   'src/ios_internal':  {
       'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' +
-        '795a986ba94ef9eb51ae7df5234a2c42dc8643d4',
+        '546166297e66e1c41ed01388ee445f4011bbd084',
       'condition': 'checkout_ios and checkout_src_internal',
   },
 
diff --git a/base/BUILD.gn b/base/BUILD.gn
index b1b814f6..c835d9e 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -41,6 +41,7 @@
 import("//build_overrides/build.gni")
 import("//testing/libfuzzer/fuzzer_test.gni")
 import("//testing/test.gni")
+import("//third_party/protobuf/proto_library.gni")
 
 if (is_ios) {
   # Used to access target_environment and target_platform.
@@ -50,11 +51,6 @@
   import("//build/config/ios/ios_sdk.gni")
 }
 
-if (is_mac) {
-  # Used to generate fuzzer corpus :base_mach_port_rendezvous_convert_corpus.
-  import("//third_party/protobuf/proto_library.gni")
-}
-
 if (is_win) {
   import("//build/config/win/control_flow_guard.gni")
 }
@@ -3740,16 +3736,8 @@
     "strings/string_piece_rust_unittest.cc",
   ]
 
-  if (use_safe_libcxx || use_safe_libstdcxx) {
-    sources += [ "libcpp_hardening_test.cc" ]
-  }
-
   fuzztests = [ "JSONReaderTest.CanParseAnythingWithoutCrashing" ]
 
-  if (is_clang) {
-    sources += [ "compiler_hardening_test.cc" ]
-  }
-
   defines = []
   frameworks = []
 
@@ -3758,6 +3746,7 @@
     ":base_stack_sampling_profiler_test_util",
     ":check_version_internal",
     ":feature_list_buildflags",
+    ":hardening_tests",
     ":i18n",
     ":path_service_unittest",
     ":sanitizer_buildflags",
@@ -4330,6 +4319,33 @@
   configs += [ "//build/config/compiler:no_exit_time_destructors" ]
 }
 
+source_set("hardening_tests") {
+  testonly = true
+
+  sources = [ "protobuf_hardening_test.cc" ]
+
+  if (use_safe_libcxx || use_safe_libstdcxx) {
+    sources += [ "libcpp_hardening_test.cc" ]
+  }
+
+  if (is_clang) {
+    sources += [ "compiler_hardening_test.cc" ]
+  }
+
+  deps = [
+    ":base",
+    ":protobuf_hardening_test_support",
+    "//testing/gmock",
+    "//testing/gtest",
+  ]
+}
+
+proto_library("protobuf_hardening_test_support") {
+  testonly = true
+  sources = [ "protobuf_hardening_test_support.proto" ]
+  generate_python = false
+}
+
 # Test that CFG is enabled in Rust code.
 if (is_win && toolchain_has_rust) {
   source_set("rust_cfg_win_test") {
diff --git a/base/protobuf_hardening_test.cc b/base/protobuf_hardening_test.cc
new file mode 100644
index 0000000..8df2ec4
--- /dev/null
+++ b/base/protobuf_hardening_test.cc
@@ -0,0 +1,42 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Tests that protobuf hardening options are enabled. Currently, the only option
+// available (and tested) is PROTOBUF_INTERNAL_BOUNDS_CHECK_MODE_ABORT.
+
+#include "base/protobuf_hardening_test_support.pb.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base::test {
+
+TEST(ProtobufHardeningTest, RepeatedFieldOutOfBounds) {
+  HardeningTestMessage message;
+
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_field(4), "");
+  EXPECT_DEATH_IF_SUPPORTED(message.set_repeated_field(4, 44), "");
+
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_field()[4], "");
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_field().Get(4), "");
+
+  EXPECT_DEATH_IF_SUPPORTED((*message.mutable_repeated_field())[4], "");
+  EXPECT_DEATH_IF_SUPPORTED(message.mutable_repeated_field()->Get(4), "");
+  EXPECT_DEATH_IF_SUPPORTED(message.mutable_repeated_field()->Mutable(4), "");
+}
+
+TEST(ProtobufHardeningTest, RepeatedPtrFieldOutOfBounds) {
+  HardeningTestMessage message;
+
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_ptr_field(4), "");
+  EXPECT_DEATH_IF_SUPPORTED(message.mutable_repeated_ptr_field(4), "");
+
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_ptr_field()[4], "");
+  EXPECT_DEATH_IF_SUPPORTED(message.repeated_ptr_field().Get(4), "");
+
+  EXPECT_DEATH_IF_SUPPORTED((*message.mutable_repeated_ptr_field())[4], "");
+  EXPECT_DEATH_IF_SUPPORTED(message.mutable_repeated_ptr_field()->Get(4), "");
+  EXPECT_DEATH_IF_SUPPORTED(message.mutable_repeated_ptr_field()->Mutable(4),
+                            "");
+}
+
+}  // namespace base::test
diff --git a/base/protobuf_hardening_test_support.proto b/base/protobuf_hardening_test_support.proto
new file mode 100644
index 0000000..84bf74f
--- /dev/null
+++ b/base/protobuf_hardening_test_support.proto
@@ -0,0 +1,16 @@
+// Copyright 2025 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto2";
+
+package base.test;
+
+option optimize_for = LITE_RUNTIME;
+
+message HardeningTestMessage {
+  message NestedMessage {}
+
+  repeated int32 repeated_field = 1;
+  repeated NestedMessage repeated_ptr_field = 2;
+}
diff --git a/chrome/VERSION b/chrome/VERSION
index 4c34b6d..547d765 100644
--- a/chrome/VERSION
+++ b/chrome/VERSION
@@ -1,4 +1,4 @@
 MAJOR=141
 MINOR=0
-BUILD=7386
+BUILD=7388
 PATCH=0
diff --git a/chrome/android/profiles/arm.newest.txt b/chrome/android/profiles/arm.newest.txt
index 129a75d..d661956 100644
--- a/chrome/android/profiles/arm.newest.txt
+++ b/chrome/android/profiles/arm.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-141.0.7383.0_pre1508226_rc-r1-merged.afdo.bz2
+chromeos-chrome-arm-141.0.7386.0_pre1508808_rc-r1-merged.afdo.bz2
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt
index 97fc77b..a7dcb7f 100644
--- a/chrome/android/profiles/newest.txt
+++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-141.0.7381.0_pre1507586_rc-r1-merged.afdo.bz2
+chromeos-chrome-amd64-141.0.7386.0_pre1508832_rc-r1-merged.afdo.bz2
diff --git a/chrome/browser/resources/new_tab_page/ntp_promo/individual_promos.css b/chrome/browser/resources/new_tab_page/ntp_promo/individual_promos.css
index ad179f493..d65883d 100644
--- a/chrome/browser/resources/new_tab_page/ntp_promo/individual_promos.css
+++ b/chrome/browser/resources/new_tab_page/ntp_promo/individual_promos.css
@@ -104,3 +104,7 @@
   text-align: center;
   width: var(--ntp-promo-icon-size);
 }
+
+#actionIcon:dir(rtl) {
+  transform: scaleX(-1);
+}
diff --git a/chrome/browser/resources/new_tab_page/ntp_promo/setup_list_item.css b/chrome/browser/resources/new_tab_page/ntp_promo/setup_list_item.css
index b92125d..d146315 100644
--- a/chrome/browser/resources/new_tab_page/ntp_promo/setup_list_item.css
+++ b/chrome/browser/resources/new_tab_page/ntp_promo/setup_list_item.css
@@ -99,6 +99,10 @@
   width: var(--setup-list-icon-size);
 }
 
+#actionIcon:dir(rtl) {
+  transform: scaleX(-1);
+}
+
 .completed #actionIcon {
   color: var(--setup-list-completed-foreground);
 }
diff --git a/chrome/browser/ui/unload_controller.cc b/chrome/browser/ui/unload_controller.cc
index b11c1ca..3afd4a6d 100644
--- a/chrome/browser/ui/unload_controller.cc
+++ b/chrome/browser/ui/unload_controller.cc
@@ -21,6 +21,7 @@
 #include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
 #include "chrome/browser/web_applications/policy/web_app_policy_manager.h"
 #include "chrome/browser/web_applications/web_app_provider.h"
+#include "components/performance_manager/public/execution_context_priority/execution_context_priority.h"
 #include "components/tab_groups/tab_group_id.h"
 #include "components/tabs/public/tab_group.h"
 #include "components/webapps/common/web_app_id.h"
@@ -115,6 +116,13 @@
   // One case where we hit this is in a tab that has an infinite loop
   // before load.
   if (contents->NeedToFireBeforeUnloadOrUnloadEvents()) {
+    // Inform PerformanceManager that the page is closing, so the priority of
+    // its frames is boosted while beforeunload/unload handlers are running,
+    // making page closing faster. This state may be reset in
+    // BeforeUnloadFired() if page closing is aborted.
+    performance_manager::execution_context_priority::SetPageIsClosing(
+        contents, /*is_closing=*/true);
+
     // If the page has unload listeners, then we tell the renderer to fire
     // them. Once they have fired, we'll get a message back saying whether
     // to proceed closing the page or not, which sends us back to this method
@@ -129,6 +137,12 @@
                                          bool proceed) {
   if (!proceed) {
     DevToolsWindow::OnPageCloseCanceled(contents);
+
+    // Inform PerformanceManager that page close was aborted. Any priority boost
+    // will be removed.
+    performance_manager::execution_context_priority::SetPageIsClosing(
+        contents, /*is_closing=*/false);
+
     std::optional<tab_groups::TabGroupId> group =
         browser_->tab_strip_model()->GetTabGroupForTab(
             browser_->tab_strip_model()->GetIndexOfWebContents(contents));
@@ -402,6 +416,13 @@
       // and then call beforeunload handlers for |web_contents|.
       // See DevToolsWindow::InterceptPageBeforeUnload for details.
       if (!DevToolsWindow::InterceptPageBeforeUnload(web_contents)) {
+        // Inform PerformanceManager that the page is closing, so the priority
+        // of its frames is boosted while beforeunload/unload handlers are
+        // running, making page closing faster. This state may be reset in
+        // BeforeUnloadFired() if page closing is aborted.
+        performance_manager::execution_context_priority::SetPageIsClosing(
+            web_contents, /*is_closing=*/true);
+
         web_contents->DispatchBeforeUnload(false /* auto_cancel */);
       }
     } else {
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt
index e2943c3..9e36575 100644
--- a/chrome/build/android-arm32.pgo.txt
+++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@
-chrome-android32-main-1756554980-b4c5870fb8a212326a906959c2e14f94fb7ac57d-4712886d2405953230be57c3716f53f05c3e5e95.profdata
+chrome-android32-main-1756640655-c53d4e4600a2d8ca3ffad2ab70f0d8a172a62097-b63ce50f1dd5bbe83c81b1872e57353df71b9ffa.profdata
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt
index 51016ca..9576b17 100644
--- a/chrome/build/android-arm64.pgo.txt
+++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@
-chrome-android64-main-1756566412-b42edf106b37e2c813ebaf4d596ccc9955c6c286-f1cf303558be5ed0cb33d6c43ae91f3982c1d32f.profdata
+chrome-android64-main-1756645721-2603bef9302abcacf141f466ea150a287cbceae7-e3e1753e0fe6d0e4dc1b30ba170343977efe7e5c.profdata
diff --git a/chrome/build/android-desktop-x64.pgo.txt b/chrome/build/android-desktop-x64.pgo.txt
index 36b52500..18c8834 100644
--- a/chrome/build/android-desktop-x64.pgo.txt
+++ b/chrome/build/android-desktop-x64.pgo.txt
@@ -1 +1 @@
-chrome-android-desktop-x64-main-1756554980-90dfe8c84bc38434848926d671bc51d7730316ca-4712886d2405953230be57c3716f53f05c3e5e95.profdata
+chrome-android-desktop-x64-main-1756640655-2b666ba1531dce799e004395194fc53cb56a0187-b63ce50f1dd5bbe83c81b1872e57353df71b9ffa.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b6542ffb6..66c85216b 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1756554980-90d072515fd46d7eaab7edb3059df645c4fab41c-4712886d2405953230be57c3716f53f05c3e5e95.profdata
+chrome-mac-main-1756640655-514e97c01756d6b1986f861779434d49b7f3402b-b63ce50f1dd5bbe83c81b1872e57353df71b9ffa.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 9ac028e1..ba1c688 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1756544143-f5f38531bae9f34e65c1c461899b656ce3529acd-8353b9e5235b42ec4ee631f65fa57f7907d8402b.profdata
+chrome-win32-main-1756629723-072c430abe5c4c2cdb5cc77f8300bdf417020155-aa466f6e2a28042c2374d6b46b62a053a9a544e8.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index a962587..b7d8f48d 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1756554980-24ef0d15f193940924fa38ad59d5d3e66a9fcc91-4712886d2405953230be57c3716f53f05c3e5e95.profdata
+chrome-win64-main-1756629723-5abcb63a6caf7d5728b409ad939da18bb5f89b90-aa466f6e2a28042c2374d6b46b62a053a9a544e8.profdata
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index 1b59043..371e263a 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-141-7367.0-1756089480-benchmark-141.0.7383.0_pre1508226-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-141-7367.0-1756089480-benchmark-141.0.7386.0_pre1508808-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index 47d2e26..853a21b 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-141-7339.18-1756086569-benchmark-141.0.7381.0_pre1507586-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-141-7339.18-1756086569-benchmark-141.0.7385.0_pre1508774-r1-redacted.afdo.xz
diff --git a/clank b/clank
index 2075075..581b055f 160000
--- a/clank
+++ b/clank
@@ -1 +1 @@
-Subproject commit 2075075ba567da319b267a73482bf9d7de4b9d9a
+Subproject commit 581b055fda53c19ff49b49b0b444e8f1aeb40930
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
index 856959f..df5195543 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.cc
@@ -8,6 +8,7 @@
 #include <map>
 #include <optional>
 #include <string>
+#include <string_view>
 #include <utility>
 
 #include "base/containers/to_vector.h"
@@ -352,7 +353,7 @@
 
 bool AddressComponent::SetValueForType(
     FieldType field_type,
-    const std::u16string& value,
+    std::u16string_view value,
     const VerificationStatus& verification_status,
     bool invalidate_child_nodes) {
   AddressComponent* node_for_type = GetNodeForType(field_type);
@@ -360,9 +361,9 @@
     return false;
   }
   node_for_type->GetStorageType() == field_type
-      ? node_for_type->SetValue(value, verification_status)
-      : node_for_type->SetValueForOtherSupportedType(field_type, value,
-                                                     verification_status);
+      ? node_for_type->SetValue(std::u16string(value), verification_status)
+      : node_for_type->SetValueForOtherSupportedType(
+            field_type, std::u16string(value), verification_status);
   if (invalidate_child_nodes) {
     node_for_type->UnsetSubcomponents();
   }
@@ -1310,7 +1311,7 @@
                      VerificationStatus::kFormatted, GetVerificationStatus()));
       } else if (formatted_value == newer_component.GetValue()) {
         // Otherwise test if the value is the same as the one of
-        // |newer_component|. If yes, maintain the better verification status.
+        // `newer_component`. If yes, maintain the better verification status.
         SetValue(formatted_value, GetMoreSignificantVerificationStatus(
                                       VerificationStatus::kFormatted,
                                       newer_component.GetVerificationStatus()));
@@ -1392,14 +1393,14 @@
   // is sufficient to apply a recursive merging strategy.
   //
   // * None of the nodes of the substructure are pairwise mergeable. In this
-  // case, either the complete substructure of |this| or |newer_component|
+  // case, either the complete substructure of `this` or `newer_component`
   // must be used. Which one to use can be decided by the higher validation
   // score.
   //
   // * In a mixed scenario, there is at least one pair of mergeable nodes
   // in the substructure and at least on pair of non-mergeable nodes. Here,
   // the mergeable nodes are merged while all other nodes are taken either
-  // from |this| or the |newer_component| decided by the higher validation
+  // from `this` or the `newer_component` decided by the higher validation
   // score of the unmerged nodes.
   //
   // The following algorithm combines the three cases by first trying to merge
diff --git a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
index eb2b019e..d207ea8c 100644
--- a/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
+++ b/components/autofill/core/browser/data_model/addresses/autofill_structured_address_component.h
@@ -9,6 +9,7 @@
 #include <memory>
 #include <optional>
 #include <string>
+#include <string_view>
 #include <type_traits>
 #include <vector>
 
@@ -51,16 +52,16 @@
 std::optional<VerificationStatus> ToSafeVerificationStatus(
     std::underlying_type_t<VerificationStatus> raw_value);
 
-// Prints the string representation of |status| to |os|.
+// Prints the string representation of `status` to `os`.
 std::ostream& operator<<(std::ostream& os, VerificationStatus status);
 
-// Returns true if |left| has a less significant verification status compared to
-// |right|.
+// Returns true if `left` has a less significant verification status compared to
+// `right`.
 bool IsLessSignificantVerificationStatus(VerificationStatus left,
                                          VerificationStatus right);
 
 // Returns the more significant verification status according to
-// |IsLessSignificantVerificationStatus|.
+// `IsLessSignificantVerificationStatus`.
 VerificationStatus GetMoreSignificantVerificationStatus(
     VerificationStatus left,
     VerificationStatus right);
@@ -68,9 +69,9 @@
 // The merge mode defines if and how two components are merged.
 // The merge operations are applied in the order defined here.
 // If one merge operation succeeds, the subsequent ones are not tested.
-// Therefore, if |KUseBetterOrMoreRecentIfDifferent| is active,
-// |kMergeChildrenAndReformatIfNeeded| will not be applied because
-// |kUseBetterOrMostRecentIfDifferent| is always applicable.
+// Therefore, if `KUseBetterOrMoreRecentIfDifferent` is active,
+// `kMergeChildrenAndReformatIfNeeded` will not be applied because
+// `kUseBetterOrMostRecentIfDifferent` is always applicable.
 enum MergeMode {
   // If one component has an empty value, use the non-empty one.
   kReplaceEmpty = 1,
@@ -110,8 +111,8 @@
 // have a set of children, each representing a more granular subtoken of the
 // component.
 //
-// An AddressComponent has a string representation stored in |value_| and a
-// VerificationStatus stored in |verification_status_|.
+// An AddressComponent has a string representation stored in `value_` and a
+// VerificationStatus stored in `verification_status_`.
 // The latter indicates if the value was user-verified, observed in a form
 // submission event, parsed from its parent component or was formatted from its
 // child components.
@@ -172,23 +173,23 @@
   // a status.
   virtual void MigrateLegacyStructure() {}
 
-  // Comparison operators are deleted in favor of and |SameAs()|.
+  // Comparison operators are deleted in favor of and `SameAs()`.
   bool operator==(const AddressComponent& right) const = delete;
   bool operator!=(const AddressComponent& right) const = delete;
 
-  // Compares the values and verification statuses with |other| recursively
+  // Compares the values and verification statuses with `other` recursively
   // down the tree. Returns true iff all values and verification statuses of
-  // this node and its subtree and |other| with its subtree are the same.
+  // this node and its subtree and `other` with its subtree are the same.
   virtual bool SameAs(const AddressComponent& other) const;
 
-  // Copies the values and verification statuses from |other| recursively down
+  // Copies the values and verification statuses from `other` recursively down
   // the tree.
   void CopyFrom(const AddressComponent& other);
 
-  // Returns the autofill storage type stored in |storage_type_|.
+  // Returns the autofill storage type stored in `storage_type_`.
   FieldType GetStorageType() const;
 
-  // Returns the string representation of |storage_type_|.
+  // Returns the string representation of `storage_type_`.
   std::string GetStorageTypeName() const;
 
   // Returns the value verification status of the component's value;
@@ -197,7 +198,7 @@
   // Returns true if the component has no subcomponents.
   bool IsAtomic() const;
 
-  // Returns a constant reference to |value_.value()|. If the value is not
+  // Returns a constant reference to `value_.value()`. If the value is not
   // assigned, an empty string is returned.
   const std::u16string& GetValue() const;
 
@@ -230,16 +231,16 @@
   // - If `invalidate_child_nodes` is true, ignores read-only status and clears
   //   child nodes after setting.
   bool SetValueForType(FieldType field_type,
-                       const std::u16string& value,
+                       std::u16string_view value,
                        const VerificationStatus& status,
                        bool invalidate_child_nodes = false);
 
   // Sets the value to an empty string, marks it unassigned and sets the
-  // verification status to |kNoStatus|.
+  // verification status to `kNoStatus`.
   virtual void UnsetValue();
 
-  // Convenience method to get the value of |field_type|.
-  // Returns an empty string if |field_type| is not supported.
+  // Convenience method to get the value of `field_type`.
+  // Returns an empty string if `field_type` is not supported.
   std::u16string GetValueForType(FieldType field_type) const;
 
   // Convenience method to get the value of `field_type` to be used for
@@ -251,22 +252,22 @@
       const AddressCountryCode& common_country_code) const;
 
   // Convenience method to get the verification status of `field_type`.
-  // Returns |VerificationStatus::kNoStatus| if `field_type` is not supported.
+  // Returns `VerificationStatus::kNoStatus` if `field_type` is not supported.
   VerificationStatus GetVerificationStatusForType(FieldType field_type) const;
 
-  // Returns true if the |value| and |verification_status| were successfully
-  // unset for |type|.
+  // Returns true if the `value` and `verification_status` were successfully
+  // unset for `type`.
   bool UnsetValueForTypeIfSupported(FieldType field_type);
 
-  // Parses |value_| to assign values to the subcomponents.
+  // Parses `value_` to assign values to the subcomponents.
   // The method uses 2 stages:
   //
-  // * Use |ParseValueAndAssignSubcomponentsByRegularExpressions()|. This stage
+  // * Use `ParseValueAndAssignSubcomponentsByRegularExpressions()`. This stage
   // uses a list of regular expressions acquired by the virtual method
-  // |GetParseRegularExpressionsByRelevance()|. This stage my fail.
+  // `GetParseRegularExpressionsByRelevance()`. This stage my fail.
   //
-  // * Use |ParseValueAndAssignSubcomponentsByFallbackMethod()| as the last
-  // resort to parse |value_|. This method must produce a valid result.
+  // * Use `ParseValueAndAssignSubcomponentsByFallbackMethod()` as the last
+  // resort to parse `value_`. This method must produce a valid result.
   void ParseValueAndAssignSubcomponents();
 
   // This methods populated the unassigned entries in the subtree of this node
@@ -275,7 +276,7 @@
   // is virtual and can be reimplemented on the type level.
   virtual void RecursivelyCompleteTree();
 
-  // Completes the full tree by calling |RecursivelyCompleteTree()| starting
+  // Completes the full tree by calling `RecursivelyCompleteTree()` starting
   // form the root node. Returns true if the completion was successful.
   virtual bool CompleteFullTree();
 
@@ -290,7 +291,7 @@
   bool IsTreeCompletable();
 
   // Recursively adds the supported types to the set. Calls
-  // |GetAdditionalSupportedFieldTypes()| to add field types.
+  // `GetAdditionalSupportedFieldTypes()` to add field types.
   FieldTypeSet GetSupportedTypes() const;
 
   // Recursively adds only the storable types to the set. No computed type is
@@ -304,7 +305,7 @@
   // - Otherwise, if `type` is not a supported type of any node, return nullopt.
   std::optional<FieldType> GetStorableTypeOf(FieldType type) const;
 
-  // Adds the additional supported field types to |supported_types|.
+  // Adds the additional supported field types to `supported_types`.
   // The method should DCHECK that the added types are not part of the set yet.
   virtual const FieldTypeSet GetAdditionalSupportedFieldTypes() const;
 
@@ -319,19 +320,19 @@
       const AddressComponent& newer_component) const;
 
   // Recursively updates the verification statuses to the higher one, for nodes
-  // in |newer_component| that have the same values as the nodes in |this|.
+  // in `newer_component` that have the same values as the nodes in `this`.
   virtual void MergeVerificationStatuses(
       const AddressComponent& newer_component);
 
-  // Merge |newer_component| into this AddressComponent.
+  // Merge `newer_component` into this AddressComponent.
   // Returns false if the merging is not possible.
   // The state of the component is not altered by a failed merging attempt.
-  // |newer_was_more_recently_used| indicates that the newer component was also
+  // `newer_was_more_recently_used` indicates that the newer component was also
   // more recently used for filling a form.
   virtual bool MergeWithComponent(const AddressComponent& newer_component,
                                   bool newer_was_more_recently_used = true);
 
-  // Merge |newer_component| into this AddressComponent.
+  // Merge `newer_component` into this AddressComponent.
   // The merging is possible iff the value of both root nodes is token
   // equivalent, meaning they contain the same tokens in an arbitrary order.
   // Returns false if the merging is not possible.
@@ -364,8 +365,8 @@
   // Recursively unsets all subcomponents.
   void RecursivelyUnsetSubcomponents();
 
-  // Return if the value associated with |field_type| is valid.
-  // If |wipe_if_not|, the value is unset if invalid.
+  // Return if the value associated with `field_type` is valid.
+  // If `wipe_if_not`, the value is unset if invalid.
   bool IsValueForTypeValid(FieldType field_type, bool wipe_if_not = false);
 
   // While processing two structured addresses, if only one of them has their
@@ -380,7 +381,7 @@
   // this function retrieves it. Otherwise it returns an empty country code.
   AddressCountryCode GetCountryCode() const;
 
-  // Deletes the stored structure and returns true if |IsStructureValid()|
+  // Deletes the stored structure and returns true if `IsStructureValid()`
   // returns false.
   virtual bool WipeInvalidStructure();
 
@@ -409,7 +410,7 @@
   // the AddressComponent tree.
   virtual bool IsValueReadOnly() const;
 
-  // Returns a vector containing the |storage_types_| of all direct
+  // Returns a vector containing the `storage_types_` of all direct
   // subcomponents.
   std::vector<FieldType> GetSubcomponentTypes() const;
 
@@ -424,7 +425,7 @@
   virtual std::vector<const re2::RE2*> GetParseRegularExpressionsByRelevance()
       const;
 
-  // This method parses |value_| to assign values to the subcomponents.
+  // This method parses `value_` to assign values to the subcomponents.
   // The method is virtual and can be reimplemented per type.
   // It must succeed.
   virtual void ParseValueAndAssignSubcomponentsByFallbackMethod();
@@ -474,14 +475,14 @@
   virtual bool HasNewerValuePrecedenceInMerging(
       const AddressComponent& newer_component) const;
 
-  // Parses |value| by using |parse_expressions| and assigns the values.
+  // Parses `value` by using `parse_expressions` and assigns the values.
   // Returns true on success.
   bool ParseValueAndAssignSubcomponentsByRegularExpression(
       const std::u16string& value,
       const re2::RE2* parse_expression);
 
   // Determines and sets a formatted value using
-  // |GetFormattedValueFromSubcomponents|.
+  // `GetFormattedValueFromSubcomponents`.
   void FormatValueFromSubcomponents();
 
   // Returns the maximum number of components with assigned values on the path
@@ -506,7 +507,7 @@
   const AddressComponent* GetNodeForType(FieldType field_type) const;
 
   // Recursively adds the supported types to the set. If `!storable_only`, calls
-  // |GetAdditionalSupportedFieldTypes()| to add computed field types.
+  // `GetAdditionalSupportedFieldTypes()` to add computed field types.
   virtual FieldTypeSet GetTypes(bool storable_only) const;
 
   // Unsets the node and all of its children.
@@ -528,7 +529,7 @@
   void FillTreeGaps();
 
   // Determines a value from the subcomponents by using the
-  // most suitable format string determined by |GetBestFormatString()|.
+  // most suitable format string determined by `GetBestFormatString()`.
   std::u16string GetFormattedValueFromSubcomponents();
 
   // Replaces placeholder values with the corresponding values.
@@ -536,23 +537,23 @@
       std::u16string_view format) const;
 
   // This method uses i18n parsing instructions used by
-  // `ParseValueByI18nRegularExpression` to parse |value_| into the values of
+  // `ParseValueByI18nRegularExpression` to parse `value_` into the values of
   // the subcomponents. Returns true on success and is allowed to fail.
   bool ParseValueAndAssignSubcomponentsByI18nParsingRules();
 
   // This method uses regular expressions acquired by
-  // |GetParseRegularExpressionsByRelevance| to parse |value_| into the values
+  // `GetParseRegularExpressionsByRelevance` to parse `value_` into the values
   // of the subcomponents. Returns true on success and is allowed to fail.
   bool ParseValueAndAssignSubcomponentsByRegularExpressions();
 
   // This method uses regular expressions acquired by
-  // |GetParseRegularExpressionsByRelevance| to parse |value_| into the values
+  // `GetParseRegularExpressionsByRelevance` to parse `value_` into the values
   // of the subcomponents that are empty, components with non-empty values
   // remain unchanged. If parsing is not successful, the function does not
   // perform any modifications. Returns true if parsing was successful.
   void TryParseValueAndAssignSubcomponentsRespectingSetValues();
 
-  // Parses |value| by using |parse_expressions| and assigns values to empty
+  // Parses `value` by using `parse_expressions` and assigns values to empty
   // subcomponents only. The value assigned to each subcomponent is compatible
   // with the information growth invariant (i.e child information is always
   // contained on their ancestors). If parsing is not successful, the function
@@ -585,7 +586,7 @@
   // The unstructured value of this component.
   std::optional<std::u16string> value_;
 
-  // The verification status of |value_| indicates the certainty of the value
+  // The verification status of `value_` indicates the certainty of the value
   // to be correct.
   VerificationStatus value_verification_status_;
 
diff --git a/components/autofill/core/browser/data_model/addresses/phone_number.cc b/components/autofill/core/browser/data_model/addresses/phone_number.cc
index a751207..9919945c 100644
--- a/components/autofill/core/browser/data_model/addresses/phone_number.cc
+++ b/components/autofill/core/browser/data_model/addresses/phone_number.cc
@@ -7,6 +7,7 @@
 #include <limits.h>
 
 #include <algorithm>
+#include <string_view>
 
 #include "base/check_op.h"
 #include "base/feature_list.h"
@@ -28,11 +29,11 @@
 namespace {
 
 // Returns the region code for this phone number, which is an ISO 3166 2-letter
-// country code.  The returned value is based on the |profile|; if the |profile|
+// country code.  The returned value is based on the `profile`; if the `profile`
 // does not have a country code associated with it, falls back to the country
-// code corresponding to the |app_locale|.
+// code corresponding to the `app_locale`.
 std::string GetRegion(const AutofillProfile& profile,
-                      const std::string& app_locale) {
+                      std::string_view app_locale) {
   std::u16string country_code = profile.GetRawInfo(ADDRESS_HOME_COUNTRY);
   if (!country_code.empty())
     return base::UTF16ToASCII(country_code);
@@ -113,7 +114,7 @@
                                    const std::string& app_locale,
                                    FieldTypeSet* matching_types) const {
   // Strip the common phone number non numerical characters before calling the
-  // base matching type function. For example, the |text| "(514) 121-1523"
+  // base matching type function. For example, the `text` "(514) 121-1523"
   // would become the stripped text "5141211523". Since the base matching
   // function only does simple canonicalization to match against the stored
   // data, some domain specific cases will be covered below.
@@ -124,7 +125,7 @@
   // TODO(crbug.com/41236729): Investigate the use of PhoneNumberUtil when
   // matching phone numbers for upload.
   // If there is not already a match for PHONE_HOME_WHOLE_NUMBER, normalize the
-  // |text| based on the app_locale before comparing it to the whole number. For
+  // `text` based on the app_locale before comparing it to the whole number. For
   // example, the France number "33 2 49 19 70 70" would be normalized to
   // "+33249197070" whereas the US number "+1 (234) 567-8901" would be
   // normalized to "12345678901".
@@ -168,7 +169,7 @@
   }
 }
 
-// Normalize phones if |type| is a whole number:
+// Normalize phones if `type` is a whole number:
 //   (650)2345678 -> 6502345678
 //   1-800-FLOWERS -> 18003569377
 // If the phone cannot be normalized, returns the stored value verbatim.
@@ -314,7 +315,7 @@
   return VerificationStatus::kNoStatus;
 }
 
-void PhoneNumber::UpdateCacheIfNeeded(const std::string& app_locale) const {
+void PhoneNumber::UpdateCacheIfNeeded(std::string_view app_locale) const {
   std::string region = GetRegion(*profile_, app_locale);
   if (!number_.empty() && cached_parsed_phone_.region() != region) {
     // To enable filling of country calling codes for nationally formatted
diff --git a/components/autofill/core/browser/data_model/addresses/phone_number.h b/components/autofill/core/browser/data_model/addresses/phone_number.h
index d26c49e..68fd5c83 100644
--- a/components/autofill/core/browser/data_model/addresses/phone_number.h
+++ b/components/autofill/core/browser/data_model/addresses/phone_number.h
@@ -8,6 +8,7 @@
 #include <stddef.h>
 
 #include <string>
+#include <string_view>
 
 #include "base/memory/raw_ptr.h"
 #include "components/autofill/core/browser/data_model/form_group.h"
@@ -84,14 +85,14 @@
     void SetInfo(FieldType field_type, const std::u16string& value);
 
     // Parses the number built up from pieces stored via SetInfo() according to
-    // the specified |profile|'s country code, falling back to the given
-    // |app_locale| if the |profile| has no associated country code.  Returns
+    // the specified `profile`'s country code, falling back to the given
+    // `app_locale` if the `profile` has no associated country code.  Returns
     // true if parsing was successful, false otherwise.
     bool ParseNumber(const AutofillProfile& profile,
                      const std::string& app_locale,
                      std::u16string* value) const;
 
-    // Returns true if both |phone_| and |whole_number_| are empty.
+    // Returns true if both `phone_` and `whole_number_` are empty.
     bool IsEmpty() const;
 
    private:
@@ -116,7 +117,7 @@
 
   // Updates the cached parsed number if the profile's region has changed
   // since the last time the cache was updated.
-  void UpdateCacheIfNeeded(const std::string& app_locale) const;
+  void UpdateCacheIfNeeded(std::string_view app_locale) const;
 
   // The phone number.
   std::u16string number_;
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 85c7848..d7d645ab 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "64.1",
-  "log_list_timestamp": "2025-08-30T12:53:42Z",
+  "version": "64.2",
+  "log_list_timestamp": "2025-08-31T12:53:40Z",
   "operators": [
     {
       "name": "Google",
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.cc b/content/browser/preloading/prefetch/prefetch_match_resolver.cc
index 8be8b2a..7cd7030 100644
--- a/content/browser/preloading/prefetch/prefetch_match_resolver.cc
+++ b/content/browser/preloading/prefetch/prefetch_match_resolver.cc
@@ -6,6 +6,7 @@
 
 #include "base/memory/ptr_util.h"
 #include "base/memory/weak_ptr.h"
+#include "base/notreached.h"
 #include "base/timer/timer.h"
 #include "base/trace_event/trace_event.h"
 #include "content/browser/preloading/prefetch/prefetch_container.h"
@@ -15,6 +16,7 @@
 #include "content/browser/preloading/prefetch/prefetch_service.h"
 #include "content/browser/preloading/prefetch/prefetch_serving_handle.h"
 #include "content/browser/preloading/prerender/prerender_features.h"
+#include "content/browser/renderer_host/frame_tree.h"
 
 namespace content {
 
@@ -40,14 +42,16 @@
 PrefetchMatchResolver::CandidateData::~CandidateData() = default;
 
 PrefetchMatchResolver::PrefetchMatchResolver(
+    base::WeakPtr<NavigationRequest> navigation_request,
+    base::WeakPtr<PrefetchService> prefetch_service,
     PrefetchKey navigated_key,
     PrefetchServiceWorkerState expected_service_worker_state,
     bool is_nav_prerender,
-    base::WeakPtr<PrefetchService> prefetch_service,
     Callback callback)
-    : navigated_key_(std::move(navigated_key)),
-      expected_service_worker_state_(expected_service_worker_state),
+    : navigation_request_for_metrics_(std::move(navigation_request)),
       prefetch_service_(std::move(prefetch_service)),
+      navigated_key_(std::move(navigated_key)),
+      expected_service_worker_state_(expected_service_worker_state),
       callback_(std::move(callback)),
       is_nav_prerender_(is_nav_prerender) {
   switch (expected_service_worker_state_) {
@@ -74,18 +78,63 @@
 
 // static
 void PrefetchMatchResolver::FindPrefetch(
+    FrameTreeNodeId frame_tree_node_id,
+    PrefetchService& prefetch_service,
     PrefetchKey navigated_key,
     PrefetchServiceWorkerState expected_service_worker_state,
-    bool is_nav_prerender,
-    PrefetchService& prefetch_service,
     base::WeakPtr<PrefetchServingPageMetricsContainer>
         serving_page_metrics_container,
     Callback callback) {
   TRACE_EVENT0("loading", "PrefetchMatchResolver::FindPrefetch");
+
+  auto* frame_tree_node = FrameTreeNode::GloballyFindByID(frame_tree_node_id);
+  if (!frame_tree_node) {
+    // TODO(crbug.com/360094997): Use `CHECK()` instead once we check the
+    // safety.
+    DUMP_WILL_BE_NOTREACHED();
+    std::move(callback).Run({});
+    return;
+  }
+
+  auto navigation_request = ([&]() -> base::WeakPtr<NavigationRequest> {
+    if (!frame_tree_node->navigation_request()) {
+      // We except that a navigation invoking `URLLoaderInterceptor` has
+      // `NavigationRequest`, but this path hits in android-x64-rel bots. If it
+      // is not satisfied in the prod, give up to record metrics.
+      //
+      // TODO(crbug.com/360094997): Investigate why.
+      return nullptr;
+    }
+
+    return frame_tree_node->navigation_request()->GetWeakPtr();
+  })();
+
   // See the comment of `self_`.
   auto prefetch_match_resolver = base::WrapUnique(new PrefetchMatchResolver(
+      std::move(navigation_request), prefetch_service.GetWeakPtr(),
+      std::move(navigated_key), expected_service_worker_state,
+      frame_tree_node->frame_tree().is_prerendering(), std::move(callback)));
+  PrefetchMatchResolver& ref = *prefetch_match_resolver.get();
+  ref.self_ = std::move(prefetch_match_resolver);
+
+  ref.FindPrefetchInternal(prefetch_service,
+                           std::move(serving_page_metrics_container));
+}
+
+// static
+void PrefetchMatchResolver::FindPrefetchForTesting(
+    PrefetchService& prefetch_service,
+    PrefetchKey navigated_key,
+    PrefetchServiceWorkerState expected_service_worker_state,
+    base::WeakPtr<PrefetchServingPageMetricsContainer>
+        serving_page_metrics_container,
+    Callback callback,
+    bool is_nav_prerender) {
+  // See the comment of `self_`.
+  auto prefetch_match_resolver = base::WrapUnique(new PrefetchMatchResolver(
+      /*navigation_request=*/nullptr, prefetch_service.GetWeakPtr(),
       std::move(navigated_key), expected_service_worker_state, is_nav_prerender,
-      prefetch_service.GetWeakPtr(), std::move(callback)));
+      std::move(callback)));
   PrefetchMatchResolver& ref = *prefetch_match_resolver.get();
   ref.self_ = std::move(prefetch_match_resolver);
 
diff --git a/content/browser/preloading/prefetch/prefetch_match_resolver.h b/content/browser/preloading/prefetch/prefetch_match_resolver.h
index 91f998a..d5264609 100644
--- a/content/browser/preloading/prefetch/prefetch_match_resolver.h
+++ b/content/browser/preloading/prefetch/prefetch_match_resolver.h
@@ -13,6 +13,7 @@
 #include "content/browser/preloading/prefetch/prefetch_params.h"
 #include "content/browser/preloading/prefetch/prefetch_servable_state.h"
 #include "content/browser/preloading/prefetch/prefetch_serving_handle.h"
+#include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/global_routing_id.h"
 
@@ -123,13 +124,21 @@
   // Matches prefetches only if its final PrefetchServiceWorkerState is
   // `expected_service_worker_state` (either `kControlled` or `kDisallowed`).
   static void FindPrefetch(
+      FrameTreeNodeId frame_tree_node_id,
+      PrefetchService& prefetch_service,
       PrefetchKey navigated_key,
       PrefetchServiceWorkerState expected_service_worker_state,
-      bool is_nav_prerender,
-      PrefetchService& prefetch_service,
       base::WeakPtr<PrefetchServingPageMetricsContainer>
           serving_page_metrics_container,
       Callback callback);
+  static void FindPrefetchForTesting(
+      PrefetchService& prefetch_service,
+      PrefetchKey navigated_key,
+      PrefetchServiceWorkerState expected_service_worker_state,
+      base::WeakPtr<PrefetchServingPageMetricsContainer>
+          serving_page_metrics_container,
+      Callback callback,
+      bool is_nav_prerender);
 
  private:
   struct CandidateData final {
@@ -141,10 +150,11 @@
   };
 
   explicit PrefetchMatchResolver(
+      base::WeakPtr<NavigationRequest> navigation_request,
+      base::WeakPtr<PrefetchService> prefetch_service,
       PrefetchKey navigated_key,
       PrefetchServiceWorkerState expected_service_worker_state,
       bool is_nav_prerender,
-      base::WeakPtr<PrefetchService> prefetch_service,
       Callback callback);
 
   // Returns blocked duration. Returns null iff it's not blocked yet.
@@ -212,9 +222,14 @@
   // A would be enough.
   std::unique_ptr<PrefetchMatchResolver> self_;
 
+  // `NavigationRequest` associated to `this`.
+  //
+  // It is used only for metrics purpose.
+  base::WeakPtr<NavigationRequest> navigation_request_for_metrics_;
+  base::WeakPtr<PrefetchService> prefetch_service_;
+
   const PrefetchKey navigated_key_;
   const PrefetchServiceWorkerState expected_service_worker_state_;
-  base::WeakPtr<PrefetchService> prefetch_service_;
   Callback callback_;
   const bool is_nav_prerender_;
   std::map<PrefetchKey, std::unique_ptr<CandidateData>> candidates_;
diff --git a/content/browser/preloading/prefetch/prefetch_service_unittest.cc b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
index 46b3693..a53a3e4 100644
--- a/content/browser/preloading/prefetch/prefetch_service_unittest.cc
+++ b/content/browser/preloading/prefetch/prefetch_service_unittest.cc
@@ -866,11 +866,12 @@
         base::Unretained(&future),
         base::Unretained(&request_handler_keep_alive_));
     auto key = PrefetchKey(initiator_document_token, url);
-    PrefetchMatchResolver::FindPrefetch(
-        std::move(key), PrefetchServiceWorkerState::kDisallowed,
-        /*is_nav_prerender=*/false, prefetch_service(),
+    PrefetchMatchResolver::FindPrefetchForTesting(
+        prefetch_service(), std::move(key),
+        PrefetchServiceWorkerState::kDisallowed,
         GetServingPageMetricsContainerForMostRecentNavigation(),
-        std::move(callback));
+        std::move(callback),
+        /*is_nav_prerender=*/false);
   }
 
   PrefetchServingHandle GetPrefetchToServe(
@@ -951,10 +952,11 @@
       return serving_page_metrics_container->GetWeakPtr();
     }();
     auto key = PrefetchKey(initiator_document_token, url);
-    PrefetchMatchResolver::FindPrefetch(
-        std::move(key), PrefetchServiceWorkerState::kDisallowed,
-        is_nav_prerender, prefetch_service(),
-        std::move(serving_page_metrics_container), std::move(callback));
+    PrefetchMatchResolver::FindPrefetchForTesting(
+        prefetch_service(), std::move(key),
+        PrefetchServiceWorkerState::kDisallowed,
+        std::move(serving_page_metrics_container), std::move(callback),
+        is_nav_prerender);
 
     return res;
   }
diff --git a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc
index f3b3b105..f25be8c 100644
--- a/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc
+++ b/content/browser/preloading/prefetch/prefetch_url_loader_interceptor.cc
@@ -194,20 +194,10 @@
                                  std::move(get_prefetch_callback));
   auto key =
       PrefetchKey(initiator_document_token_, tentative_resource_request_url);
-
-  const bool is_nav_prerender = [&]() -> bool {
-    auto* frame_tree_node =
-        FrameTreeNode::GloballyFindByID(frame_tree_node_id_);
-    if (!frame_tree_node) {
-      return false;
-    }
-
-    return frame_tree_node->frame_tree().is_prerendering();
-  }();
-
   PrefetchMatchResolver::FindPrefetch(
-      std::move(key), expected_service_worker_state_, is_nav_prerender,
-      *prefetch_service, serving_page_metrics_container_, std::move(callback));
+      frame_tree_node_id_, *prefetch_service, std::move(key),
+      expected_service_worker_state_, serving_page_metrics_container_,
+      std::move(callback));
 }
 
 void PrefetchURLLoaderInterceptor::OnGetPrefetchComplete(
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service.h b/ios/chrome/browser/home_customization/model/home_background_customization_service.h
index 74f8d08..59960be2 100644
--- a/ios/chrome/browser/home_customization/model/home_background_customization_service.h
+++ b/ios/chrome/browser/home_customization/model/home_background_customization_service.h
@@ -25,6 +25,10 @@
 class PrefService;
 class UserUploadedImageManager;
 
+// Type representing any custom background on the NTP.
+typedef std::variant<sync_pb::NtpCustomBackground, HomeUserUploadedBackground>
+    HomeCustomBackground;
+
 // Type of the recently used backgrounds exposed externally.
 typedef std::variant<HomeCustomBackground, sync_pb::UserColorTheme>
     RecentlyUsedBackground;
@@ -99,15 +103,15 @@
 
 }  // namespace std
 
-// Equality operators.
-bool operator==(RecentlyUsedBackgroundInternal const& lhs,
-                RecentlyUsedBackgroundInternal const& rhs);
-bool operator==(sync_pb::NtpCustomBackground const& lhs,
-                sync_pb::NtpCustomBackground const& rhs);
-bool operator==(sync_pb::UserColorTheme const& lhs,
-                sync_pb::UserColorTheme const& rhs);
-bool operator==(sync_pb::ThemeSpecificsIos const& lhs,
-                sync_pb::ThemeSpecificsIos const& rhs);
+// Equality operators for theme comparison.
+namespace sync_pb {
+bool operator==(const sync_pb::NtpCustomBackground& lhs,
+                const sync_pb::NtpCustomBackground& rhs);
+bool operator==(const sync_pb::UserColorTheme& lhs,
+                const sync_pb::UserColorTheme& rhs);
+bool operator==(const sync_pb::ThemeSpecificsIos& lhs,
+                const sync_pb::ThemeSpecificsIos& rhs);
+}  // namespace sync_pb
 
 // Service for allowing customization of the Home surface background.
 class HomeBackgroundCustomizationService : public KeyedService {
diff --git a/ios/chrome/browser/home_customization/model/home_background_customization_service.mm b/ios/chrome/browser/home_customization/model/home_background_customization_service.mm
index 8b08bae..d1e81f7 100644
--- a/ios/chrome/browser/home_customization/model/home_background_customization_service.mm
+++ b/ios/chrome/browser/home_customization/model/home_background_customization_service.mm
@@ -30,31 +30,20 @@
 
 }  // namespace
 
-bool operator==(RecentlyUsedBackgroundInternal const& lhs,
-                RecentlyUsedBackgroundInternal const& rhs) {
-  if (std::holds_alternative<sync_pb::ThemeSpecificsIos>(lhs) &&
-      std::holds_alternative<sync_pb::ThemeSpecificsIos>(rhs)) {
-    return std::get<sync_pb::ThemeSpecificsIos>(lhs) ==
-           std::get<sync_pb::ThemeSpecificsIos>(rhs);
-  } else {
-    return std::get<HomeUserUploadedBackground>(lhs) ==
-           std::get<HomeUserUploadedBackground>(rhs);
-  }
-}
-
-bool operator==(sync_pb::NtpCustomBackground const& lhs,
-                sync_pb::NtpCustomBackground const& rhs) {
+namespace sync_pb {
+bool operator==(const sync_pb::NtpCustomBackground& lhs,
+                const sync_pb::NtpCustomBackground& rhs) {
   return lhs.url() == rhs.url();
 }
 
-bool operator==(sync_pb::UserColorTheme const& lhs,
-                sync_pb::UserColorTheme const& rhs) {
+bool operator==(const sync_pb::UserColorTheme& lhs,
+                const sync_pb::UserColorTheme& rhs) {
   return lhs.color() == rhs.color() &&
          lhs.browser_color_variant() == rhs.browser_color_variant();
 }
 
-bool operator==(sync_pb::ThemeSpecificsIos const& lhs,
-                sync_pb::ThemeSpecificsIos const& rhs) {
+bool operator==(const sync_pb::ThemeSpecificsIos& lhs,
+                const sync_pb::ThemeSpecificsIos& rhs) {
   // Ntp Background field takes precedence. Only compare colors if neither
   // theme has an ntp background.
   if (lhs.has_ntp_background() != rhs.has_ntp_background()) {
@@ -72,6 +61,7 @@
 
   return lhs.user_color_theme() == rhs.user_color_theme();
 }
+}  // namespace sync_pb
 
 HomeBackgroundCustomizationService::HomeBackgroundCustomizationService(
     PrefService* pref_service,
@@ -247,19 +237,18 @@
 void HomeBackgroundCustomizationService::DeleteRecentlyUsedBackground(
     RecentlyUsedBackground recent_background) {
   // Make sure this is not the current background.
+  RecentlyUsedBackground current_background;
   std::optional<HomeCustomBackground> current_custom_background =
       GetCurrentCustomBackground();
-  if (current_custom_background &&
-      std::holds_alternative<HomeCustomBackground>(recent_background) &&
-      current_custom_background.value() ==
-          std::get<HomeCustomBackground>(recent_background)) {
+  if (current_custom_background) {
+    current_background = current_custom_background.value();
   }
   std::optional<sync_pb::UserColorTheme> current_color_theme =
       GetCurrentColorTheme();
-  if (current_color_theme &&
-      std::holds_alternative<sync_pb::UserColorTheme>(recent_background) &&
-      current_color_theme.value() ==
-          std::get<sync_pb::UserColorTheme>(recent_background)) {
+  if (current_color_theme) {
+    current_background = current_color_theme.value();
+  }
+  if (current_background == recent_background) {
     return;
   }
 
diff --git a/ios/chrome/browser/home_customization/model/home_background_data.h b/ios/chrome/browser/home_customization/model/home_background_data.h
index 9738aa8f..e763391 100644
--- a/ios/chrome/browser/home_customization/model/home_background_data.h
+++ b/ios/chrome/browser/home_customization/model/home_background_data.h
@@ -12,12 +12,6 @@
 
 struct HomeUserUploadedBackground;
 
-typedef std::variant<sync_pb::NtpCustomBackground, HomeUserUploadedBackground>
-    HomeCustomBackground;
-
-bool operator==(HomeCustomBackground const& lhs,
-                HomeCustomBackground const& rhs);
-
 // C++ representation of framing coordinates for background images.
 // This struct is persisted to disk via prefs. When adding new fields,
 // ensure backward compatibility by providing defaults in FromDict().
@@ -44,9 +38,9 @@
   // Converts to base::Value::Dict for serialization.
   base::Value::Dict ToDict() const;
 
-  // Equality operators.
-  bool operator==(const FramingCoordinates& other) const;
-  bool operator!=(const FramingCoordinates& other) const;
+  // Equality operator.
+  friend bool operator==(const FramingCoordinates&,
+                         const FramingCoordinates&) = default;
 };
 
 // This struct is persisted to disk via prefs. When adding new fields,
@@ -62,7 +56,9 @@
   // Converts to base::Value::Dict for serialization.
   base::Value::Dict ToDict() const;
 
-  bool operator==(const HomeUserUploadedBackground& other) const = default;
+  // Equality operator.
+  friend bool operator==(const HomeUserUploadedBackground&,
+                         const HomeUserUploadedBackground&) = default;
 };
 
 #endif  // IOS_CHROME_BROWSER_HOME_CUSTOMIZATION_MODEL_HOME_BACKGROUND_DATA_H_
diff --git a/ios/chrome/browser/home_customization/model/home_background_data.mm b/ios/chrome/browser/home_customization/model/home_background_data.mm
index af0d71f..b41376ddf 100644
--- a/ios/chrome/browser/home_customization/model/home_background_data.mm
+++ b/ios/chrome/browser/home_customization/model/home_background_data.mm
@@ -15,20 +15,6 @@
 const char kImagePathKey[] = "image_path";
 }  // namespace
 
-bool operator==(HomeCustomBackground const& lhs,
-                HomeCustomBackground const& rhs) {
-  if (std::holds_alternative<sync_pb::NtpCustomBackground>(lhs) &&
-      std::holds_alternative<sync_pb::NtpCustomBackground>(rhs)) {
-    return std::get<sync_pb::NtpCustomBackground>(lhs) ==
-           std::get<sync_pb::NtpCustomBackground>(rhs);
-  } else if (std::holds_alternative<HomeUserUploadedBackground>(lhs) &&
-             std::holds_alternative<HomeUserUploadedBackground>(rhs)) {
-    return std::get<HomeUserUploadedBackground>(lhs) ==
-           std::get<HomeUserUploadedBackground>(rhs);
-  }
-  return false;
-}
-
 FramingCoordinates::FramingCoordinates(double x_val,
                                        double y_val,
                                        double width_val,
@@ -58,15 +44,6 @@
   return dict;
 }
 
-bool FramingCoordinates::operator==(const FramingCoordinates& other) const {
-  return x == other.x && y == other.y && width == other.width &&
-         height == other.height;
-}
-
-bool FramingCoordinates::operator!=(const FramingCoordinates& other) const {
-  return !(*this == other);
-}
-
 std::optional<HomeUserUploadedBackground> HomeUserUploadedBackground::FromDict(
     const base::Value::Dict& dict) {
   const std::string* image_path = dict.FindString(kImagePathKey);
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
index a873706..79aba008 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-c97838b7d4695c2d5efe881dc7d00ea9dad1860d
\ No newline at end of file
+c956a702d2cac9a11cc49961ddd46998f8ee1d00
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
index 4ca023ea6..fc833b5 100644
--- a/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeExtensionKeychainInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-eca5f742b2bba51a5aeec3612a6e234546e67f3d
\ No newline at end of file
+b5fa42833d3eea877d9c4678b42d49856d25e0c0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
index a8e6d53..1f57c9a0 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-0d6c380b32375dc2fb7b27a5ceda2d42b0fb5027
\ No newline at end of file
+45ef07dd759d093b4eec6fe262064cdce8dfec75
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
index 7614d4fd..6324549 100644
--- a/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-2c09226ff05156d6c36b79003fe7c9b0b1e778d6
\ No newline at end of file
+a8717c16df0513ac57c91bf9b191c999a714cbb8
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
index bb282e88..de10ad6 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios.zip.sha1
@@ -1 +1 @@
-eaf429441a31085c93e7b158a02f372a2053bf06
\ No newline at end of file
+2400f331008c52f8caba3a1970e1491e8d48606d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1 b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
index 41f1909..e0c8071 100644
--- a/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/ChromeSSOInternal.framework.dSYM.ios_asan.zip.sha1
@@ -1 +1 @@
-b3ed60e2161cc1bc1a0830cd7479171702cbc2a9
\ No newline at end of file
+5853e5a3463c074c70fa4113e7c1728aeff89cea
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
index 31e0f595..57fea8b 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-3bae010f0f01226396e01803b209315f26fbf05a
\ No newline at end of file
+9a7f43cc542ed19d39b3e1eaa377d0540308b81e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
index 8bb7699..170ddb3 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-26d539f9369485f8008e6c3a4140319406b3e7f6
\ No newline at end of file
+b4a9165d9e4724581ccb05beb32488329995d60a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
index 2701727..c575bed 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-35732380f5f09a08bb7f9a2205f19085e53a4052
\ No newline at end of file
+0b3696e9515c2e879f8bf6de7d4d2243e699ac71
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 73797e6..b6c414073 100644
--- a/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_extension_keychain_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-397474e8c0dd5293af7a7f6f26434e5ca2b59c64
\ No newline at end of file
+96b81892f5ce0e6395f87397496120a5f8849b6a
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
index 14a665b..866e598 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-101205303d2c17a9dc5591f8849d32469929160a
\ No newline at end of file
+35ea72cb8e9d56cc22c29c70a0d53af3ccd80ff9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
index f6559e77..e5f1489a 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-4038dccdfe19430698c1340b48e717f8c9252a8e
\ No newline at end of file
+afbf4b97ea64e030d79b639df9d05e3c032d2112
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
index 4991b12..be9d69d 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-28a3ebd759f8bef3c337987146336ce2f9e5e6c8
\ No newline at end of file
+12dcddc1955cb58959dee0a719fbcbb67e418b69
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 193d62b..317c4fa7 100644
--- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-9e88251ba4fc7c1c3ee65a61b22b67a90da17adc
\ No newline at end of file
+587e9a4e151fc9891dd591fc7600d03d418d19ec
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
index 37fe181..079cd99 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-1ac651b062e89781f576d61d6045601d11f80875
\ No newline at end of file
+7139bca4602024927c1530e2305bca9e562bb40d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
index 8672793e..6399d65 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-4c6860474282ec8584412f8bfdca1965731875c7
\ No newline at end of file
+486e7b0d497bc2c06b22c550772b41fb37bb0b88
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
index 22fddc7..eba99bc 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-abd39dfb0d9778af18bf92365d84423b2c38727e
\ No newline at end of file
+4452ebe2ed93cde10faaf7ea3a7d9c88f6306a27
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 77d3658..9ac0759 100644
--- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-1a6a35330cb620487c8b21e54c1c61f29ea13e6a
\ No newline at end of file
+113e600f80a6a2c8db72ace42f858beb09b9c604
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
index f5810f0..5f4e09a 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-0b9ff11616b0b416d1c1194918381d04a7ca49aa
\ No newline at end of file
+49cbdc511da13233e76edcf246169f6c9c8c0b7d
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
index 05b1af7..c7d9b63b 100644
--- a/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/chrome_test_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-dc9a8dc06a110bfacc4aa5922d039eee1889e414
\ No newline at end of file
+a210c524dcb96f7c70e719af4b466124cb0bf92e
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
index 899691a..c18d0ec 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-b6155031179442c41cbd6fc6abfcc77a39afc82a
\ No newline at end of file
+623d2f48010828305449b2c29abdadd0b941c8a2
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
index 9692f6c..1083b4f 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-4f8c8aec2a092797034bdaf63e0ecac632bd2307
\ No newline at end of file
+68f32e7a344f0396b3fa45b7ed42549cddb6f8c0
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
index ef73cca..db705fc5 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-dcda131bdb8b50a515655d3557422a2221cb4759
\ No newline at end of file
+430bdc490ed579ac69ae14ea7c67b4288e7edc94
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 784b558..396a5994 100644
--- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-ae0ccbbae133359cd97ddab574ccaa1b1e1ea645
\ No newline at end of file
+b4c5254365bf7bf8f2b343b38b59371a971ffab7
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
index 370b327e..2399952 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@
-6cc4fa741c40bb222eac0bec88f2b1bd31ad7cbc
\ No newline at end of file
+aba6261eaf96c6ee347fd1d139a69cb4ea380672
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
index 0f72015..03c644c 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios_asan.zip.sha1
@@ -1 +1 @@
-378e9cb8c94d4fbbe553ba4e8aa178d9dfc28e86
\ No newline at end of file
+a4e6138a01cf75c031c3012be858beae237f9ab9
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
index 26c24847..8c10fdf 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@
-7be67e92b53a11507b19e63f121141c98cceb542
\ No newline at end of file
+5fa125f408ed8468ca9f6c19cd0032a5ea464163
\ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
index 8934364..98c38df9 100644
--- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
+++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator_asan.zip.sha1
@@ -1 +1 @@
-24eb35329e121786a22102741e4b9aa7643a3eff
\ No newline at end of file
+9c3a210fa0bbbbb8429f3adbd11efe958ef44859
\ No newline at end of file
diff --git a/ios_internal b/ios_internal
index 795a986..5461662 160000
--- a/ios_internal
+++ b/ios_internal
@@ -1 +1 @@
-Subproject commit 795a986ba94ef9eb51ae7df5234a2c42dc8643d4
+Subproject commit 546166297e66e1c41ed01388ee445f4011bbd084
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src
index 361e879..c4d9ab5 160000
--- a/third_party/compiler-rt/src
+++ b/third_party/compiler-rt/src
@@ -1 +1 @@
-Subproject commit 361e87916c9c4822c77ea70d4723823e2b6574c1
+Subproject commit c4d9ab5e7cf25d4a8dfe1159267036a6eb2648a4
diff --git a/third_party/dawn b/third_party/dawn
index ce4c6d5..3143cb3 160000
--- a/third_party/dawn
+++ b/third_party/dawn
@@ -1 +1 @@
-Subproject commit ce4c6d59514cbba545859dc5788eb8e154c1db31
+Subproject commit 3143cb32483ee3226a4665661957650a0ab54ea7
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src
index b2274b5..fa03707 160000
--- a/third_party/devtools-frontend/src
+++ b/third_party/devtools-frontend/src
@@ -1 +1 @@
-Subproject commit b2274b582648b9f295fb8bf1c4726eb5e0079dd9
+Subproject commit fa037075c43e9fcc6543d7fa001cffa58e7e0abf
diff --git a/third_party/protobuf/BUILD.gn b/third_party/protobuf/BUILD.gn
index 3a58c48..b2efa8253 100644
--- a/third_party/protobuf/BUILD.gn
+++ b/third_party/protobuf/BUILD.gn
@@ -14,7 +14,10 @@
 
 config("protobuf_config") {
   include_dirs = [ "src" ]
-  defines = [ "GOOGLE_PROTOBUF_NO_RTTI" ]
+  defines = [
+    "GOOGLE_PROTOBUF_NO_RTTI",
+    "PROTOBUF_INTERNAL_BOUNDS_CHECK_MODE_ABORT",
+  ]
   if (!is_win) {
     defines += [ "HAVE_PTHREAD" ]
   }
diff --git a/third_party/skia b/third_party/skia
index fb66e39..466b248 160000
--- a/third_party/skia
+++ b/third_party/skia
@@ -1 +1 @@
-Subproject commit fb66e398427555675a4c616f184fde655a3f14e5
+Subproject commit 466b248469e852daebce53871dc88295c5ecb212
diff --git a/third_party/spirv-tools/src b/third_party/spirv-tools/src
index d0bcfb2..392b489 160000
--- a/third_party/spirv-tools/src
+++ b/third_party/spirv-tools/src
@@ -1 +1 @@
-Subproject commit d0bcfb229123d542e9fda847bf2f3d90e8d38721
+Subproject commit 392b4893c4955125c1873c33a97f2a8ee8363bd3
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps
index e1c9d59..dd883ff 160000
--- a/third_party/vulkan-deps
+++ b/third_party/vulkan-deps
@@ -1 +1 @@
-Subproject commit e1c9d596803856d1f67833d1e1d29081e26298d1
+Subproject commit dd883ffe3224c33ad5d1303764a1583bd37777d8
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src
index 20c577e..3682d20 160000
--- a/third_party/vulkan-validation-layers/src
+++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@
-Subproject commit 20c577e6e0e90f9e531d044816c15c48f0b5f913
+Subproject commit 3682d20aecdb4e005cd2785a0429cc357047ad12
diff --git a/third_party/webrtc b/third_party/webrtc
index b12e03f..620b3a2 160000
--- a/third_party/webrtc
+++ b/third_party/webrtc
@@ -1 +1 @@
-Subproject commit b12e03f7671717aedaf04e598d4da88011e0542e
+Subproject commit 620b3a2805f198ef797bb78098883d9cf3c17604
diff --git a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
index e6aadd9..2972f2e 100644
--- a/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
+++ b/ui/android/java/src/org/chromium/ui/widget/AnchoredPopupWindow.java
@@ -248,6 +248,290 @@
     private @StyleRes int mAnimationStyleId;
     private boolean mAnimateFromAnchor;
 
+    /** A builder for {@link AnchoredPopupWindow} instances. */
+    public static class Builder {
+        private final Context mContext;
+        private final View mRootView;
+        private final Supplier<View> mContentViewCreator;
+        private final RectProvider mAnchorRectProvider;
+        private final Drawable mBackground;
+
+        private @Nullable RectProvider mViewportRectProvider;
+        private @Nullable OnDismissListener mOnDismissListener;
+        private @Nullable OnTouchListener mTouchListener;
+        private @Nullable LayoutObserver mLayoutObserver;
+        private int mMarginPx;
+        private int mMaxWidthPx;
+        private int mDesiredContentWidthPx;
+        private int mDesiredContentHeightPx;
+
+        @VerticalOrientation
+        private int mPreferredVerticalOrientation = VerticalOrientation.MAX_AVAILABLE_SPACE;
+
+        @HorizontalOrientation
+        private int mPreferredHorizontalOrientation = HorizontalOrientation.MAX_AVAILABLE_SPACE;
+
+        private boolean mDismissOnTouchInteraction;
+        private boolean mVerticalOverlapAnchor;
+        private boolean mHorizontalOverlapAnchor;
+        private boolean mUpdateOrientationOnChange;
+        private boolean mSmartAnchorWithMaxWidth;
+        private boolean mAllowNonTouchableSize;
+        private @StyleRes int mAnimationStyleId;
+        private boolean mAnimateFromAnchor;
+        private boolean mFocusable;
+        private float mElevation;
+        private boolean mTouchModal;
+        private boolean mOutsideTouchable;
+        private boolean mIsOutsideTouchableSet;
+
+        /**
+         * Constructs an {@link AnchoredPopupWindow} instance.
+         *
+         * @param context Context to draw resources from.
+         * @param rootView The {@link View} to use for size calculations and for display.
+         * @param background The background {@link Drawable} to use for the popup.
+         * @param contentViewCreator The supplier for the content view to set on the popup. The view
+         *     is expected to be a {@link ViewGroup}.
+         * @param anchorRectProvider The {@link RectProvider} that will provide the {@link Rect}
+         *     this popup attaches and orients to. The coordinates in the {@link Rect} are expected
+         *     to be screen coordinates.
+         * @deprecated Use the {@link Builder} to create the popup instead.
+         */
+        public Builder(
+                Context context,
+                View rootView,
+                Drawable background,
+                Supplier<View> contentViewCreator,
+                RectProvider anchorRectProvider) {
+            mContext = context;
+            mRootView = rootView;
+            mBackground = background;
+            mContentViewCreator = contentViewCreator;
+            mAnchorRectProvider = anchorRectProvider;
+        }
+
+        /**
+         * @param viewportRectProvider The {@link RectProvider} that provides the {@link Rect} for
+         *     the visible viewpoint. If null, the window coordinates of the root view will be used.
+         */
+        public Builder setViewportRectProvider(RectProvider viewportRectProvider) {
+            mViewportRectProvider = viewportRectProvider;
+            return this;
+        }
+
+        /**
+         * @param onDismissListener A listener to be called when the popup is dismissed.
+         */
+        public Builder addOnDismissListener(OnDismissListener onDismissListener) {
+            mOnDismissListener = onDismissListener;
+            return this;
+        }
+
+        /**
+         * @param onTouchListener A callback for all touch events being dispatched to the popup.
+         */
+        public Builder setTouchInterceptor(OnTouchListener onTouchListener) {
+            mTouchListener = onTouchListener;
+            return this;
+        }
+
+        /**
+         * @param layoutObserver The observer to be notified of layout changes.
+         */
+        public Builder setLayoutObserver(LayoutObserver layoutObserver) {
+            mLayoutObserver = layoutObserver;
+            return this;
+        }
+
+        /**
+         * @param margin The vertical and horizontal margin in pixels.
+         */
+        public Builder setMargin(int margin) {
+            mMarginPx = margin;
+            return this;
+        }
+
+        /**
+         * @param maxWidth The max width for the popup.
+         */
+        public Builder setMaxWidth(int maxWidth) {
+            mMaxWidthPx = maxWidth;
+            return this;
+        }
+
+        /**
+         * @param width The desired width for the content of the popup window in pixel.
+         * @param height The desired height for the content of the popup window in pixel.
+         */
+        public Builder setDesiredContentSize(int width, int height) {
+            mDesiredContentWidthPx = width;
+            mDesiredContentHeightPx = height;
+            return this;
+        }
+
+        /**
+         * @param orientation The vertical orientation preferred.
+         */
+        public Builder setPreferredVerticalOrientation(@VerticalOrientation int orientation) {
+            mPreferredVerticalOrientation = orientation;
+            return this;
+        }
+
+        /**
+         * @param orientation The horizontal orientation preferred.
+         */
+        public Builder setPreferredHorizontalOrientation(@HorizontalOrientation int orientation) {
+            mPreferredHorizontalOrientation = orientation;
+            return this;
+        }
+
+        /**
+         * @param dismiss Whether or not to dismiss this popup when the screen is tapped.
+         */
+        public Builder setDismissOnTouchInteraction(boolean dismiss) {
+            mDismissOnTouchInteraction = dismiss;
+            return this;
+        }
+
+        /**
+         * @param overlap Whether the popup should vertically overlap the anchor.
+         */
+        public Builder setVerticalOverlapAnchor(boolean overlap) {
+            mVerticalOverlapAnchor = overlap;
+            return this;
+        }
+
+        /**
+         * @param overlap Whether the popup should horizontally overlap the anchor.
+         */
+        public Builder setHorizontalOverlapAnchor(boolean overlap) {
+            mHorizontalOverlapAnchor = overlap;
+            return this;
+        }
+
+        /**
+         * @param update If set to true, orientation will be updated every time that the {@link
+         *     OnRectChanged} is called.
+         */
+        public Builder setUpdateOrientationOnChange(boolean update) {
+            mUpdateOrientationOnChange = update;
+            return this;
+        }
+
+        /**
+         * @param smartAnchor Whether the popup should smartAnchor the anchor.
+         */
+        public Builder setSmartAnchorWithMaxWidth(boolean smartAnchor) {
+            mSmartAnchorWithMaxWidth = smartAnchor;
+            return this;
+        }
+
+        /**
+         * @param allow Whether to allow the popup to have a small non-touchable size.
+         */
+        public Builder setAllowNonTouchableSize(boolean allow) {
+            mAllowNonTouchableSize = allow;
+            return this;
+        }
+
+        /**
+         * @param animationStyleId The id of the animation style.
+         */
+        public Builder setAnimationStyle(@StyleRes int animationStyleId) {
+            mAnimationStyleId = animationStyleId;
+            return this;
+        }
+
+        /**
+         * @param animateFromAnchor Whether the popup should animator from anchor point.
+         */
+        public Builder setAnimateFromAnchor(boolean animateFromAnchor) {
+            mAnimateFromAnchor = animateFromAnchor;
+            return this;
+        }
+
+        /**
+         * @param focusable True if the popup is focusable, false otherwise.
+         */
+        public Builder setFocusable(boolean focusable) {
+            mFocusable = focusable;
+            return this;
+        }
+
+        /**
+         * @param elevation The elevation of the popup.
+         */
+        public Builder setElevation(float elevation) {
+            mElevation = elevation;
+            return this;
+        }
+
+        /**
+         * @param touchModal True if the popup is touch modal, false otherwise.
+         */
+        public Builder setTouchModal(boolean touchModal) {
+            mTouchModal = touchModal;
+            return this;
+        }
+
+        /**
+         * @param touchable True if the popup is outside touchable, false otherwise.
+         */
+        public Builder setOutsideTouchable(boolean touchable) {
+            mOutsideTouchable = touchable;
+            mIsOutsideTouchableSet = true;
+            return this;
+        }
+
+        /**
+         * @return A new {@link AnchoredPopupWindow}.
+         */
+        public AnchoredPopupWindow build() {
+            return new AnchoredPopupWindow(this);
+        }
+    }
+
+    private AnchoredPopupWindow(Builder builder) {
+        this(
+                builder.mContext,
+                builder.mRootView,
+                builder.mBackground,
+                builder.mContentViewCreator,
+                builder.mAnchorRectProvider,
+                builder.mViewportRectProvider);
+
+        if (builder.mOnDismissListener != null) {
+            addOnDismissListener(builder.mOnDismissListener);
+        }
+        setTouchInterceptor(builder.mTouchListener);
+        setLayoutObserver(builder.mLayoutObserver);
+        setMargin(builder.mMarginPx);
+        if (builder.mMaxWidthPx > 0) setMaxWidth(builder.mMaxWidthPx);
+        if (builder.mDesiredContentWidthPx != 0 || builder.mDesiredContentHeightPx != 0) {
+            updateDesiredContentSize(
+                    builder.mDesiredContentWidthPx, builder.mDesiredContentHeightPx, false);
+        }
+        setPreferredVerticalOrientation(builder.mPreferredVerticalOrientation);
+        setPreferredHorizontalOrientation(builder.mPreferredHorizontalOrientation);
+        setDismissOnTouchInteraction(builder.mDismissOnTouchInteraction);
+        setVerticalOverlapAnchor(builder.mVerticalOverlapAnchor);
+        setHorizontalOverlapAnchor(builder.mHorizontalOverlapAnchor);
+        setUpdateOrientationOnChange(builder.mUpdateOrientationOnChange);
+        setSmartAnchorWithMaxWidth(builder.mSmartAnchorWithMaxWidth);
+        setAllowNonTouchableSize(builder.mAllowNonTouchableSize);
+        if (builder.mAnimationStyleId != 0) {
+            setAnimationStyle(builder.mAnimationStyleId);
+        }
+        setAnimateFromAnchor(builder.mAnimateFromAnchor);
+        setFocusable(builder.mFocusable);
+        setElevation(builder.mElevation);
+        setTouchModal(builder.mTouchModal);
+        if (builder.mIsOutsideTouchableSet) {
+            setOutsideTouchable(builder.mOutsideTouchable);
+        }
+    }
+
     /**
      * Constructs an {@link AnchoredPopupWindow} instance.
      *
@@ -258,8 +542,7 @@
      * @param anchorRectProvider The {@link RectProvider} that will provide the {@link Rect} this
      *     popup attaches and orients to. The coordinates in the {@link Rect} are expected to be
      *     screen coordinates.
-     * @deprecated Use {@link #AnchoredPopupWindow(Context, View, Drawable, Supplier, RectProvider,
-     *     RectProvider)} instead.
+     * @deprecated Use the {@link Builder} to create the popup instead.
      */
     @Deprecated
     public AnchoredPopupWindow(
@@ -284,15 +567,16 @@
      *     screen coordinates.
      * @param viewportRectProvider The {@link RectProvider} that provides the {@link Rect} for the
      *     visible viewpoint. If null, the window coordinates of the root view will be used.
+     * @deprecated Use the {@link Builder} to create the popup instead.
      */
+    @Deprecated
     public AnchoredPopupWindow(
             Context context,
             View rootView,
-            Drawable background,
+            @Nullable Drawable background,
             Supplier<View> contentViewCreator,
             RectProvider anchorRectProvider,
             @Nullable RectProvider viewportRectProvider) {
-
         mContext = context;
         mRootView = rootView.getRootView();
         mContentViewCreator = contentViewCreator;
@@ -353,8 +637,10 @@
      * Sets the {@link LayoutObserver} for this AnchoredPopupWindow.
      *
      * @param layoutObserver The observer to be notified of layout changes.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
-    public void setLayoutObserver(LayoutObserver layoutObserver) {
+    @Deprecated
+    public void setLayoutObserver(@Nullable LayoutObserver layoutObserver) {
         mLayoutObserver = layoutObserver;
     }
 
@@ -369,6 +655,7 @@
     /**
      * @param onDismissListener A listener to be called when the popup is dismissed.
      * @see PopupWindow#setOnDismissListener(OnDismissListener)
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
     public void addOnDismissListener(OnDismissListener onDismissListener) {
         mDismissListeners.addObserver(onDismissListener);
@@ -386,7 +673,9 @@
      * @param dismiss Whether or not to dismiss this popup when the screen is tapped. This will
      *     happen for both taps inside and outside the popup except when a tap is handled by child
      *     views. The default is {@code false}.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setDismissOnTouchInteraction(boolean dismiss) {
         mDismissOnTouchInteraction = dismiss;
         mPopupWindow.setOutsideTouchable(mDismissOnTouchInteraction);
@@ -400,7 +689,9 @@
      *
      * @param touchable Whether or not to notify the popup when an outside touch happens. The
      *     default is {@code false}.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setOutsideTouchable(boolean touchable) {
         mPopupWindow.setOutsideTouchable(touchable);
     }
@@ -410,7 +701,9 @@
      * above or below the anchor. This should be called before the popup is shown.
      *
      * @param orientation The vertical orientation preferred.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setPreferredVerticalOrientation(@VerticalOrientation int orientation) {
         mPreferredVerticalOrientation = orientation;
     }
@@ -420,7 +713,9 @@
      * as centered with respect to the anchor. This should be called before the popup is shown.
      *
      * @param orientation The horizontal orientation preferred.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setPreferredHorizontalOrientation(@HorizontalOrientation int orientation) {
         mPreferredHorizontalOrientation = orientation;
     }
@@ -430,7 +725,9 @@
      * Setting this style will take precedence over {@link #setAnimateFromAnchor(boolean)}.
      *
      * @param animationStyleId The id of the animation style.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setAnimationStyle(int animationStyleId) {
         mAnimationStyleId = animationStyleId;
         mPopupWindow.setAnimationStyle(animationStyleId);
@@ -442,7 +739,9 @@
      * #setAnimationStyle(int)}, this method will have no effect.
      *
      * @param animateFromAnchor Whether the popup should animator from anchor point.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setAnimateFromAnchor(boolean animateFromAnchor) {
         mAnimateFromAnchor = animateFromAnchor;
     }
@@ -450,7 +749,10 @@
     /**
      * If set to true, orientation will be updated every time that the {@link OnRectChanged} is
      * called.
+     *
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setUpdateOrientationOnChange(boolean updateOrientationOnChange) {
         mUpdateOrientationOnChange = updateOrientationOnChange;
     }
@@ -459,7 +761,9 @@
      * Changes the focusability of the popup. See {@link PopupWindow#setFocusable(boolean)}.
      *
      * @param focusable True if the popup is focusable, false otherwise.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setFocusable(boolean focusable) {
         mPopupWindow.setFocusable(focusable);
     }
@@ -470,7 +774,9 @@
      *
      * @param touchModal True to sent all outside touches to this window, false to other windows
      *     behind it.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setTouchModal(boolean touchModal) {
         mPopupWindow.setTouchModal(touchModal);
     }
@@ -479,7 +785,9 @@
      * Sets the margin for the popup window. This should be called before the popup is shown.
      *
      * @param margin The margin in pixels.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setMargin(int margin) {
         mMarginPx = margin;
     }
@@ -488,7 +796,9 @@
      * Sets the max width for the popup. This should be called before the popup is shown.
      *
      * @param maxWidth The max width for the popup.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setMaxWidth(int maxWidth) {
         final float density = mRootView.getResources().getDisplayMetrics().density;
         mMaxWidthPx = Math.max(maxWidth, (int) Math.ceil(density * MIN_TOUCHABLE_WIDTH_DIP));
@@ -499,7 +809,9 @@
      * false. This should be called before the popup is shown.
      *
      * @param overlap Whether the popup should overlap the anchor.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setHorizontalOverlapAnchor(boolean overlap) {
         mHorizontalOverlapAnchor = overlap;
     }
@@ -509,7 +821,9 @@
      * This should be called before the popup is shown.
      *
      * @param overlap Whether the popup should overlap the anchor.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setVerticalOverlapAnchor(boolean overlap) {
         mVerticalOverlapAnchor = overlap;
     }
@@ -524,12 +838,19 @@
      * <p>This should be called before the popup is shown.
      *
      * @param smartAnchor Whether the popup should smartAnchor the anchor.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setSmartAnchorWithMaxWidth(boolean smartAnchor) {
         mSmartAnchorWithMaxWidth = smartAnchor;
     }
 
-    /** Sets the elevation of the popup. */
+    /**
+     * Sets the elevation of the popup.
+     *
+     * @deprecated Use the {@link Builder} to set this value during construction.
+     */
+    @Deprecated
     public void setElevation(float elevation) {
         mPopupWindow.setElevation(elevation);
     }
@@ -540,11 +861,11 @@
      * <p>You can call this method only before {@link #show()} as it does not trigger relayout,
      * whereas {@link #setDesiredContentSize(int, int)} triggers it.
      *
-     * @deprecated Use {@link #setDesiredContentSize(int, int)} instead.
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
     @Deprecated
     public void setDesiredContentWidth(int width) {
-        mDesiredContentWidth = width;
+        updateDesiredContentSize(width, mDesiredContentHeight, false);
     }
 
     /**
@@ -556,14 +877,40 @@
      *
      * <p>This method triggers an update of the layout if the popup is already shown. You can call
      * it to resize the popup at any time.
+     *
+     * @deprecated Use the {@link Builder} to set this value during construction.
      */
+    @Deprecated
     public void setDesiredContentSize(int width, int height) {
-        mDesiredContentWidth = width;
-        mDesiredContentHeight = height;
-        updatePopupLayout();
+        updateDesiredContentSize(width, height, true);
     }
 
-    /** Sets whether to allow the popup to have a small non-touchable size. The default is false. */
+    /**
+     * Sets the desired dimensions for the content of the popup window.
+     *
+     * <p>Pass 0 to either dimension to have it determine its own size. The popup window will be
+     * shown in this exact size unless certain constraint presents (e.g. desiredContentWidth >
+     * maxWidthPx).
+     *
+     * <p>This method triggers an update of the layout if the popup is already shown. You can call
+     * it to resize the popup at any time.
+     *
+     * @param height The desired height for the popup.
+     * @param width The desired width for the popup.
+     * @param updateLayout Whether trigger layout update
+     */
+    public void updateDesiredContentSize(int width, int height, boolean updateLayout) {
+        mDesiredContentWidth = width;
+        mDesiredContentHeight = height;
+        if (updateLayout) updatePopupLayout();
+    }
+
+    /**
+     * Sets whether to allow the popup to have a small non-touchable size. The default is false.
+     *
+     * @deprecated Use the {@link Builder} to set this value during construction.
+     */
+    @Deprecated
     public void setAllowNonTouchableSize(boolean allowNonTouchableSize) {
         mAllowNonTouchableSize = allowNonTouchableSize;
     }
diff --git a/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java b/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
index c24e0071..e4f8cfb8 100644
--- a/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
+++ b/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
@@ -18,7 +18,9 @@
 import static org.mockito.Mockito.when;
 
 import android.app.Activity;
+import android.graphics.Color;
 import android.graphics.Rect;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.util.DisplayMetrics;
 import android.view.View;
@@ -72,6 +74,7 @@
 
     private FrameLayout mContentView;
     private Activity mActivity;
+    private Drawable mDrawable;
 
     @Before
     public void setUp() {
@@ -82,6 +85,7 @@
         mWindowRect = new Rect(0, 0, mRootWidth, mRootHeight);
 
         mActivity = Robolectric.buildActivity(Activity.class).get();
+        mDrawable = new ColorDrawable(Color.RED);
 
         mContentView = new FrameLayout(mActivity);
         mContentView.setMinimumWidth(mPopupWidth);
@@ -922,7 +926,7 @@
                 new AnchoredPopupWindow(
                         mActivity,
                         view,
-                        null,
+                        mDrawable,
                         () -> contentView,
                         anchorRectProvider,
                         visibleWebContentsRectSupplier);
@@ -938,6 +942,56 @@
         verify(mockPopup, times(1)).update(anyInt(), anyInt(), anyInt(), anyInt());
     }
 
+    // This is a temporary test that used to ensure the completeness of builder migraiton.
+    @Test
+    public void testBuilder() {
+        // Set up for test case, so we have a mock popup window.
+        UiWidgetFactory mockFactory = mock(UiWidgetFactory.class);
+        UiWidgetFactory.setInstance(mockFactory);
+        PopupWindow mockPopup = mock(PopupWindow.class);
+        doReturn(mockPopup).when(mockFactory).createPopupWindow(any());
+
+        View view = mock(View.class, Answers.RETURNS_DEEP_STUBS);
+        DisplayMetrics fakeMetrics = new DisplayMetrics();
+        fakeMetrics.density = 1;
+        when(view.getRootView().getResources().getDisplayMetrics()).thenReturn(fakeMetrics);
+        when(view.getRootView().isAttachedToWindow()).thenReturn(true);
+        RectProvider anchorRectProvider = new RectProvider(new Rect(0, 0, 1000, 1000));
+        RectProvider viewportRectProvider = new RectProvider(new Rect(0, 100, 1000, 900));
+        PopupWindow.OnDismissListener dismissListener = mock(PopupWindow.OnDismissListener.class);
+        View.OnTouchListener touchListener = mock(View.OnTouchListener.class);
+        AnchoredPopupWindow.LayoutObserver layoutObserver =
+                mock(AnchoredPopupWindow.LayoutObserver.class);
+        when(mockPopup.getContentView()).thenReturn(mContentView);
+        when(mockPopup.isFocusable()).thenReturn(true);
+        when(mockPopup.getElevation()).thenReturn(20f);
+
+        new AnchoredPopupWindow.Builder(
+                        mActivity, view, mDrawable, () -> mContentView, anchorRectProvider)
+                .setViewportRectProvider(viewportRectProvider)
+                .addOnDismissListener(dismissListener)
+                .setTouchInterceptor(touchListener)
+                .setLayoutObserver(layoutObserver)
+                .setMargin(10)
+                .setMaxWidth(200)
+                .setDesiredContentSize(150, 300)
+                .setPreferredVerticalOrientation(VerticalOrientation.ABOVE)
+                .setPreferredHorizontalOrientation(HorizontalOrientation.CENTER)
+                .setDismissOnTouchInteraction(true)
+                .setVerticalOverlapAnchor(true)
+                .setHorizontalOverlapAnchor(true)
+                .setUpdateOrientationOnChange(true)
+                .setSmartAnchorWithMaxWidth(true)
+                .setAllowNonTouchableSize(true)
+                .setAnimationStyle(R.style.DropdownPopupWindow)
+                .setAnimateFromAnchor(true)
+                .setFocusable(true)
+                .setElevation(20f)
+                .build();
+
+        verify(mockFactory).createPopupWindow(mActivity);
+    }
+
     private void setDefaultValueForAnchoredPopup() {
         mPaddingX = 0;
         mPaddingY = 0;
@@ -994,6 +1048,6 @@
         when(view.getRootView().getResources().getDisplayMetrics()).thenReturn(fakeMetrics);
         when(view.getRootView().isAttachedToWindow()).thenReturn(true);
         RectProvider provider = new RectProvider(new Rect(0, 0, 0, 0));
-        return new AnchoredPopupWindow(mActivity, view, null, mContentView, provider);
+        return new AnchoredPopupWindow(mActivity, view, mDrawable, mContentView, provider);
     }
 }