diff --git a/DEPS b/DEPS
index 81c9d7a..ce55f7e 100644
--- a/DEPS
+++ b/DEPS
@@ -289,7 +289,7 @@
   # The Rust toolchain sources. It is a version tag from an instance of the
   # CIPD `chromium/third_party/rust_src` package. This field is written by
   # //tools/clang/scripts/upload_revision.py and shouldn't be updated by hand.
-  'rust_toolchain_version': 'version:2@2023-01-17',
+  'rust_toolchain_version': 'version:2@2022-12-09',
 
   'android_git': 'https://android.googlesource.com',
   'aomedia_git': 'https://aomedia.googlesource.com',
@@ -304,15 +304,15 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': 'da5034f9d117ac2bc6ee62af6530e114c874d443',
+  'skia_revision': 'c4b171fe5668a522c222b0777afefcb3cbd8a2ac',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': 'd0578efe564af5dbf3c8b39e6c78cbed301775aa',
+  'v8_revision': '7256aca77c6c1a7b4b9007dabd5fd74e8dac1b47',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '660e4a7c0d4f919b58a7ef22903aad2efabefa1d',
+  'angle_revision': 'f26cfec911f775949a9179a4f1b65da021340945',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -383,7 +383,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': '25650e0d5d2db67fc0e1b670dd81023775124b41',
+  'devtools_frontend_revision': '9f3432a40c557b3faa3da01fc2ef84e4cf60e66a',
   # 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.
@@ -419,7 +419,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': '2cf9764e450fa31846943764ec5e3c518615cf1d',
+  'dawn_revision': '58dd079e466579f5c4c5fe35d41aff9bd16cd555',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -459,7 +459,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.
-  'resultdb_version': 'git_revision:39e20ee396fe4a84eaa7f7d389e5659198c12e87',
+  'resultdb_version': 'git_revision:ac21cf9883af7d1bf6d60e8a7448918eb3b6aa18',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -770,7 +770,7 @@
 
   'src/clank': {
     'url': 'https://chrome-internal.googlesource.com/clank/internal/apps.git' + '@' +
-    'fe129212b094323fe75657a1cc566554d0e23de9',
+    '2684540a00a1b31d6bc5a5d9e55021562cd10ce3',
     'condition': 'checkout_android and checkout_src_internal',
   },
 
@@ -959,7 +959,7 @@
     'packages': [
       {
           'package': 'chromium/third_party/androidx',
-          'version': 'aYKU5k2YMftLAo4DCcErxGnD4lv2Mumfhrh8DR_wAnIC',
+          'version': '3nXDIlFQ-oAo4egDVeC0GbueTl4mOfPrEDzT5jgDEK8C',
       },
     ],
     'condition': 'checkout_android',
@@ -1204,13 +1204,13 @@
   },
 
   'src/third_party/depot_tools':
-    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '00be3f079a1bd376c594d348ebf7d7021a9de245',
+    Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'c710e2d56a813d27d2368eb0e7e292bd2f59519f',
 
   'src/third_party/devtools-frontend/src':
     Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'),
 
   'src/third_party/devtools-frontend-internal': {
-      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + '4a9880edc819ab88d1a7ffc67a73c2616538b575',
+      'url': 'https://chrome-internal.googlesource.com/devtools/devtools-internal.git' + '@' + 'ac4f163294daa437967536cd83b3ede02f39a619',
     'condition': 'checkout_src_internal',
   },
 
@@ -1655,7 +1655,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '61eeba8d065b8fc69f9dee9b36bc94d9d6a0293c',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + 'ee03e391a1003e8cdc7ce7e07f14b6872883fd1c',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1689,13 +1689,13 @@
   },
 
   'src/third_party/re2/src':
-    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + 'ba541565b4fbe1684d4b98695ec0b6d6c13ba98b',
+    Var('chromium_git') + '/external/github.com/google/re2.git' + '@' + '8afcf7fcc481692197e33612446d69e8f5777c54',
 
   'src/third_party/r8': {
       'packages': [
           {
               'package': 'chromium/third_party/r8',
-              'version': 'LH65AcDi3ysVLfebZhbSxN3YUGUV62qpqLIlrV6Znm8C',
+              'version': 'SCuPfdKTpEJfVbWzckpmWx125Zf3pO-4RitqcfXX-RQC',
           },
       ],
       'condition': 'checkout_android',
@@ -1840,7 +1840,7 @@
     Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + 'ad8abf400d8d23fb04bdcf1f654bccb6625db7b4',
 
   'src/third_party/webrtc':
-    Var('webrtc_git') + '/src.git' + '@' + 'cc1c932f104196022f907e034b88266c1bdaaf4e',
+    Var('webrtc_git') + '/src.git' + '@' + '5671c6410395d6bc3f6041cc15d16ca256688c8e',
 
   # 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.
@@ -1888,7 +1888,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/mac-amd64',
-          'version': 'AUahse3CmKx-dL05gv51smOfDW3bSRbiOmWly3oDmyQC',
+          'version': '8qZDLAMyGda5EhgtPxm1HRsnplhGtP0Mny-vLqo--TcC',
         },
       ],
       'dep_type': 'cipd',
@@ -1910,7 +1910,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@024bd0d0d5a44a4b6dca4c5c412f1dd86b30c95b',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6d740d36bf274cefca0698dab445cdf541d50f7c',
     'condition': 'checkout_src_internal',
   },
 
@@ -1940,7 +1940,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/help_app/app',
-        'version': 'DzLMEi52JC5lvw49dQ77zbprCvDk689lWS94QUAkP_MC',
+        'version': 'lhhymPxLgpNiHKsHFh4rUwx4vPVqpd_QMBZGIhHePusC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
@@ -1962,7 +1962,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/projector_app/app',
-        'version': '9_YPq-7rVC3g0cuAG5BJLkP3A-_Fa5DLqssVwS-74rAC',
+        'version': 'mOGkd2s46jvj37CK6ZuCIX2LSetf3yzXCPiX09K5XE8C',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/BUILD.gn b/android_webview/BUILD.gn
index e91c6c8..0c8c5189 100644
--- a/android_webview/BUILD.gn
+++ b/android_webview/BUILD.gn
@@ -609,6 +609,7 @@
     "java/src/org/chromium/android_webview/JsResultHandler.java",
     "java/src/org/chromium/android_webview/JsResultReceiver.java",
     "java/src/org/chromium/android_webview/ManifestMetadataUtil.java",
+    "java/src/org/chromium/android_webview/NoopSafeModeAction.java",
     "java/src/org/chromium/android_webview/NullAwViewMethods.java",
     "java/src/org/chromium/android_webview/OverScrollGlow.java",
     "java/src/org/chromium/android_webview/PopupTouchHandleDrawable.java",
diff --git a/android_webview/browser/gfx/display_scheduler_webview.h b/android_webview/browser/gfx/display_scheduler_webview.h
index 2df8ec5..4248af4b 100644
--- a/android_webview/browser/gfx/display_scheduler_webview.h
+++ b/android_webview/browser/gfx/display_scheduler_webview.h
@@ -85,7 +85,8 @@
 
   // Due to destruction order in viz::Display this might be not safe to use in
   // destructor of this class.
-  const raw_ptr<OverlaysInfoProvider> overlays_info_provider_;
+  const raw_ptr<OverlaysInfoProvider, DanglingUntriaged>
+      overlays_info_provider_;
 
   base::ScopedObservation<viz::SurfaceManager, viz::SurfaceObserver>
       surface_manager_observation_{this};
diff --git a/android_webview/java/src/org/chromium/android_webview/BrowserSafeModeActionList.java b/android_webview/java/src/org/chromium/android_webview/BrowserSafeModeActionList.java
index a02fcfc..85c3373 100644
--- a/android_webview/java/src/org/chromium/android_webview/BrowserSafeModeActionList.java
+++ b/android_webview/java/src/org/chromium/android_webview/BrowserSafeModeActionList.java
@@ -23,5 +23,6 @@
             new VariationsSeedSafeModeAction(),
             new AndroidAutofillSafeModeAction(),
             new ChromeAutocompleteSafeModeAction(),
+            new NoopSafeModeAction(),
     };
 }
diff --git a/android_webview/java/src/org/chromium/android_webview/NoopSafeModeAction.java b/android_webview/java/src/org/chromium/android_webview/NoopSafeModeAction.java
new file mode 100644
index 0000000..d728da90
--- /dev/null
+++ b/android_webview/java/src/org/chromium/android_webview/NoopSafeModeAction.java
@@ -0,0 +1,32 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.android_webview;
+
+import androidx.annotation.NonNull;
+
+import org.chromium.android_webview.common.SafeModeAction;
+import org.chromium.base.Log;
+
+/**
+ * A {@link SafeModeAction} that has no effect.
+ */
+public class NoopSafeModeAction implements SafeModeAction {
+    private static final String TAG = "WebViewSafeMode";
+    // This ID should not be changed or reused.
+    private static final String ID = "noop";
+
+    @NonNull
+    @Override
+    public String getId() {
+        return ID;
+    }
+
+    @Override
+    public boolean execute() {
+        // This is intentionally no operation as this action is meant for testing purposes only.
+        Log.i(TAG, "NOOP action executed");
+        return true;
+    }
+}
diff --git a/android_webview/test/shell/src/draw_fn/overlays_manager.cc b/android_webview/test/shell/src/draw_fn/overlays_manager.cc
index f21081e..8b3cb64 100644
--- a/android_webview/test/shell/src/draw_fn/overlays_manager.cc
+++ b/android_webview/test/shell/src/draw_fn/overlays_manager.cc
@@ -68,7 +68,7 @@
     gfx::SurfaceControl::ApplyTransaction(transaction);
   }
 
-  const raw_ref<FunctorData> functor_;
+  const raw_ref<FunctorData, DanglingUntriaged> functor_;
   raw_ptr<ANativeWindow> native_window_;
 };
 
diff --git a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
index 833551f..a1e62f1 100644
--- a/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
+++ b/android_webview/tools/system_webview_shell/test/data/webexposed/not-webview-exposed.txt
@@ -13,7 +13,6 @@
 
 # web payments api not enabled in webiew, crbug.com/667069
 interface PaymentAddress
-interface PaymentInstruments
 interface PaymentManager
 interface PaymentMethodChangeEvent : PaymentRequestUpdateEvent
 interface PaymentRequest : EventTarget
diff --git a/ash/login/OOBE_WEBUI_OWNERS b/ash/login/OOBE_WEBUI_OWNERS
index 2247a45..736f656 100644
--- a/ash/login/OOBE_WEBUI_OWNERS
+++ b/ash/login/OOBE_WEBUI_OWNERS
@@ -1,7 +1,6 @@
 # Primary (in CET)
 dkuzmin@google.com
 rrsilva@google.com
-rsorokin@google.com
 
 #Secondary (in CET)
 antrim@chromium.org
diff --git a/base/allocator/dispatcher/dispatcher.cc b/base/allocator/dispatcher/dispatcher.cc
index 9a1b471..fd6e8a16 100644
--- a/base/allocator/dispatcher/dispatcher.cc
+++ b/base/allocator/dispatcher/dispatcher.cc
@@ -6,7 +6,6 @@
 
 #include "base/allocator/buildflags.h"
 #include "base/allocator/dispatcher/internal/dispatch_data.h"
-#include "base/allocator/dispatcher/reentry_guard.h"
 #include "base/allocator/partition_allocator/partition_alloc.h"
 #include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
 #include "base/allocator/partition_allocator/shim/allocator_shim.h"
@@ -26,25 +25,23 @@
 using allocator_shim::AllocatorDispatch;
 
 void* AllocFn(const AllocatorDispatch* self, size_t size, void* context) {
-  ReentryGuard guard;
   void* address = self->next->alloc_function(self->next, size, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
 void* AllocUncheckedFn(const AllocatorDispatch* self,
                        size_t size,
                        void* context) {
-  ReentryGuard guard;
   void* address =
       self->next->alloc_unchecked_function(self->next, size, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
@@ -52,13 +49,12 @@
                              size_t n,
                              size_t size,
                              void* context) {
-  ReentryGuard guard;
   void* address =
       self->next->alloc_zero_initialized_function(self->next, n, size, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, n * size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, n * size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
@@ -66,13 +62,12 @@
                      size_t alignment,
                      size_t size,
                      void* context) {
-  ReentryGuard guard;
   void* address =
       self->next->alloc_aligned_function(self->next, alignment, size, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
@@ -80,14 +75,13 @@
                 void* address,
                 size_t size,
                 void* context) {
-  ReentryGuard guard;
   // Note: size == 0 actually performs free.
   PoissonAllocationSampler::RecordFree(address);
   address = self->next->realloc_function(self->next, address, size, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
@@ -118,15 +112,14 @@
                        void** results,
                        unsigned num_requested,
                        void* context) {
-  ReentryGuard guard;
   unsigned num_allocated = self->next->batch_malloc_function(
       self->next, size, results, num_requested, context);
-  if (LIKELY(guard)) {
-    for (unsigned i = 0; i < num_allocated; ++i) {
-      PoissonAllocationSampler::RecordAlloc(
-          results[i], size, AllocationSubsystem::kAllocatorShim, nullptr);
-    }
+
+  for (unsigned i = 0; i < num_allocated; ++i) {
+    PoissonAllocationSampler::RecordAlloc(
+        results[i], size, AllocationSubsystem::kAllocatorShim, nullptr);
   }
+
   return num_allocated;
 }
 
@@ -134,8 +127,10 @@
                  void** to_be_freed,
                  unsigned num_to_be_freed,
                  void* context) {
-  for (unsigned i = 0; i < num_to_be_freed; ++i)
+  for (unsigned i = 0; i < num_to_be_freed; ++i) {
     PoissonAllocationSampler::RecordFree(to_be_freed[i]);
+  }
+
   self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed,
                                   context);
 }
@@ -159,13 +154,12 @@
                              size_t size,
                              size_t alignment,
                              void* context) {
-  ReentryGuard guard;
   void* address =
       self->next->aligned_malloc_function(self->next, size, alignment, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
@@ -174,15 +168,14 @@
                               size_t size,
                               size_t alignment,
                               void* context) {
-  ReentryGuard guard;
   // Note: size == 0 actually performs free.
   PoissonAllocationSampler::RecordFree(address);
   address = self->next->aligned_realloc_function(self->next, address, size,
                                                  alignment, context);
-  if (LIKELY(guard)) {
-    PoissonAllocationSampler::RecordAlloc(
-        address, size, AllocationSubsystem::kAllocatorShim, nullptr);
-  }
+
+  PoissonAllocationSampler::RecordAlloc(
+      address, size, AllocationSubsystem::kAllocatorShim, nullptr);
+
   return address;
 }
 
diff --git a/base/allocator/dispatcher/internal/dispatcher_internal.h b/base/allocator/dispatcher/internal/dispatcher_internal.h
index 2868b6f33..3203d9e 100644
--- a/base/allocator/dispatcher/internal/dispatcher_internal.h
+++ b/base/allocator/dispatcher/internal/dispatcher_internal.h
@@ -9,9 +9,9 @@
 #include "base/allocator/dispatcher/configuration.h"
 #include "base/allocator/dispatcher/internal/dispatch_data.h"
 #include "base/allocator/dispatcher/internal/tools.h"
-#include "base/allocator/dispatcher/reentry_guard.h"
 #include "base/allocator/dispatcher/subsystem.h"
 #include "base/allocator/partition_allocator/partition_alloc_buildflags.h"
+#include "base/check.h"
 #include "base/compiler_specific.h"
 #include "build/build_config.h"
 
@@ -115,23 +115,21 @@
   static void* AllocFn(const AllocatorDispatch* self,
                        size_t size,
                        void* context) {
-    ReentryGuard guard;
     void* const address = self->next->alloc_function(self->next, size, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
   static void* AllocUncheckedFn(const AllocatorDispatch* self,
                                 size_t size,
                                 void* context) {
-    ReentryGuard guard;
     void* const address =
         self->next->alloc_unchecked_function(self->next, size, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
@@ -139,13 +137,11 @@
                                       size_t n,
                                       size_t size,
                                       void* context) {
-    ReentryGuard guard;
     void* const address = self->next->alloc_zero_initialized_function(
         self->next, n, size, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, n * size,
-                         AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, n * size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
@@ -153,12 +149,11 @@
                               size_t alignment,
                               size_t size,
                               void* context) {
-    ReentryGuard guard;
     void* const address = self->next->alloc_aligned_function(
         self->next, alignment, size, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
@@ -166,20 +161,14 @@
                          void* address,
                          size_t size,
                          void* context) {
-    ReentryGuard guard;
     // Note: size == 0 actually performs free.
-    // Note: ReentryGuard prevents from recursions introduced by malloc and
-    // initialization of thread local storage which happen in the allocation
-    // path only (please see docs of ReentryGuard for full details). Therefore,
-    // the DoNotifyFree doesn't need to be guarded. Instead, making it unguarded
-    // also ensures proper notification.
     DoNotifyFree(address);
     void* const reallocated_address =
         self->next->realloc_function(self->next, address, size, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(reallocated_address, size,
-                         AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(reallocated_address, size,
+                       AllocationSubsystem::kAllocatorShim);
+
     return reallocated_address;
   }
 
@@ -191,8 +180,6 @@
     // being freed before calling free_function, as once the latter is executed
     // the address becomes available and can be allocated by another thread.
     // That would be racy otherwise.
-    // Note: The code doesn't need to protect from recursions using
-    // ReentryGuard, see ReallocFn for details.
     DoNotifyFree(address);
     self->next->free_function(self->next, address, context);
   }
@@ -214,14 +201,10 @@
                                 void** results,
                                 unsigned num_requested,
                                 void* context) {
-    ReentryGuard guard;
     unsigned const num_allocated = self->next->batch_malloc_function(
         self->next, size, results, num_requested, context);
-    if (LIKELY(guard)) {
-      for (unsigned i = 0; i < num_allocated; ++i) {
-        DoNotifyAllocation(results[i], size,
-                           AllocationSubsystem::kAllocatorShim);
-      }
+    for (unsigned i = 0; i < num_allocated; ++i) {
+      DoNotifyAllocation(results[i], size, AllocationSubsystem::kAllocatorShim);
     }
     return num_allocated;
   }
@@ -243,8 +226,6 @@
                                  void* address,
                                  size_t size,
                                  void* context) {
-    // Note: The code doesn't need to protect from recursions using
-    // ReentryGuard, see ReallocFn for details.
     DoNotifyFree(address);
     self->next->free_definite_size_function(self->next, address, size, context);
   }
@@ -260,12 +241,11 @@
                                size_t size,
                                size_t alignment,
                                void* context) {
-    ReentryGuard guard;
     void* const address = self->next->aligned_malloc_function(
         self->next, size, alignment, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
@@ -274,26 +254,19 @@
                                 size_t size,
                                 size_t alignment,
                                 void* context) {
-    ReentryGuard guard;
     // Note: size == 0 actually performs free.
-    // Note: DoNotifyFree doesn't need to protect from recursions using
-    // ReentryGuard, see ReallocFn for details.
-    // Instead, making it unguarded also ensures proper notification of the free
-    // portion.
     DoNotifyFree(address);
     address = self->next->aligned_realloc_function(self->next, address, size,
                                                    alignment, context);
-    if (LIKELY(guard)) {
-      DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
-    }
+
+    DoNotifyAllocation(address, size, AllocationSubsystem::kAllocatorShim);
+
     return address;
   }
 
   static void AlignedFreeFn(const AllocatorDispatch* self,
                             void* address,
                             void* context) {
-    // Note: The code doesn't need to protect from recursions using
-    // ReentryGuard, see ReallocFn for details.
     DoNotifyFree(address);
     self->next->aligned_free_function(self->next, address, context);
   }
diff --git a/base/allocator/partition_allocator/partition_address_space.cc b/base/allocator/partition_allocator/partition_address_space.cc
index 373b1ee4..8227a64 100644
--- a/base/allocator/partition_allocator/partition_address_space.cc
+++ b/base/allocator/partition_allocator/partition_address_space.cc
@@ -42,34 +42,6 @@
 
 #if BUILDFLAG(IS_WIN)
 
-#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
-bool IsLegacyWindowsVersion() {
-  // Use ::RtlGetVersion instead of ::GetVersionEx or helpers from
-  // VersionHelpers.h because those alternatives change their behavior depending
-  // on whether or not the calling executable has a compatibility manifest
-  // resource. It's better for the allocator to not depend on that to decide the
-  // pool size.
-  // Assume legacy if ::RtlGetVersion is not available or it fails.
-  using RtlGetVersion = LONG(WINAPI*)(OSVERSIONINFOEX*);
-  const RtlGetVersion rtl_get_version = reinterpret_cast<RtlGetVersion>(
-      ::GetProcAddress(::GetModuleHandle(L"ntdll.dll"), "RtlGetVersion"));
-  if (!rtl_get_version) {
-    return true;
-  }
-
-  OSVERSIONINFOEX version_info = {};
-  version_info.dwOSVersionInfoSize = sizeof(version_info);
-  if (rtl_get_version(&version_info) != ERROR_SUCCESS) {
-    return true;
-  }
-
-  // Anything prior to Windows 8.1 is considered legacy for the allocator.
-  // Windows 8.1 is major 6 with minor 3.
-  return version_info.dwMajorVersion < 6 ||
-         (version_info.dwMajorVersion == 6 && version_info.dwMinorVersion < 3);
-}
-#endif  // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
-
 PA_NOINLINE void HandlePoolAllocFailureOutOfVASpace() {
   PA_NO_CODE_FOLDING();
   PA_CHECK(false);
@@ -93,9 +65,9 @@
     // it must be VA space exhaustion.
     HandlePoolAllocFailureOutOfVASpace();
   } else if (alloc_page_error_code == ERROR_COMMITMENT_LIMIT) {
-    // On Windows <8.1, MEM_RESERVE increases commit charge to account for
-    // not-yet-committed PTEs needed to cover that VA space, if it was to be
-    // committed (see crbug.com/1101421#c16).
+    // Should not happen, since as of Windows 8.1+, reserving address space
+    // should not be charged against the commit limit, aside from a very small
+    // amount per 64kiB block. Keep this path anyway, to check in crash reports.
     HandlePoolAllocFailureOutOfCommitCharge();
   } else
 #endif  // BUILDFLAG(IS_WIN)
@@ -119,7 +91,10 @@
 #endif
 
 #if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
-#if BUILDFLAG(IS_IOS)
+#if !BUILDFLAG(IS_IOS)
+#error Dynamic pool size is only supported on iOS.
+#endif
+
 namespace {
 bool IsIOSTestProcess() {
   // On iOS, only applications with the extended virtual addressing entitlement
@@ -161,15 +136,6 @@
 PA_ALWAYS_INLINE size_t PartitionAddressSpace::BRPPoolSize() {
   return IsIOSTestProcess() ? kBRPPoolSizeForIOSTestProcess : kBRPPoolSize;
 }
-#else
-PA_ALWAYS_INLINE size_t PartitionAddressSpace::RegularPoolSize() {
-  return IsLegacyWindowsVersion() ? kRegularPoolSizeForLegacyWindows
-                                  : kRegularPoolSize;
-}
-PA_ALWAYS_INLINE size_t PartitionAddressSpace::BRPPoolSize() {
-  return IsLegacyWindowsVersion() ? kBRPPoolSizeForLegacyWindows : kBRPPoolSize;
-}
-#endif  // BUILDFLAG(IS_IOS)
 #endif  // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
 
 void PartitionAddressSpace::Init() {
diff --git a/base/allocator/partition_allocator/partition_address_space.h b/base/allocator/partition_allocator/partition_address_space.h
index 07e26dc..0774a0d 100644
--- a/base/allocator/partition_allocator/partition_address_space.h
+++ b/base/allocator/partition_allocator/partition_address_space.h
@@ -267,16 +267,6 @@
   static constexpr size_t kPkeyPoolSize = kGiB / 4;
   static_assert(base::bits::IsPowerOfTwo(kPkeyPoolSize));
 #endif
-#if PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
-  // We can't afford pool sizes as large as kPoolMaxSize on Windows <8.1 (see
-  // crbug.com/1101421 and crbug.com/1217759).
-  static constexpr size_t kRegularPoolSizeForLegacyWindows = 4 * kGiB;
-  static constexpr size_t kBRPPoolSizeForLegacyWindows = 4 * kGiB;
-  static_assert(kRegularPoolSizeForLegacyWindows < kRegularPoolSize);
-  static_assert(kBRPPoolSizeForLegacyWindows < kBRPPoolSize);
-  static_assert(base::bits::IsPowerOfTwo(kRegularPoolSizeForLegacyWindows));
-  static_assert(base::bits::IsPowerOfTwo(kBRPPoolSizeForLegacyWindows));
-#endif  // PA_CONFIG(DYNAMICALLY_SELECT_POOL_SIZE)
   static constexpr size_t kConfigurablePoolMaxSize = kPoolMaxSize;
   static constexpr size_t kConfigurablePoolMinSize = 1 * kGiB;
   static_assert(kConfigurablePoolMinSize <= kConfigurablePoolMaxSize);
diff --git a/base/allocator/partition_allocator/partition_alloc_config.h b/base/allocator/partition_allocator/partition_alloc_config.h
index 387f6047..5e6a00f 100644
--- a/base/allocator/partition_allocator/partition_alloc_config.h
+++ b/base/allocator/partition_allocator/partition_alloc_config.h
@@ -53,23 +53,18 @@
 #define PA_CONFIG_STARSCAN_NEON_SUPPORTED() 0
 #endif
 
-#if PA_CONFIG(HAS_64_BITS_POINTERS) && (BUILDFLAG(IS_IOS) || BUILDFLAG(IS_WIN))
+#if PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_IOS)
 // Allow PA to select an alternate pool size at run-time before initialization,
 // rather than using a single constexpr value.
 //
 // This is needed on iOS because iOS test processes can't handle large pools
 // (see crbug.com/1250788).
 //
-// This is needed on Windows, because OS versions <8.1 incur commit charge even
-// on reserved address space, thus don't handle large pools well (see
-// crbug.com/1101421 and crbug.com/1217759).
-//
 // This setting is specific to 64-bit, as 32-bit has a different implementation.
 #define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 1
 #else
 #define PA_CONFIG_DYNAMICALLY_SELECT_POOL_SIZE() 0
-#endif  // PA_CONFIG(HAS_64_BITS_POINTERS) && (BUILDFLAG(IS_IOS) ||
-        // BUILDFLAG(IS_WIN))
+#endif  // PA_CONFIG(HAS_64_BITS_POINTERS) && BUILDFLAG(IS_IOS)
 
 // Puts the regular and BRP pools right next to each other, so that we can
 // check "belongs to one of the two pools" with a single bitmask operation.
diff --git a/base/debug/stack_trace_posix.cc b/base/debug/stack_trace_posix.cc
index 501261c..6fc7785 100644
--- a/base/debug/stack_trace_posix.cc
+++ b/base/debug/stack_trace_posix.cc
@@ -28,9 +28,14 @@
 #include "base/memory/raw_ptr.h"
 #include "build/build_config.h"
 
-#if !defined(USE_SYMBOLIZE)
-#include <cxxabi.h>
+// Controls whether `dladdr(...)` is used to print the callstack. This is
+// only used on iOS Official build where `backtrace_symbols(...)` prints
+// misleading symbols (as the binary is stripped).
+#if BUILDFLAG(IS_IOS) && defined(OFFICIAL_BUILD)
+#define HAVE_DLADDR
+#include <dlfcn.h>
 #endif
+
 // Surprisingly, uClibc defines __GLIBC__ in some build configs, but
 // execinfo.h and backtrace(3) are really only present in glibc and in macOS
 // libc.
@@ -40,6 +45,15 @@
 #include <execinfo.h>
 #endif
 
+// Controls whether to include code to demangle C++ symbols.
+#if !defined(USE_SYMBOLIZE) && defined(HAVE_BACKTRACE) && !defined(HAVE_DLADDR)
+#define DEMANGLE_SYMBOLS
+#endif
+
+#if defined(DEMANGLE_SYMBOLS)
+#include <cxxabi.h>
+#endif
+
 #if BUILDFLAG(IS_APPLE)
 #include <AvailabilityMacros.h>
 #endif
@@ -82,7 +96,7 @@
 bool (*try_handle_signal)(int, siginfo_t*, void*) = nullptr;
 #endif
 
-#if !defined(USE_SYMBOLIZE)
+#if defined(DEMANGLE_SYMBOLS)
 // The prefix used for mangled symbols, per the Itanium C++ ABI:
 // http://www.codesourcery.com/cxx-abi/abi.html#mangling
 const char kMangledSymbolPrefix[] = "_Z";
@@ -91,9 +105,7 @@
 // (('a'..'z').to_a+('A'..'Z').to_a+('0'..'9').to_a + ['_']).join
 const char kSymbolCharacters[] =
     "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_";
-#endif  // !defined(USE_SYMBOLIZE)
 
-#if !defined(USE_SYMBOLIZE)
 // Demangles C++ symbols in the given text. Example:
 //
 // "out/Debug/base_unittests(_ZN10StackTraceC1Ev+0x20) [0x817778c]"
@@ -103,7 +115,6 @@
   // Note: code in this function is NOT async-signal safe (std::string uses
   // malloc internally).
 
-#if defined(HAVE_BACKTRACE)
   std::string::size_type search_from = 0;
   while (search_from < text->size()) {
     // Look for the start of a mangled symbol, from search_from.
@@ -138,9 +149,8 @@
       search_from = mangled_start + 2;
     }
   }
-#endif  // defined(HAVE_BACKTRACE)
 }
-#endif  // !defined(USE_SYMBOLIZE)
+#endif  // defined(DEMANGLE_SYMBOLS)
 
 class BacktraceOutputHandler {
  public:
@@ -161,16 +171,22 @@
   handler->HandleOutput(buf);
 }
 
-#if defined(USE_SYMBOLIZE)
-void OutputFrameId(size_t frame_id, BacktraceOutputHandler* handler) {
+#if defined(HAVE_DLADDR) || defined(USE_SYMBOLIZE)
+void OutputValue(size_t value, BacktraceOutputHandler* handler) {
   // Max unsigned 64-bit number in decimal has 20 digits (18446744073709551615).
   // Hence, 30 digits should be more than enough to represent it in decimal
   // (including the null-terminator).
   char buf[30] = { '\0' };
-  handler->HandleOutput("#");
-  internal::itoa_r(static_cast<intptr_t>(frame_id), buf, sizeof(buf), 10, 1);
+  internal::itoa_r(static_cast<intptr_t>(value), buf, sizeof(buf), 10, 1);
   handler->HandleOutput(buf);
 }
+#endif  // defined(HAVE_DLADDR) || defined(USE_SYMBOLIZE)
+
+#if defined(USE_SYMBOLIZE)
+void OutputFrameId(size_t frame_id, BacktraceOutputHandler* handler) {
+  handler->HandleOutput("#");
+  OutputValue(frame_id, handler);
+}
 #endif  // defined(USE_SYMBOLIZE)
 
 void ProcessBacktrace(void* const* trace,
@@ -225,6 +241,31 @@
   // Below part is async-signal unsafe (uses malloc), so execute it only
   // when we are not executing the signal handler.
   if (in_signal_handler == 0 && IsValueInRangeForNumericType<int>(size)) {
+#if defined(HAVE_DLADDR)
+    Dl_info dl_info;
+    for (size_t i = 0; i < size; ++i) {
+      if (prefix_string) {
+        handler->HandleOutput(prefix_string);
+      }
+
+      OutputValue(i, handler);
+      handler->HandleOutput(" ");
+
+      const bool dl_info_found = dladdr(trace[i], &dl_info) != 0;
+      if (dl_info_found) {
+        const char* last_sep = strrchr(dl_info.dli_fname, '/');
+        const char* basename = last_sep ? last_sep + 1 : dl_info.dli_fname;
+        handler->HandleOutput(basename);
+      } else {
+        handler->HandleOutput("???");
+      }
+      handler->HandleOutput(" ");
+      OutputPointer(trace[i], handler);
+
+      handler->HandleOutput("\n");
+    }
+    printed = true;
+#else   // defined(HAVE_DLADDR)
     std::unique_ptr<char*, FreeDeleter> trace_symbols(
         backtrace_symbols(trace, static_cast<int>(size)));
     if (trace_symbols.get()) {
@@ -239,6 +280,7 @@
 
       printed = true;
     }
+#endif  // defined(HAVE_DLADDR)
   }
 
   if (!printed) {
diff --git a/base/files/memory_mapped_file.h b/base/files/memory_mapped_file.h
index 74a5a4f0..13ec05e 100644
--- a/base/files/memory_mapped_file.h
+++ b/base/files/memory_mapped_file.h
@@ -141,7 +141,7 @@
   File file_;
 
   // TODO(crbug.com/1298696): Breaks one of the test suites.
-  raw_ptr<uint8_t, DegradeToNoOpWhenMTE> data_ = nullptr;
+  raw_ptr<uint8_t, DanglingUntriagedDegradeToNoOpWhenMTE> data_ = nullptr;
   size_t length_ = 0;
 
 #if BUILDFLAG(IS_WIN)
diff --git a/base/metrics/histogram.cc b/base/metrics/histogram.cc
index 30f3d04..e6a31df 100644
--- a/base/metrics/histogram.cc
+++ b/base/metrics/histogram.cc
@@ -940,7 +940,7 @@
 
 ScaledLinearHistogram::~ScaledLinearHistogram() = default;
 
-void ScaledLinearHistogram::AddScaledCount(Sample value, int count) {
+void ScaledLinearHistogram::AddScaledCount(Sample value, int64_t count) {
   if (histogram_->GetHistogramType() == DUMMY_HISTOGRAM)
     return;
   if (count == 0)
@@ -955,8 +955,8 @@
   const auto max_value = static_cast<Sample>(histogram->bucket_count() - 1);
   value = base::clamp(value, 0, max_value);
 
-  int scaled_count = count / scale_;
-  subtle::Atomic32 remainder = count - scaled_count * scale_;
+  int64_t scaled_count = count / scale_;
+  subtle::Atomic32 remainder = static_cast<int>(count - scaled_count * scale_);
 
   // ScaledLinearHistogram currently requires 1-to-1 mappings between value
   // and bucket which alleviates the need to do a bucket lookup here (something
@@ -975,8 +975,10 @@
     }
   }
 
-  if (scaled_count > 0)
-    histogram->AddCount(value, scaled_count);
+  if (scaled_count > 0) {
+    DCHECK(scaled_count <= std::numeric_limits<int>::max());
+    histogram->AddCount(value, static_cast<int>(scaled_count));
+  }
 }
 
 //------------------------------------------------------------------------------
diff --git a/base/metrics/histogram.h b/base/metrics/histogram.h
index afb7679..0b9a8f5 100644
--- a/base/metrics/histogram.h
+++ b/base/metrics/histogram.h
@@ -435,7 +435,8 @@
   // Like AddCount() but actually accumulates |count|/|scale| and increments
   // the accumulated remainder by |count|%|scale|. An additional increment
   // is done when the remainder has grown sufficiently large.
-  void AddScaledCount(Sample value, int count);
+  // The value after scaling must fit into 32-bit signed integer.
+  void AddScaledCount(Sample value, int64_t count);
 
   int32_t scale() const { return scale_; }
   HistogramBase* histogram() { return histogram_; }
diff --git a/base/sampling_heap_profiler/poisson_allocation_sampler.h b/base/sampling_heap_profiler/poisson_allocation_sampler.h
index 55f5d48..20b5f93a7e 100644
--- a/base/sampling_heap_profiler/poisson_allocation_sampler.h
+++ b/base/sampling_heap_profiler/poisson_allocation_sampler.h
@@ -8,6 +8,7 @@
 #include <atomic>
 #include <vector>
 
+#include "base/allocator/dispatcher/reentry_guard.h"
 #include "base/allocator/dispatcher/subsystem.h"
 #include "base/base_export.h"
 #include "base/compiler_specific.h"
@@ -261,6 +262,15 @@
     return;
   }
 
+  // Note: ReentryGuard prevents from recursions introduced by malloc and
+  // initialization of thread local storage which happen in the allocation path
+  // only (please see docs of ReentryGuard for full details).
+  allocator::dispatcher::ReentryGuard reentry_guard;
+
+  if (UNLIKELY(!reentry_guard)) {
+    return;
+  }
+
   DoRecordAllocation(state, address, size, type, context);
 }
 
@@ -327,6 +337,11 @@
     return;
   }
 
+  // Note: ReentryGuard prevents from recursions introduced by malloc and
+  // initialization of thread local storage which happen in the allocation path
+  // only (please see docs of ReentryGuard for full details). Therefore, the
+  // DoNotifyFree doesn't need to be guarded.
+
   DoRecordFree(address);
 }
 
diff --git a/base/trace_event/log_message.cc b/base/trace_event/log_message.cc
index 8b9b051..0af9d779 100644
--- a/base/trace_event/log_message.cc
+++ b/base/trace_event/log_message.cc
@@ -36,7 +36,7 @@
   overhead->AddString(message_);
 }
 
-bool LogMessage::AppendToProto(ProtoAppender* appender) {
+bool LogMessage::AppendToProto(ProtoAppender* appender) const {
   // LogMessage is handled in a special way in
   // track_event_thread_local_event_sink.cc in the function |AddTraceEvent|, so
   // this call should never happen.
diff --git a/base/trace_event/log_message.h b/base/trace_event/log_message.h
index 2329824..dbde68f 100644
--- a/base/trace_event/log_message.h
+++ b/base/trace_event/log_message.h
@@ -26,7 +26,7 @@
 
   // ConvertableToTraceFormat class implementation.
   void AppendAsTraceFormat(std::string* out) const override;
-  bool AppendToProto(ProtoAppender* appender) override;
+  bool AppendToProto(ProtoAppender* appender) const override;
 
   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
 
diff --git a/base/trace_event/trace_arguments.cc b/base/trace_event/trace_arguments.cc
index cbd9e52..ad202ec 100644
--- a/base/trace_event/trace_arguments.cc
+++ b/base/trace_event/trace_arguments.cc
@@ -14,6 +14,7 @@
 
 #include "base/check_op.h"
 #include "base/json/string_escape.h"
+#include "base/memory/raw_ptr.h"
 #include "base/notreached.h"
 #include "base/strings/string_number_conversions.h"
 #include "base/strings/string_util.h"
@@ -114,6 +115,31 @@
   *out += ")";
 }
 
+#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+class PerfettoProtoAppender : public ConvertableToTraceFormat::ProtoAppender {
+ public:
+  explicit PerfettoProtoAppender(
+      perfetto::protos::pbzero::DebugAnnotation* proto)
+      : annotation_proto_(proto) {}
+  ~PerfettoProtoAppender() override = default;
+
+  void AddBuffer(uint8_t* begin, uint8_t* end) override {
+    ranges_.emplace_back();
+    ranges_.back().begin = begin;
+    ranges_.back().end = end;
+  }
+
+  size_t Finalize(uint32_t field_id) override {
+    return annotation_proto_->AppendScatteredBytes(field_id, ranges_.data(),
+                                                   ranges_.size());
+  }
+
+ private:
+  std::vector<protozero::ContiguousMemoryRange> ranges_;
+  raw_ptr<perfetto::protos::pbzero::DebugAnnotation> annotation_proto_;
+};
+#endif  // BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+
 }  // namespace
 
 void StringStorage::Reset(size_t alloc_size) {
@@ -294,6 +320,11 @@
 #if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
 void ConvertableToTraceFormat::Add(
     perfetto::protos::pbzero::DebugAnnotation* annotation) const {
+  PerfettoProtoAppender proto_appender(annotation);
+  if (AppendToProto(&proto_appender)) {
+    return;
+  }
+
   std::string json;
   AppendAsTraceFormat(&json);
   annotation->set_legacy_json_value(json);
diff --git a/base/trace_event/trace_arguments.h b/base/trace_event/trace_arguments.h
index f852043..fb614a8 100644
--- a/base/trace_event/trace_arguments.h
+++ b/base/trace_event/trace_arguments.h
@@ -175,7 +175,7 @@
     // into the proto, with the given |field_id|.
     virtual size_t Finalize(uint32_t field_id) = 0;
   };
-  virtual bool AppendToProto(ProtoAppender* appender);
+  virtual bool AppendToProto(ProtoAppender* appender) const;
 
   virtual void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead);
 
diff --git a/base/trace_event/trace_event_impl.cc b/base/trace_event/trace_event_impl.cc
index 41e713ce..e9c97f4 100644
--- a/base/trace_event/trace_event_impl.cc
+++ b/base/trace_event/trace_event_impl.cc
@@ -65,7 +65,7 @@
 namespace base {
 namespace trace_event {
 
-bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) {
+bool ConvertableToTraceFormat::AppendToProto(ProtoAppender* appender) const {
   return false;
 }
 
diff --git a/base/trace_event/traced_value.cc b/base/trace_event/traced_value.cc
index 17735299..4a7f2872 100644
--- a/base/trace_event/traced_value.cc
+++ b/base/trace_event/traced_value.cc
@@ -640,7 +640,7 @@
   writer_->AppendAsTraceFormat(out);
 }
 
-bool TracedValue::AppendToProto(ProtoAppender* appender) {
+bool TracedValue::AppendToProto(ProtoAppender* appender) const {
   return writer_->AppendToProto(appender);
 }
 
diff --git a/base/trace_event/traced_value.h b/base/trace_event/traced_value.h
index beb6343..da856cb 100644
--- a/base/trace_event/traced_value.h
+++ b/base/trace_event/traced_value.h
@@ -67,7 +67,7 @@
 
   // ConvertableToTraceFormat implementation.
   void AppendAsTraceFormat(std::string* out) const override;
-  bool AppendToProto(ProtoAppender* appender) override;
+  bool AppendToProto(ProtoAppender* appender) const override;
 
   void EstimateTraceMemoryOverhead(TraceEventMemoryOverhead* overhead) override;
 
@@ -393,7 +393,7 @@
   std::unique_ptr<base::Value> ToBaseValue() const;
 
  private:
-  std::unique_ptr<Writer> writer_;
+  mutable std::unique_ptr<Writer> writer_;
 
 #ifndef NDEBUG
   // In debug builds checks the pairings of {Start,End}{Dictionary,Array}
diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc
index 6ce96f706..24e99bc 100644
--- a/base/win/windows_version.cc
+++ b/base/win/windows_version.cc
@@ -311,38 +311,59 @@
 Version OSInfo::MajorMinorBuildToVersion(uint32_t major,
                                          uint32_t minor,
                                          uint32_t build) {
-  if (major == 11)
+  if (major == 11) {
+    if (build >= 22621) {
+      return Version::WIN11_22H2;
+    }
     return Version::WIN11;
+  }
 
   if (major == 10) {
-    if (build >= 22000)
+    if (build >= 22000) {
       return Version::WIN11;
-    if (build >= 20348)
+    }
+    if (build >= 20348) {
       return Version::SERVER_2022;
-    if (build >= 19044)
+    }
+    if (build >= 19045) {
+      return Version::WIN10_22H2;
+    }
+    if (build >= 19044) {
       return Version::WIN10_21H2;
-    if (build >= 19043)
+    }
+    if (build >= 19043) {
       return Version::WIN10_21H1;
-    if (build >= 19042)
+    }
+    if (build >= 19042) {
       return Version::WIN10_20H2;
-    if (build >= 19041)
+    }
+    if (build >= 19041) {
       return Version::WIN10_20H1;
-    if (build >= 18363)
+    }
+    if (build >= 18363) {
       return Version::WIN10_19H2;
-    if (build >= 18362)
+    }
+    if (build >= 18362) {
       return Version::WIN10_19H1;
-    if (build >= 17763)
+    }
+    if (build >= 17763) {
       return Version::WIN10_RS5;
-    if (build >= 17134)
+    }
+    if (build >= 17134) {
       return Version::WIN10_RS4;
-    if (build >= 16299)
+    }
+    if (build >= 16299) {
       return Version::WIN10_RS3;
-    if (build >= 15063)
+    }
+    if (build >= 15063) {
       return Version::WIN10_RS2;
-    if (build >= 14393)
+    }
+    if (build >= 14393) {
       return Version::WIN10_RS1;
-    if (build >= 10586)
+    }
+    if (build >= 10586) {
       return Version::WIN10_TH2;
+    }
     return Version::WIN10;
   }
 
diff --git a/base/win/windows_version.h b/base/win/windows_version.h
index c9e5b309..4d820fd7 100644
--- a/base/win/windows_version.h
+++ b/base/win/windows_version.h
@@ -54,8 +54,10 @@
   WIN10_20H2 = 17,   // 20H2: Build 19042.
   WIN10_21H1 = 18,   // 21H1: Build 19043.
   WIN10_21H2 = 19,   // Win10 21H2: Build 19044.
-  SERVER_2022 = 20,  // Server 2022: Build 20348.
-  WIN11 = 21,        // Win11 21H2: Build 22000.
+  WIN10_22H2 = 20,   // Win10 21H2: Build 19045.
+  SERVER_2022 = 21,  // Server 2022: Build 20348.
+  WIN11 = 22,        // Win11 21H2: Build 22000.
+  WIN11_22H2 = 23,   // Win11 22H2: Build 22621.
   WIN_LAST,          // Indicates error condition.
 };
 
diff --git a/base/win/windows_version_unittest.cc b/base/win/windows_version_unittest.cc
index 5ce147aa..41720a9 100644
--- a/base/win/windows_version_unittest.cc
+++ b/base/win/windows_version_unittest.cc
@@ -24,16 +24,22 @@
 }
 
 TEST(OSInfo, MajorMinorBuildToVersion) {
-  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 32767),
-            Version::WIN11);
-  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 22000),
-            Version::WIN11);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 32767),
+            Version::WIN11_22H2);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 22621),
+            Version::WIN11_22H2);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 22000), Version::WIN11);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(11, 0, 0), Version::WIN11);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 32767), Version::WIN11);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 22000), Version::WIN11);
   EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 21999),
             Version::SERVER_2022);
   EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 20348),
             Version::SERVER_2022);
   EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 20347),
-            Version::WIN10_21H2);
+            Version::WIN10_22H2);
+  EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 19045),
+            Version::WIN10_22H2);
   EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 19044),
             Version::WIN10_21H2);
   EXPECT_EQ(OSInfo::MajorMinorBuildToVersion(10, 0, 19043),
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1
index d245135..eb74071 100644
--- a/build/fuchsia/linux_internal.sdk.sha1
+++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@
-11.20230125.0.1
+11.20230125.1.1
diff --git a/build/toolchain/toolchain.gni b/build/toolchain/toolchain.gni
index 844bc8e..9d37839 100644
--- a/build/toolchain/toolchain.gni
+++ b/build/toolchain/toolchain.gni
@@ -33,7 +33,12 @@
 }
 
 declare_args() {
-  clang_version = "16"
+  if (llvm_force_head_revision) {
+    clang_version = "17"
+  } else {
+    # TODO(crbug.com/1410101): Remove in next Clang roll.
+    clang_version = "16"
+  }
 }
 
 # Extension for shared library files (including leading dot).
diff --git a/build_overrides/partition_alloc.gni b/build_overrides/partition_alloc.gni
index e1fa5fe9..e90ccba 100644
--- a/build_overrides/partition_alloc.gni
+++ b/build_overrides/partition_alloc.gni
@@ -29,6 +29,7 @@
 import("//build/config/sanitizers/sanitizers.gni")
 if (is_ios) {
   import("//build/config/ios/ios_sdk.gni")
+  import("//ios/features.gni")
 }
 
 # Sanitizers replace the allocator, don't use our own.
@@ -41,8 +42,12 @@
 _disable_partition_alloc_everywhere = is_component_build || (is_win && is_debug)
 
 # - NaCl: No plans to support it.
-# - iOS: not done yet.
-_is_partition_alloc_everywhere_platform = !is_nacl && !is_ios
+# - iOS: Depends on ios_partition_alloc_enabled.
+if (is_ios) {
+  _is_partition_alloc_everywhere_platform = ios_partition_alloc_enabled
+} else {
+  _is_partition_alloc_everywhere_platform = !is_nacl
+}
 
 # Under Windows debug build, the allocator shim is not compatible with CRT.
 #     NaCl in particular does seem to link some binaries statically
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index d455138f..f1778a7 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -395,10 +395,12 @@
   "java/res/drawable/ic_incognito.xml",
   "java/res/drawable/ic_incognito_cct_24dp.xml",
   "java/res/drawable/ic_incognito_reauth_promo_icon.xml",
+  "java/res/drawable/ic_install_webapp.xml",
   "java/res/drawable/ic_new_tab_button.xml",
   "java/res/drawable/ic_new_window.xml",
   "java/res/drawable/ic_offer_tag.xml",
   "java/res/drawable/ic_open_in_browser.xml",
+  "java/res/drawable/ic_open_webapk.xml",
   "java/res/drawable/ic_person_add_40dp.xml",
   "java/res/drawable/ic_reading_list_folder_24dp.xml",
   "java/res/drawable/ic_recent_tabs_bulk_20dp.xml",
diff --git a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
index 2158a5c..48e42f4 100644
--- a/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
+++ b/chrome/android/features/keyboard_accessory/junit/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingControllerTest.java
@@ -1182,7 +1182,7 @@
         when(mMockTabModelSelector.getCurrentTab()).thenReturn(tab);
         mActivityTabProvider.set(tab);
         mediator.getTabModelObserverForTesting().didAddTab(
-                tab, FROM_BROWSER_ACTIONS, TabCreationState.LIVE_IN_FOREGROUND);
+                tab, FROM_BROWSER_ACTIONS, TabCreationState.LIVE_IN_FOREGROUND, false);
         mediator.getTabObserverForTesting().onShown(tab, FROM_NEW);
         mediator.getTabModelObserverForTesting().didSelectTab(tab, FROM_NEW, lastId);
         setContentAreaDimensions(2.f, 300, 128);
diff --git a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
index e15b0a8..0ad7633 100644
--- a/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
+++ b/chrome/android/features/start_surface/javatests/src/org/chromium/chrome/features/start_surface/TabSwitcherAndStartSurfaceLayoutTest.java
@@ -110,6 +110,7 @@
 import org.chromium.chrome.browser.tasks.tab_management.TabUiFeatureUtilities;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiTestHelper;
 import org.chromium.chrome.browser.tasks.tab_management.TabUiThemeProvider;
+import org.chromium.chrome.browser.tasks.tab_management.UndoGroupSnackbarController;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.undo_tab_close_snackbar.UndoBarController;
 import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
@@ -1810,7 +1811,7 @@
         // Create a tab group.
         mergeAllNormalTabsToAGroup(cta);
         verifyTabSwitcherCardCount(cta, 1);
-        assertNull(snackbarManager.getCurrentSnackbarForTesting());
+        assertNotNull(snackbarManager.getCurrentSnackbarForTesting());
 
         // Verify close this tab group and undo in tab switcher.
         closeFirstTabInTabSwitcher(cta);
@@ -1902,6 +1903,103 @@
         TabUiFeatureUtilities.ENABLE_TAB_SELECTION_EDITOR_V2_LONGPRESS_ENTRY.setForTesting(false);
     }
 
+    @Test
+    @MediumTest
+    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
+    public void testUndoGroupMergeInTabSwitcher_TabToTab() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager();
+        createTabs(cta, false, 2);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 2);
+
+        // Create a tab group.
+        mergeAllNormalTabsToAGroup(cta);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+
+        // Undo merge in tab switcher.
+        verifyTabSwitcherCardCount(cta, 1);
+        assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
+        verifyTabSwitcherCardCount(cta, 2);
+    }
+
+    @Test
+    @MediumTest
+    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
+    public void testUndoGroupMergeInTabSwitcher_TabToGroupAdjacent() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager();
+        createTabs(cta, false, 3);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 3);
+
+        // Merge first two tabs into a group.
+        TabModel normalTabModel = cta.getTabModelSelector().getModel(false);
+        List<Tab> tabGroup = new ArrayList<>(
+                Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(1)));
+        createTabGroup(cta, false, tabGroup);
+        verifyTabSwitcherCardCount(cta, 2);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+        assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+
+        // Merge tab group of 2 at first index with the 3rd tab.
+        mergeAllNormalTabsToAGroup(cta);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+
+        // Undo merge in tab switcher.
+        verifyTabSwitcherCardCount(cta, 1);
+        assertEquals("3", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
+        verifyTabSwitcherCardCount(cta, 2);
+    }
+
+    @Test
+    @MediumTest
+    @EnableFeatures({ChromeFeatureList.TAB_GROUPS_ANDROID})
+    public void testUndoGroupMergeInTabSwitcher_GroupToGroupNonAdjacent() {
+        final ChromeTabbedActivity cta = mActivityTestRule.getActivity();
+        SnackbarManager snackbarManager = mActivityTestRule.getActivity().getSnackbarManager();
+        createTabs(cta, false, 5);
+        enterTabSwitcher(cta);
+        verifyTabSwitcherCardCount(cta, 5);
+
+        // Merge last two tabs into a group.
+        TabModel normalTabModel = cta.getTabModelSelector().getModel(false);
+        List<Tab> tabGroup = new ArrayList<>(
+                Arrays.asList(normalTabModel.getTabAt(3), normalTabModel.getTabAt(4)));
+        createTabGroup(cta, false, tabGroup);
+        verifyTabSwitcherCardCount(cta, 4);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+        assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+
+        // Merge first two tabs into a group.
+        List<Tab> tabGroup2 = new ArrayList<>(
+                Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(1)));
+        createTabGroup(cta, false, tabGroup2);
+        verifyTabSwitcherCardCount(cta, 3);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+        assertEquals("2", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+
+        // Merge the two tab groups into a group.
+        List<Tab> tabGroup3 = new ArrayList<>(
+                Arrays.asList(normalTabModel.getTabAt(0), normalTabModel.getTabAt(3)));
+        createTabGroup(cta, false, tabGroup3);
+        assertTrue(snackbarManager.getCurrentSnackbarForTesting().getController()
+                           instanceof UndoGroupSnackbarController);
+
+        // Undo merge in tab switcher.
+        verifyTabSwitcherCardCount(cta, 2);
+        assertEquals("4", snackbarManager.getCurrentSnackbarForTesting().getTextForTesting());
+        CriteriaHelper.pollInstrumentationThread(TabUiTestHelper::verifyUndoBarShowingAndClickUndo);
+        verifyTabSwitcherCardCount(cta, 3);
+    }
+
     private TabSwitcher.TabListDelegate getTabListDelegateFromUIThread() {
         AtomicReference<TabSwitcher.TabListDelegate> tabListDelegate = new AtomicReference<>();
         TestThreadUtils.runOnUiThreadBlocking(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
index dcc3edf..ebea916 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediator.java
@@ -166,8 +166,8 @@
         // Register for tab model.
         mTabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 if (!mTabModelSelector.isTabStateInitialized()) {
                     return;
                 }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
index 59e8c3b..d972e414 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediator.java
@@ -165,7 +165,8 @@
             }
 
             @Override
-            public void didAddTab(Tab tab, int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, int type, @TabCreationState int creationState,
+                    boolean markedForSelection) {
                 if (type == TabLaunchType.FROM_CHROME_UI || type == TabLaunchType.FROM_RESTORE
                         || type == TabLaunchType.FROM_STARTUP) {
                     return;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
index a909f249..5ec1a15 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediator.java
@@ -113,6 +113,7 @@
     // screen.
     private boolean mVisible;
     private boolean mShownIPH;
+    private Tab mTabToAddDelayed;
 
     /**
      * An interface to get the thumbnails to be shown inside the tab grid cards.
@@ -581,15 +582,6 @@
                 if (tab.getId() == lastId) return;
 
                 int oldIndex = mModel.indexFromId(lastId);
-                mLastSelectedTabListModelIndex = oldIndex;
-                if (oldIndex != TabModel.INVALID_TAB_INDEX) {
-                    mModel.get(oldIndex).model.set(TabProperties.IS_SELECTED, false);
-                    if (mActionsOnAllRelatedTabs && mThumbnailProvider != null && mVisible) {
-                        mModel.get(oldIndex).model.set(TabProperties.THUMBNAIL_FETCHER,
-                                new ThumbnailFetcher(mThumbnailProvider, lastId, true, false));
-                    }
-                }
-
                 int newIndex = mModel.indexFromId(tab.getId());
                 if (newIndex == TabModel.INVALID_TAB_INDEX && mActionsOnAllRelatedTabs
                         && type == TabSelectionType.FROM_UNDO) {
@@ -598,12 +590,13 @@
                     // the related ids are present in model.
                     newIndex = getIndexForTabWithRelatedTabs(tab);
                 }
-                if (newIndex == TabModel.INVALID_TAB_INDEX) return;
-                mModel.get(newIndex).model.set(TabProperties.IS_SELECTED, true);
-                if (mThumbnailProvider != null && mVisible) {
-                    mModel.get(newIndex).model.set(TabProperties.THUMBNAIL_FETCHER,
-                            new ThumbnailFetcher(mThumbnailProvider, tab.getId(), true, false));
+
+                mLastSelectedTabListModelIndex = oldIndex;
+                if (mTabToAddDelayed != null && mTabToAddDelayed == tab) {
+                    // If tab is being added later, it will be selected later.
+                    return;
                 }
+                selectTab(oldIndex, newIndex);
             }
 
             @Override
@@ -651,9 +644,16 @@
             }
 
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 if (!mTabModelSelector.isTabStateInitialized()) return;
+                // Check if we need to delay tab addition to model.
+                boolean delayAdd =
+                        (type == TabLaunchType.FROM_TAB_SWITCHER_UI) && markedForSelection;
+                if (delayAdd) {
+                    mTabToAddDelayed = tab;
+                    return;
+                }
                 onTabAdded(tab, !mActionsOnAllRelatedTabs);
                 if (type == TabLaunchType.FROM_RESTORE && mActionsOnAllRelatedTabs) {
                     // When tab is restored after restoring stage (e.g. exiting multi-window mode,
@@ -786,6 +786,26 @@
         }
     }
 
+    private void selectTab(int oldIndex, int newIndex) {
+        if (oldIndex != TabModel.INVALID_TAB_INDEX) {
+            int lastId = mModel.get(oldIndex).model.get(TAB_ID);
+            mModel.get(oldIndex).model.set(TabProperties.IS_SELECTED, false);
+            if (mActionsOnAllRelatedTabs && mThumbnailProvider != null && mVisible) {
+                mModel.get(oldIndex).model.set(TabProperties.THUMBNAIL_FETCHER,
+                        new ThumbnailFetcher(mThumbnailProvider, lastId, true, false));
+            }
+        }
+
+        if (newIndex != TabModel.INVALID_TAB_INDEX) {
+            int newId = mModel.get(newIndex).model.get(TAB_ID);
+            mModel.get(newIndex).model.set(TabProperties.IS_SELECTED, true);
+            if (mThumbnailProvider != null && mVisible) {
+                mModel.get(newIndex).model.set(TabProperties.THUMBNAIL_FETCHER,
+                        new ThumbnailFetcher(mThumbnailProvider, newId, true, false));
+            }
+        }
+    }
+
     public void initWithNative(Profile profile) {
         mTabListFaviconProvider.initWithNative(profile);
         mTabModelSelector.getTabModelFilterProvider().addTabModelFilterObserver(mTabModelObserver);
@@ -1121,11 +1141,12 @@
         return index;
     }
 
-    private void onTabAdded(Tab tab, boolean onlyShowRelatedTabs) {
+    private int onTabAdded(Tab tab, boolean onlyShowRelatedTabs) {
         int index = getIndexOfTab(tab, onlyShowRelatedTabs);
-        if (index == TabList.INVALID_TAB_INDEX) return;
+        if (index == TabList.INVALID_TAB_INDEX) return index;
 
         addTabInfoToModel(PseudoTab.fromTab(tab), index, mTabModelSelector.getCurrentTab() == tab);
+        return index;
     }
 
     private void onTabMoved(int newIndex, int curIndex) {
@@ -1246,6 +1267,12 @@
     void postHiding() {
         mVisible = false;
         unregisterOnScrolledListener();
+        // if tab was marked for add later, add to model and mark as selected.
+        if (mTabToAddDelayed != null) {
+            int index = onTabAdded(mTabToAddDelayed, !mActionsOnAllRelatedTabs);
+            selectTab(mLastSelectedTabListModelIndex, index);
+            mTabToAddDelayed = null;
+        }
     }
 
     private boolean isSelectedTab(PseudoTab tab, int tabModelSelectedTabId) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupAction.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupAction.java
index 25a7c01..da3adc6 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupAction.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupAction.java
@@ -72,8 +72,6 @@
 
         // Sort tabs by index prevent visual bugs when undoing.
         List<Tab> sortedTabs = new ArrayList<>(selectedTabs.size());
-        // Ensure tab count is as expected and the group doesn't get shuffled.
-        sortedTabs.addAll(relatedTabs);
         TabModel model = getTabModelSelector().getCurrentModel();
         for (int i = 0; i < model.getCount(); i++) {
             Tab tab = model.getTabAt(i);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
index 0e388a6..a9585c3c 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorMediator.java
@@ -119,7 +119,8 @@
 
         mTabModelObserver = new TabModelSelectorTabModelObserver(mTabModelSelector) {
             @Override
-            public void didAddTab(Tab tab, int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, int type, @TabCreationState int creationState,
+                    boolean markedForSelection) {
                 if (!mTabModelSelector.isTabStateInitialized()) return;
                 // When tab is added due to multi-window close or moving between multiple windows,
                 // force hiding the selection editor.
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
index c307c5d8..e728f76 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherMediator.java
@@ -327,7 +327,8 @@
 
         mTabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(Tab tab, int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, int type, @TabCreationState int creationState,
+                    boolean markedForSelection) {
                 // TODO(wychen): move didAddTab and didSelectTab to another observer and inject
                 //  after restoreCompleted.
                 if (!mTabModelSelector.isTabStateInitialized()) {
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java
index b291905..8c8cd4d 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/UndoGroupSnackbarController.java
@@ -97,8 +97,8 @@
         mTabModelSelectorTabModelObserver =
                 new TabModelSelectorTabModelObserver(mTabModelSelector) {
                     @Override
-                    public void didAddTab(
-                            Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                    public void didAddTab(Tab tab, @TabLaunchType int type,
+                            @TabCreationState int creationState, boolean markedForSelection) {
                         mSnackbarManager.dismissSnackbars(UndoGroupSnackbarController.this);
                     }
 
@@ -132,7 +132,13 @@
     }
 
     private void showUndoGroupSnackbar(List<TabUndoInfo> tabUndoInfo) {
-        String content = String.format(Locale.getDefault(), "%d", tabUndoInfo.size());
+        int mergedGroupSize = mTabModelSelector.getTabModelFilterProvider()
+                                      .getCurrentTabModelFilter()
+                                      .getRelatedTabIds(tabUndoInfo.get(0).tabOriginalGroupId)
+                                      .size();
+        assert mergedGroupSize > 1;
+
+        String content = String.format(Locale.getDefault(), "%d", mergedGroupSize);
         mSnackbarManager.showSnackbar(
                 Snackbar.make(content, this, Snackbar.TYPE_ACTION,
                                 Snackbar.UMA_TAB_GROUP_MANUAL_CREATION_UNDO)
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java
index a283f8a9..5d422c9 100644
--- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java
+++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserver.java
@@ -33,7 +33,8 @@
 
         mTabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(Tab tab, int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, int type, @TabCreationState int creationState,
+                    boolean markedForSelection) {
                 onTabContextChanged(TabContextChangeReason.TAB_ADDED);
             }
 
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
index a773dee..0e94c09 100644
--- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
+++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabUiTestHelper.java
@@ -586,7 +586,7 @@
 
     /**
      * Verify that the snack bar is showing and click on the snack bar button. Right now it is only
-     * used for undoing a tab closure. This should be used with
+     * used for undoing a tab closure or undoing a tab group merge. This should be used with
      * CriteriaHelper.pollInstrumentationThread().
      * @return whether the visibility checking and the clicking have finished or not.
      */
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
index 78ec6d6..f0f5f21 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMediatorUnitTest.java
@@ -471,7 +471,7 @@
 
         doReturn(true).when(mTabModelSelector).isTabStateInitialized();
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.get(TabGridPanelProperties.ANIMATION_SOURCE_VIEW), equalTo(null));
         verify(mDialogController).resetWithListOfTabs(null);
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
index 8a6b3d2..1c4927d8 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiMediatorUnitTest.java
@@ -533,9 +533,9 @@
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
 
         mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
         mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE);
+                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE, false);
 
         // Strip should be not be reset when adding a single new tab.
         verifyNeverReset();
@@ -552,7 +552,8 @@
         doReturn(tabs).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
 
         mTabModelObserverArgumentCaptor.getValue().didAddTab(newTab,
-                TabLaunchType.FROM_LONGPRESS_BACKGROUND, TabCreationState.LIVE_IN_FOREGROUND);
+                TabLaunchType.FROM_LONGPRESS_BACKGROUND, TabCreationState.LIVE_IN_FOREGROUND,
+                false);
 
         // Strip should be be reset when long pressing a link and add a tab into group.
         verifyResetStrip(true, tabs);
@@ -570,7 +571,7 @@
 
         mTabModelObserverArgumentCaptor.getValue().didAddTab(newTab,
                 TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP,
-                TabCreationState.LIVE_IN_FOREGROUND);
+                TabCreationState.LIVE_IN_FOREGROUND, false);
 
         // Strip should be be reset when long pressing a link and add a tab into group.
         verifyResetStrip(true, tabs);
@@ -589,11 +590,12 @@
         doReturn(mTabGroup1).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
 
         mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
         mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE);
+                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE, false);
         mTabModelObserverArgumentCaptor.getValue().didAddTab(newTab,
-                TabLaunchType.FROM_LONGPRESS_BACKGROUND, TabCreationState.LIVE_IN_FOREGROUND);
+                TabLaunchType.FROM_LONGPRESS_BACKGROUND, TabCreationState.LIVE_IN_FOREGROUND,
+                false);
 
         // Strip should be not be reset through these two types of launching.
         verifyNeverReset();
@@ -609,8 +611,8 @@
         mTabGroup2.add(newTab);
         doReturn(mTabGroup2).when(mTabGroupModelFilter).getRelatedTabList(TAB4_ID);
 
-        mTabModelObserverArgumentCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_TAB_GROUP_UI, TabCreationState.LIVE_IN_FOREGROUND);
+        mTabModelObserverArgumentCaptor.getValue().didAddTab(newTab,
+                TabLaunchType.FROM_TAB_GROUP_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         // Strip should be not be reset through adding tab from UI.
         verifyNeverReset();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
index 935be18..1cd5f4e 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabListMediatorUnitTest.java
@@ -620,7 +620,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(3));
         assertThat(mModel.get(2).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
@@ -897,7 +897,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         // When tab restoring stage is not yet finished, this tab info should not be added to
         // property model.
@@ -925,7 +925,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         TabListMediator.TabActionListener actionListenerAfterUpdate =
                 mModel.get(1).model.get(TabProperties.TAB_SELECTED_LISTENER);
@@ -952,11 +952,11 @@
         mModel.clear();
 
         mMediatorTabModelObserver.didAddTab(
-                mTab2, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab2, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND, false);
         assertThat(mModel.size(), equalTo(0));
 
         mMediatorTabModelObserver.didAddTab(
-                mTab1, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab1, TabLaunchType.FROM_RESTORE, TabCreationState.LIVE_IN_FOREGROUND, false);
         assertThat(mModel.size(), equalTo(1));
     }
 
@@ -975,7 +975,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(3));
         assertThat(mModel.get(2).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
@@ -997,7 +997,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(2));
     }
@@ -1017,7 +1017,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(3));
         assertThat(mModel.get(1).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
@@ -1037,7 +1037,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(3));
         assertThat(mModel.get(2).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
@@ -1057,7 +1057,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(3));
         assertThat(mModel.get(1).model.get(TabProperties.TAB_ID), equalTo(TAB3_ID));
@@ -1075,7 +1075,7 @@
         assertThat(mModel.size(), equalTo(2));
 
         mTabModelObserverCaptor.getValue().didAddTab(
-                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                newTab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(2));
     }
@@ -1091,7 +1091,7 @@
         // Try to do a redundant addition by adding the PropertyModel of an existing tab to the
         // TabListModel.
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         assertThat(mModel.size(), equalTo(2));
     }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
index a6921f56..047d0a02 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/TabSelectionEditorGroupActionUnitTest.java
@@ -196,12 +196,10 @@
         Assert.assertEquals(7, holder.getSelectedAndRelatedTabs().get(3).getId());
         Assert.assertTrue(mAction.perform());
         List<Tab> expectedTabs = holder.getSelectedAndRelatedTabs();
-        Tab tab7 = expectedTabs.get(3);
-        expectedTabs.remove(3);
-        Tab tab8 = expectedTabs.get(2);
-        expectedTabs.remove(2);
-        expectedTabs.add(0, tab7);
-        expectedTabs.add(0, tab8);
+        // Remove selected destination tab and all related tabs from the expected tabs list
+        List<Tab> destinationAndRelatedTabs =
+                mGroupFilter.getRelatedTabList(holder.getSelectedTabIds().get(2));
+        expectedTabs.removeAll(destinationAndRelatedTabs);
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(2), true, true);
         verify(mDelegate).hideByAction();
@@ -238,6 +236,10 @@
         Assert.assertEquals(6, holder.getSelectedAndRelatedTabs().get(4).getId());
         Assert.assertTrue(mAction.perform());
         List<Tab> expectedTabs = holder.getSelectedAndRelatedTabs();
+        // Remove selected destination tab and all related tabs from the expected tabs list
+        List<Tab> destinationAndRelatedTabs =
+                mGroupFilter.getRelatedTabList(holder.getSelectedTabIds().get(0));
+        expectedTabs.removeAll(destinationAndRelatedTabs);
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(0), true, true);
         verify(mDelegate).hideByAction();
@@ -281,6 +283,10 @@
         Assert.assertEquals(1, holder.getSelectedAndRelatedTabs().get(8).getId());
         Assert.assertTrue(mAction.perform());
         List<Tab> expectedTabs = holder.getSelectedAndRelatedTabs();
+        // Remove selected destination tab and all related tabs from the expected tabs list
+        List<Tab> destinationAndRelatedTabs =
+                mGroupFilter.getRelatedTabList(holder.getSelectedTabIds().get(0));
+        expectedTabs.removeAll(destinationAndRelatedTabs);
         verify(mGroupFilter)
                 .mergeListOfTabsToGroup(expectedTabs, holder.getSelectedTabs().get(0), true, true);
         verify(mDelegate).hideByAction();
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserverTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserverTest.java
index f5b0338..dde1042 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserverTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabContextObserverTest.java
@@ -78,7 +78,7 @@
         TabContextObserverTestHelper tabContextObserverTestHelper =
                 new TabContextObserverTestHelper(mTabModelSelector);
         tabContextObserverTestHelper.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertEquals(TabContextObserver.TabContextChangeReason.TAB_ADDED,
                 tabContextObserverTestHelper.getChangeReason());
     }
diff --git a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestratorTest.java b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestratorTest.java
index d31626b1..1cea55a 100644
--- a/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestratorTest.java
+++ b/chrome/android/features/tab_ui/junit/src/org/chromium/chrome/browser/tasks/tab_management/suggestions/TabSuggestionsOrchestratorTest.java
@@ -132,7 +132,7 @@
         };
         tabSuggestionsOrchestrator.addObserver(tabSuggestionsObserver);
         tabSuggestionsOrchestrator.mTabContextObserver.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertEquals(1, suggestions.size());
         Assert.assertEquals(TAB_IDS.length, suggestions.get(0).getTabsInfo().size());
         for (int idx = 0; idx < TAB_IDS.length; idx++) {
@@ -172,7 +172,7 @@
             public void onTabSuggestionInvalidated() {}
         };
         tabSuggestionsOrchestrator.mTabContextObserver.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertEquals(0, suggestions.size());
     }
 
@@ -200,7 +200,7 @@
 
         tabSuggestionsOrchestrator.addObserver(tabSuggestionsObserver);
         tabSuggestionsOrchestrator.mTabContextObserver.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertNotNull(tabSuggestionsOrchestrator.mTabSuggestionFeedback);
         Assert.assertEquals(tabSuggestionsOrchestrator.mTabSuggestionFeedback.tabSuggestionResponse,
                 TabSuggestionFeedback.TabSuggestionResponse.ACCEPTED);
@@ -271,11 +271,11 @@
         tabSuggestionsOrchestrator.setFetchersForTesting();
         tabSuggestionsOrchestrator.addObserver(tabSuggestionsObserver);
         tabSuggestionsOrchestrator.mTabContextObserver.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertEquals(1, suggestions.size());
         suggestions.clear();
         tabSuggestionsOrchestrator.mTabContextObserver.mTabModelObserver.didAddTab(
-                null, 0, TabCreationState.LIVE_IN_FOREGROUND);
+                null, 0, TabCreationState.LIVE_IN_FOREGROUND, false);
         Assert.assertEquals(expectedSuggestions, suggestions.size());
         tabSuggestionsOrchestrator.restoreMinTimeBetweenPrefetchesForTesting();
     }
diff --git a/chrome/android/java/res/drawable/ic_install_webapp.xml b/chrome/android/java/res/drawable/ic_install_webapp.xml
new file mode 100644
index 0000000..6a3f201
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_install_webapp.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2022 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="@macro/default_icon_color">
+
+    <path
+        android:pathData="M7 23q-.825 0-1.412-.587Q5 21.825 5 21V3q0-.825.588-1.413Q6.175 1 7 1h7v5H7v12h10v-2h2v5q0 .825-.587 1.413Q17.825 23 17 23Zm11-9-5-5 1.4-1.4 2.6 2.6V3h2v7.2l2.6-2.6L23 9Z"
+        android:fillColor="@macro/default_icon_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/chrome/android/java/res/drawable/ic_open_webapk.xml b/chrome/android/java/res/drawable/ic_open_webapk.xml
new file mode 100644
index 0000000..38a55c08
--- /dev/null
+++ b/chrome/android/java/res/drawable/ic_open_webapk.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2022 The Chromium Authors
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+-->
+
+<vector
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24"
+    android:tint="@macro/default_icon_color">
+
+    <path
+        android:pathData="M7 23q-.825 0-1.412-.587Q5 21.825 5 21v-6h2v3h10V6H7v3H5V3q0-.825.588-1.413Q6.175 1 7 1h10q.825 0 1.413.587Q19 2.175 19 3v18q0 .825-.587 1.413Q17.825 23 17 23Zm3-7-1.4-1.4 1.55-1.6H2v-2h8.15L8.6 9.4 10 8l4 4Z"
+        android:fillColor="@macro/default_icon_color"
+        android:strokeWidth="1"/>
+</vector>
diff --git a/chrome/android/java/res/menu/custom_tabs_menu.xml b/chrome/android/java/res/menu/custom_tabs_menu.xml
index 6cbc79c..c346555 100644
--- a/chrome/android/java/res/menu/custom_tabs_menu.xml
+++ b/chrome/android/java/res/menu/custom_tabs_menu.xml
@@ -51,6 +51,9 @@
         <item android:id="@+id/add_to_homescreen_id"
             android:title="@string/menu_add_to_homescreen"
             android:orderInCategory="2" />
+        <item android:id="@+id/install_webapp_id"
+            android:title="@string/menu_install_webapp"
+            android:orderInCategory="2" />
         <item android:id="@+id/open_webapk_id"
             android:title="@string/menu_open_webapk"
             android:orderInCategory="2" />
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml
index 68f5b596..7749fd7 100644
--- a/chrome/android/java/res/menu/main_menu.xml
+++ b/chrome/android/java/res/menu/main_menu.xml
@@ -108,9 +108,12 @@
         <item android:id="@+id/add_to_homescreen_id"
             android:title="@string/menu_add_to_homescreen"
             android:icon="@drawable/ic_add_to_home_screen" />
+        <item android:id="@+id/install_webapp_id"
+            android:title="@string/menu_install_webapp"
+            android:icon="@drawable/ic_install_webapp" />
         <item android:id="@+id/open_webapk_id"
             android:title="@string/menu_open_webapk"
-            android:icon="@drawable/ic_add_to_home_screen" />
+            android:icon="@drawable/ic_open_webapk" />
         <item android:id="@+id/request_desktop_site_row_menu_id"
             android:title="@null">
           <menu>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
index 0e962e9d..be226e4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -648,8 +648,8 @@
                 }
 
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     if (type == TabLaunchType.FROM_LONGPRESS_BACKGROUND
                             || type == TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP
                             || type == TabLaunchType.FROM_RECENT_TABS
@@ -834,7 +834,11 @@
                 getTabModelSelector().getModel(false).commitAllTabClosures();
                 // This assumes that the keyboard can not be seen at the same time as the
                 // newtab button on the toolbar.
-                getCurrentTabCreator().launchNTP();
+                int tabLaunchType =
+                        (getLayoutManager().getActiveLayoutType() == LayoutType.TAB_SWITCHER)
+                        ? TabLaunchType.FROM_TAB_SWITCHER_UI
+                        : TabLaunchType.FROM_CHROME_UI;
+                getCurrentTabCreator().launchNTP(tabLaunchType);
                 mLocaleManager.showSearchEnginePromoIfNeeded(ChromeTabbedActivity.this, null);
                 if (getTabModelSelector().isIncognitoSelected()) {
                     RecordUserAction.record("MobileToolbarStackViewNewIncognitoTab");
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/TabUsageTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/TabUsageTracker.java
index 6a036e73..214df53 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/TabUsageTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/TabUsageTracker.java
@@ -120,7 +120,8 @@
 
         mTabModelSelectorTabModelObserver = new TabModelSelectorTabModelObserver(mModelSelector) {
             @Override
-            public void didAddTab(Tab tab, int type, int creationState) {
+            public void didAddTab(
+                    Tab tab, int type, int creationState, boolean markedForSelection) {
                 mNewlyAddedTabCount++;
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
index ca4ed532..6eb9513 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -2521,36 +2521,17 @@
 
         if (id == R.id.add_to_homescreen_id) {
             RecordUserAction.record("MobileMenuAddToHomescreen");
-            PwaBottomSheetController controller =
-                    PwaBottomSheetControllerProvider.from(getWindowAndroid());
-            if (controller != null
-                    && controller.requestOrExpandBottomSheetInstaller(
-                            currentTab.getWebContents(), InstallTrigger.MENU)) {
-                return true;
-            }
-            AddToHomescreenCoordinator.showForAppMenu(this, getWindowAndroid(),
-                    getModalDialogManager(), currentTab.getWebContents(), mMenuItemData);
-            if (ChromeFeatureList.isEnabled(ChromeFeatureList.ADD_TO_HOMESCREEN_IPH)) {
-                Tracker tracker = TrackerFactory.getTrackerForProfile(
-                        Profile.fromWebContents(currentTab.getWebContents()));
-                tracker.notifyEvent(EventConstants.ADD_TO_HOMESCREEN_DIALOG_SHOWN);
-            }
-            return true;
+            return doAddToHomescreenOrInstallWebApp(currentTab);
+        }
+
+        if (id == R.id.install_webapp_id) {
+            RecordUserAction.record("InstallWebAppFromMenu");
+            return doAddToHomescreenOrInstallWebApp(currentTab);
         }
 
         if (id == R.id.open_webapk_id) {
-            Context context = ContextUtils.getApplicationContext();
-            String packageName =
-                    WebApkValidator.queryFirstWebApkPackage(context, currentTab.getUrl().getSpec());
-            Intent launchIntent = WebApkNavigationClient.createLaunchWebApkIntent(
-                    packageName, currentTab.getUrl().getSpec(), false);
-            try {
-                context.startActivity(launchIntent);
-                RecordUserAction.record("MobileMenuOpenWebApk");
-            } catch (ActivityNotFoundException e) {
-                Toast.makeText(context, R.string.open_webapk_failed, Toast.LENGTH_SHORT).show();
-            }
-            return true;
+            RecordUserAction.record("MobileMenuOpenWebApk");
+            return doOpenWebApk(currentTab);
         }
 
         if (id == R.id.request_desktop_site_id || id == R.id.request_desktop_site_check_id) {
@@ -2887,4 +2868,40 @@
     private static PrefService getPrefService() {
         return UserPrefs.get(Profile.getLastUsedRegularProfile());
     }
+
+    /**
+     * Returns whether the Add to Home screen or Install Web App action was successfully started.
+     */
+    private boolean doAddToHomescreenOrInstallWebApp(Tab currentTab) {
+        PwaBottomSheetController controller =
+                PwaBottomSheetControllerProvider.from(getWindowAndroid());
+        if (controller != null
+                && controller.requestOrExpandBottomSheetInstaller(
+                        currentTab.getWebContents(), InstallTrigger.MENU)) {
+            return true;
+        }
+        AddToHomescreenCoordinator.showForAppMenu(this, getWindowAndroid(), getModalDialogManager(),
+                currentTab.getWebContents(), mMenuItemData);
+        if (ChromeFeatureList.isEnabled(ChromeFeatureList.ADD_TO_HOMESCREEN_IPH)) {
+            Tracker tracker = TrackerFactory.getTrackerForProfile(
+                    Profile.fromWebContents(currentTab.getWebContents()));
+            tracker.notifyEvent(EventConstants.ADD_TO_HOMESCREEN_DIALOG_SHOWN);
+        }
+        return true;
+    }
+
+    /** Returns whether the Open WebAPK action was successfully started. */
+    private boolean doOpenWebApk(Tab currentTab) {
+        Context context = ContextUtils.getApplicationContext();
+        String packageName =
+                WebApkValidator.queryFirstWebApkPackage(context, currentTab.getUrl().getSpec());
+        Intent launchIntent = WebApkNavigationClient.createLaunchWebApkIntent(
+                packageName, currentTab.getUrl().getSpec(), false);
+        try {
+            context.startActivity(launchIntent);
+        } catch (ActivityNotFoundException e) {
+            Toast.makeText(context, R.string.open_webapk_failed, Toast.LENGTH_SHORT).show();
+        }
+        return true;
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
index ced473c..409b7fb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -876,13 +876,20 @@
      */
     protected void prepareAddToHomescreenMenuItem(
             Menu menu, Tab currentTab, boolean shouldShowHomeScreenMenuItem) {
-        MenuItem homescreenItem = menu.findItem(R.id.add_to_homescreen_id);
-        MenuItem openWebApkItem = menu.findItem(R.id.open_webapk_id);
         mAddAppTitleShown = AppMenuVerbiage.APP_MENU_OPTION_UNKNOWN;
+
+        MenuItem addTohomescreenItem = menu.findItem(R.id.add_to_homescreen_id);
+        MenuItem installWebAppItem = menu.findItem(R.id.install_webapp_id);
+        MenuItem openWebApkItem = menu.findItem(R.id.open_webapk_id);
+
+        addTohomescreenItem.setVisible(false);
+        installWebAppItem.setVisible(false);
+        openWebApkItem.setVisible(false);
+
         if (currentTab != null && shouldShowHomeScreenMenuItem) {
             Context context = ContextUtils.getApplicationContext();
             long addToHomeScreenStart = SystemClock.elapsedRealtime();
-            ResolveInfo resolveInfo = queryWebApkResolvInfo(context, currentTab);
+            ResolveInfo resolveInfo = queryWebApkResolveInfo(context, currentTab);
             RecordHistogram.recordTimesHistogram("Android.PrepareMenu.OpenWebApkVisibilityCheck",
                     SystemClock.elapsedRealtime() - addToHomeScreenStart);
 
@@ -892,29 +899,25 @@
             if (openWebApkItemVisible) {
                 String appName = resolveInfo.loadLabel(context.getPackageManager()).toString();
                 openWebApkItem.setTitle(context.getString(R.string.menu_open_webapk, appName));
-
-                homescreenItem.setVisible(false);
                 openWebApkItem.setVisible(true);
             } else {
                 AppBannerManager.InstallStringPair installStrings =
                         getAddToHomeScreenTitle(currentTab);
-                homescreenItem.setTitle(installStrings.titleTextId);
-                homescreenItem.setVisible(true);
-                openWebApkItem.setVisible(false);
 
                 if (installStrings.titleTextId == AppBannerManager.NON_PWA_PAIR.titleTextId) {
+                    addTohomescreenItem.setTitle(installStrings.titleTextId);
+                    addTohomescreenItem.setVisible(true);
                     mAddAppTitleShown = AppMenuVerbiage.APP_MENU_OPTION_ADD_TO_HOMESCREEN;
                 } else if (installStrings.titleTextId == AppBannerManager.PWA_PAIR.titleTextId) {
+                    installWebAppItem.setTitle(installStrings.titleTextId);
+                    installWebAppItem.setVisible(true);
                     mAddAppTitleShown = AppMenuVerbiage.APP_MENU_OPTION_INSTALL;
                 }
             }
-        } else {
-            homescreenItem.setVisible(false);
-            openWebApkItem.setVisible(false);
         }
     }
 
-    private ResolveInfo queryWebApkResolvInfo(Context context, Tab currentTab) {
+    private ResolveInfo queryWebApkResolveInfo(Context context, Tab currentTab) {
         ResolveInfo resolveInfo = null;
         if (ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_APK_UNIQUE_ID)) {
             String manifestId = AppBannerManager.maybeGetManifestId(currentTab.getWebContents());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
index 62c7663c..1d1cb3bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerImpl.java
@@ -207,8 +207,8 @@
         }
 
         @Override
-        public void didAddTab(
-                Tab tab, @TabLaunchType int launchType, @TabCreationState int creationState) {
+        public void didAddTab(Tab tab, @TabLaunchType int launchType,
+                @TabCreationState int creationState, boolean markedForSelection) {
             int tabId = tab.getId();
             if (launchType == TabLaunchType.FROM_RESTORE) {
                 getActiveLayout().onTabRestored(time(), tabId);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
index 05ca5ac..19032ea 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -566,8 +566,8 @@
 
         mTabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int launchType, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int launchType,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 updateTitleForTab(tab);
             }
         };
@@ -664,7 +664,8 @@
             }
 
             @Override
-            public void didAddTab(Tab tab, int type, int creationState) {
+            public void didAddTab(
+                    Tab tab, int type, int creationState, boolean markedForSelection) {
                 boolean selected = type != TabLaunchType.FROM_LONGPRESS_BACKGROUND
                         || (mTabModelSelector.isIncognitoSelected() && tab.isIncognito());
                 boolean onStartup = type == TabLaunchType.FROM_RESTORE;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
index 73c542a..e0fde2d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextualsearch/ContextualSearchManager.java
@@ -605,8 +605,8 @@
             }
 
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 // If we're in the process of promoting this tab, just return and don't mess with
                 // this state.
                 if (tab.getWebContents() == getSearchPanelWebContents()) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
index 810f8ab..943df1f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabDelegateFactory.java
@@ -113,9 +113,9 @@
         }
 
         @Override
-        public boolean shouldAvoidDisambiguationDialog(Intent intent) {
+        public boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl) {
             // Don't show the disambiguation dialog if Chrome could handle the intent.
-            return UrlUtilities.isAcceptedScheme(intent.toUri(0));
+            return UrlUtilities.isAcceptedScheme(intentDataUrl);
         }
 
         @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
index b245da6..bea2b68f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/TabObserverRegistrar.java
@@ -133,7 +133,8 @@
     }
 
     @Override
-    public void didAddTab(Tab tab, int type, @TabCreationState int creationState) {
+    public void didAddTab(
+            Tab tab, int type, @TabCreationState int creationState, boolean markedForSelection) {
         addObserversForTab(tab);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
index 881d6502..3daa6bb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/externalnav/ExternalNavigationDelegateImpl.java
@@ -217,7 +217,7 @@
     }
 
     @Override
-    public boolean shouldAvoidDisambiguationDialog(Intent intent) {
+    public boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl) {
         return false;
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
index 74dd333..83aac08 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31.java
@@ -301,7 +301,8 @@
             }
 
             @Override
-            public void didAddTab(Tab tab, int type, int creationState) {
+            public void didAddTab(
+                    Tab tab, int type, int creationState, boolean markedForSelection) {
                 writeTabCount(mInstanceId, selector);
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
index d1acebe..2ea177b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/offlinepages/OfflinePageUtils.java
@@ -806,8 +806,8 @@
         }
 
         @Override
-        public void didAddTab(
-                Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+        public void didAddTab(Tab tab, @TabLaunchType int type, @TabCreationState int creationState,
+                boolean markedForSelection) {
             tab.addObserver(sTabRestoreTracker);
         }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
index d02a284..fcd7a436 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -134,6 +134,8 @@
                 return "RecentTabs";
             case TabLaunchType.FROM_READING_LIST:
                 return "ReadingList";
+            case TabLaunchType.FROM_TAB_SWITCHER_UI:
+                return "TabSwitcherUI";
             default:
                 assert false : "Unexpected serialization of tabLaunchType: " + tabLaunchType;
                 return "TypeUnknown";
@@ -512,6 +514,7 @@
                 transition = PageTransition.LINK | PageTransition.FROM_API;
                 break;
             case TabLaunchType.FROM_CHROME_UI:
+            case TabLaunchType.FROM_TAB_SWITCHER_UI:
             case TabLaunchType.FROM_TAB_GROUP_UI:
             case TabLaunchType.FROM_STARTUP:
             case TabLaunchType.FROM_LAUNCHER_SHORTCUT:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
index 075401f..86b2bcd 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelImpl.java
@@ -250,7 +250,9 @@
             int newIndex = indexOf(tab);
             tabAddedToModel(tab);
 
-            for (TabModelObserver obs : mObservers) obs.didAddTab(tab, type, creationState);
+            for (TabModelObserver obs : mObservers) {
+                obs.didAddTab(tab, type, creationState, selectTab);
+            }
 
             // setIndex takes care of making sure the appropriate model is active.
             if (selectTab) setIndex(newIndex, TabSelectionType.FROM_NEW, false);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
index f8a1f90a..94da3c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserverJniBridge.java
@@ -75,8 +75,8 @@
     }
 
     @Override
-    public final void didAddTab(
-            Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+    public final void didAddTab(Tab tab, @TabLaunchType int type,
+            @TabCreationState int creationState, boolean markedForSelection) {
         assert mNativeTabModelObserverJniBridge != 0;
         TabModelObserverJniBridgeJni.get().didAddTab(
                 mNativeTabModelObserverJniBridge, TabModelObserverJniBridge.this, tab, type);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
index 6cd242050..4d48b97 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
@@ -72,8 +72,8 @@
 
         TabModelObserver tabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 notifyChanged();
                 notifyNewTabCreated(tab, creationState);
             }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewWrapper.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewWrapper.java
index 73ea007..c8b1947 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewWrapper.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/EmptyBackgroundViewWrapper.java
@@ -75,8 +75,8 @@
 
         mTabModelObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 updateEmptyContainerState();
             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/incognitotoggle/IncognitoToggleButtonTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/incognitotoggle/IncognitoToggleButtonTablet.java
index 2b95793..d09c69c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/incognitotoggle/IncognitoToggleButtonTablet.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ui/tablet/emptybackground/incognitotoggle/IncognitoToggleButtonTablet.java
@@ -70,8 +70,8 @@
 
             mTabModelObserver = new TabModelObserver() {
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     updateButtonVisibility();
                 }
 
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
index 3e1cc15a..3e201b6e 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -801,8 +801,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             tabSelector.getModel(false).addObserver(new TabModelObserver() {
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     openTabHelper.notifyCalled();
                 }
             });
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
index 082cc14..3146581 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/PageInfoViewTest.java
@@ -850,6 +850,7 @@
     @MediumTest
     @Feature({"RenderTest"})
     @Features.EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_3)
+    @Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
     public void testShowAdPersonalizationInfoSubPage() throws IOException {
         loadUrlAndOpenPageInfo(
                 mTestServerRule.getServer().getURLWithHostName("example.com", sSimpleHtml));
@@ -864,6 +865,7 @@
     @Test
     @MediumTest
     @Features.EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_3)
+    @Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
     public void testOpenAdPersonalizationSettings() throws IOException {
         loadUrlAndOpenPageInfo(
                 mTestServerRule.getServer().getURLWithHostName("example.com", sSimpleHtml));
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
index b36d53f2..c6d89319 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/PrivacySettingsFragmentTest.java
@@ -231,6 +231,7 @@
     @Test
     @LargeTest
     @Feature({"RenderTest"})
+    @Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
     public void testRenderIncognitoLockView_DeviceScreenLockDisabled() throws IOException {
         IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(true);
         IncognitoReauthSettingUtils.setIsDeviceScreenLockEnabledForTesting(false);
@@ -246,6 +247,7 @@
     @Test
     @LargeTest
     @Feature({"RenderTest"})
+    @Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
     public void testRenderIncognitoLockView_DeviceScreenLockEnabled() throws IOException {
         IncognitoReauthManager.setIsIncognitoReauthFeatureAvailableForTesting(true);
         IncognitoReauthSettingUtils.setIsDeviceScreenLockEnabledForTesting(true);
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java
index 4bc7d56..ec4ede0 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/subresource_filter/SubresourceFilterTest.java
@@ -163,16 +163,15 @@
         Tab originalTab = mActivityTestRule.getActivity().getActivityTab();
         CallbackHelper tabCreatedCallback = new CallbackHelper();
         TabModel tabModel = mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
-        TestThreadUtils.runOnUiThreadBlocking(
-                () -> tabModel.addObserver(new TabModelObserver() {
-                    @Override
-                    public void didAddTab(
-                            Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
-                        if (tab.getUrl().getSpec().equals(LEARN_MORE_PAGE)) {
-                            tabCreatedCallback.notifyCalled();
-                        }
-                    }
-                }));
+        TestThreadUtils.runOnUiThreadBlocking(() -> tabModel.addObserver(new TabModelObserver() {
+            @Override
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
+                if (tab.getUrl().getSpec().equals(LEARN_MORE_PAGE)) {
+                    tabCreatedCallback.notifyCalled();
+                }
+            }
+        }));
 
         // Check that the infobar is showing.
         List<InfoBar> infoBars = mActivityTestRule.getInfoBars();
@@ -279,8 +278,8 @@
         TabModel tabModel = mActivityTestRule.getActivity().getTabModelSelector().getCurrentModel();
         TestThreadUtils.runOnUiThreadBlocking(() -> tabModel.addObserver(new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 if (tab.getUrl().getSpec().equals(LEARN_MORE_PAGE)) {
                     tabCreatedCallback.notifyCalled();
                 }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
index e67850f..f43038b 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabDataTest.java
@@ -686,10 +686,11 @@
         Assert.assertEquals(16, LaunchTypeAtCreation.FROM_LONGPRESS_INCOGNITO);
         Assert.assertEquals(17, LaunchTypeAtCreation.FROM_RECENT_TABS);
         Assert.assertEquals(18, LaunchTypeAtCreation.FROM_READING_LIST);
+        Assert.assertEquals(19, LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI);
         Assert.assertEquals(
                 "Need to increment 1 to expected value each time a LaunchTypeAtCreation "
                         + "is added. Also need to add any new LaunchTypeAtCreation to this test.",
-                21, LaunchTypeAtCreation.names.length);
+                22, LaunchTypeAtCreation.names.length);
     }
 
     @SmallTest
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
index 8d9f5a2..cee1466 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModelTest.java
@@ -120,7 +120,8 @@
                 }
 
                 @Override
-                public void didAddTab(Tab tab, int type, int creationState) {
+                public void didAddTab(
+                        Tab tab, int type, int creationState, boolean markedForSelection) {
                     didAddTabCallbackHelper.notifyCalled();
                 }
             });
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
index 52c1b88..c2abc393 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateUnitTest.java
@@ -438,8 +438,8 @@
                                .withShowTranslate()
                                .withShowAddToHomeScreen()
                                .withAutoDarkEnabled());
-        doReturn(new AppBannerManager.InstallStringPair(R.string.menu_add_to_homescreen_install,
-                         R.string.menu_add_to_homescreen_install))
+        doReturn(new AppBannerManager.InstallStringPair(
+                         R.string.menu_install_webapp, R.string.app_banner_install))
                 .when(mAppMenuPropertiesDelegate)
                 .getAddToHomeScreenTitle(mTab);
 
@@ -451,13 +451,13 @@
                 R.id.new_incognito_tab_menu_id, R.id.divider_line_id, R.id.open_history_menu_id,
                 R.id.downloads_menu_id, R.id.all_bookmarks_menu_id, R.id.recent_tabs_menu_id,
                 R.id.divider_line_id, R.id.translate_id, R.id.share_row_menu_id,
-                R.id.find_in_page_id, R.id.add_to_homescreen_id,
-                R.id.request_desktop_site_row_menu_id, R.id.auto_dark_web_contents_row_menu_id,
-                R.id.divider_line_id, R.id.preferences_id, R.id.help_id};
+                R.id.find_in_page_id, R.id.install_webapp_id, R.id.request_desktop_site_row_menu_id,
+                R.id.auto_dark_web_contents_row_menu_id, R.id.divider_line_id, R.id.preferences_id,
+                R.id.help_id};
         Integer[] expectedTitles = {0, R.string.menu_new_tab, R.string.menu_new_incognito_tab, 0,
                 R.string.menu_history, R.string.menu_downloads, R.string.menu_bookmarks,
                 R.string.menu_recent_tabs, 0, 0, R.string.menu_find_in_page,
-                R.string.menu_translate, R.string.menu_add_to_homescreen_install, 0, 0, 0,
+                R.string.menu_translate, R.string.menu_install_webapp, 0, 0, 0,
                 R.string.menu_settings, R.string.menu_help};
         Integer[] expectedActionBarItems = {R.id.forward_menu_id, R.id.bookmark_this_page_id,
                 R.id.offline_page_id, R.id.info_menu_id, R.id.reload_menu_id};
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java
index 686a4c27..249b0b2 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/compositor/overlays/strip/TabUsageTrackerTest.java
@@ -83,8 +83,10 @@
         // Act: Create 2 tabs, select 1 tab and call onStop.
         TabModelSelectorTabModelObserver observer =
                 mTabUsageTracker.getTabModelSelectorTabModelObserverForTests();
-        observer.didAddTab(tab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
-        observer.didAddTab(tab2, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+        observer.didAddTab(
+                tab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
+        observer.didAddTab(
+                tab2, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
         observer.didSelectTab(tab1, TabLaunchType.FROM_CHROME_UI, 0);
 
         mTabUsageTracker.onStopWithNative();
@@ -110,7 +112,8 @@
         // Act: Create 1 tab, select 1 tab and call onStop.
         TabModelSelectorTabModelObserver observer =
                 mTabUsageTracker.getTabModelSelectorTabModelObserverForTests();
-        observer.didAddTab(tab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+        observer.didAddTab(
+                tab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
         observer.didSelectTab(tab1, TabLaunchType.FROM_CHROME_UI, 3);
 
         mTabUsageTracker.onStopWithNative();
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
index 8d780022..5c85bd5d 100644
--- a/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/multiwindow/MultiInstanceManagerApi31UnitTest.java
@@ -607,7 +607,7 @@
         } else {
             mNormalTabCount++;
         }
-        tabModelObserver.didAddTab(tab, 0, 0);
+        tabModelObserver.didAddTab(tab, 0, 0, false);
     }
 
     private void triggerOnFinishingTabClosure(TabModelObserver tabModelObserver, Tab tab) {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 8bccbad3..0e5a3fc1 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -8088,6 +8088,11 @@
      flag_descriptions::kChromeWhatsNewUIDescription, kOsDesktop,
      FEATURE_VALUE_TYPE(features::kChromeWhatsNewUI)},
 
+    {"sync-trusted-vault-passphrase-promo",
+     flag_descriptions::kSyncTrustedVaultPassphrasePromoName,
+     flag_descriptions::kSyncTrustedVaultPassphrasePromoDescription, kOsAll,
+     FEATURE_VALUE_TYPE(::syncer::kSyncTrustedVaultPassphrasePromo)},
+
     {"sync-standalone-invalidations", flag_descriptions::kSyncInvalidationsName,
      flag_descriptions::kSyncInvalidationsDescription, kOsAll,
      FEATURE_VALUE_TYPE(::syncer::kUseSyncInvalidations)},
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.h b/chrome/browser/apps/app_service/publishers/app_publisher.h
index 50f1b4c..91d89d9 100644
--- a/chrome/browser/apps/app_service/publishers/app_publisher.h
+++ b/chrome/browser/apps/app_service/publishers/app_publisher.h
@@ -257,7 +257,7 @@
   AppServiceProxy* proxy() { return proxy_; }
 
  private:
-  const raw_ptr<AppServiceProxy> proxy_;
+  const raw_ptr<AppServiceProxy, DanglingUntriaged> proxy_;
 };
 
 }  // namespace apps
diff --git a/chrome/browser/ash/crosapi/multi_capture_service_ash.h b/chrome/browser/ash/crosapi/multi_capture_service_ash.h
index b7dfa4c7..c2d35b9 100644
--- a/chrome/browser/ash/crosapi/multi_capture_service_ash.h
+++ b/chrome/browser/ash/crosapi/multi_capture_service_ash.h
@@ -33,7 +33,8 @@
  private:
   mojo::ReceiverSet<mojom::MultiCaptureService>
       multi_capture_service_receiver_set_;
-  base::raw_ptr<ash::MultiCaptureServiceClient> multi_capture_client_ = nullptr;
+  base::raw_ptr<ash::MultiCaptureServiceClient, DanglingUntriaged>
+      multi_capture_client_ = nullptr;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/ash/file_system_provider/mount_request_handler.h b/chrome/browser/ash/file_system_provider/mount_request_handler.h
index 0314264..34285157 100644
--- a/chrome/browser/ash/file_system_provider/mount_request_handler.h
+++ b/chrome/browser/ash/file_system_provider/mount_request_handler.h
@@ -34,7 +34,7 @@
   void OnAbort(int request_id) override;
 
  private:
-  raw_ptr<RequestDispatcher> request_dispatcher_;
+  raw_ptr<RequestDispatcher, DanglingUntriaged> request_dispatcher_;
   RequestMountCallback callback_;
 };
 
diff --git a/chrome/browser/ash/file_system_provider/operations/operation.h b/chrome/browser/ash/file_system_provider/operations/operation.h
index 0c048da..72f9939 100644
--- a/chrome/browser/ash/file_system_provider/operations/operation.h
+++ b/chrome/browser/ash/file_system_provider/operations/operation.h
@@ -56,7 +56,7 @@
   ProvidedFileSystemInfo file_system_info_;
 
  private:
-  raw_ptr<RequestDispatcher> request_dispatcher_;
+  raw_ptr<RequestDispatcher, DanglingUntriaged> request_dispatcher_;
 };
 
 }  // namespace operations
diff --git a/chrome/browser/ash/telemetry_extension/probe_service_converters.cc b/chrome/browser/ash/telemetry_extension/probe_service_converters.cc
index a50fcae4..aee217a 100644
--- a/chrome/browser/ash/telemetry_extension/probe_service_converters.cc
+++ b/chrome/browser/ash/telemetry_extension/probe_service_converters.cc
@@ -54,6 +54,8 @@
       return cros_healthd::mojom::ProbeCategoryEnum::kTpm;
     case crosapi::mojom::ProbeCategoryEnum::kAudio:
       return cros_healthd::mojom::ProbeCategoryEnum::kAudio;
+    case crosapi::mojom::ProbeCategoryEnum::kBus:
+      return cros_healthd::mojom::ProbeCategoryEnum::kBus;
   }
   NOTREACHED();
 }
@@ -115,6 +117,69 @@
   }
 }
 
+crosapi::mojom::ProbeUsbBusInterfaceInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::UsbBusInterfaceInfoPtr input) {
+  return crosapi::mojom::ProbeUsbBusInterfaceInfo::New(
+      crosapi::mojom::UInt8Value::New(input->interface_number),
+      crosapi::mojom::UInt8Value::New(input->class_id),
+      crosapi::mojom::UInt8Value::New(input->subclass_id),
+      crosapi::mojom::UInt8Value::New(input->protocol_id), input->driver);
+}
+
+crosapi::mojom::ProbeFwupdFirmwareVersionInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::FwupdFirmwareVersionInfoPtr input) {
+  return crosapi::mojom::ProbeFwupdFirmwareVersionInfo::New(
+      input->version, Convert(input->version_format));
+}
+
+crosapi::mojom::ProbeUsbBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::UsbBusInfoPtr input) {
+  return crosapi::mojom::ProbeUsbBusInfo::New(
+      crosapi::mojom::UInt8Value::New(input->class_id),
+      crosapi::mojom::UInt8Value::New(input->subclass_id),
+      crosapi::mojom::UInt8Value::New(input->protocol_id),
+      crosapi::mojom::UInt16Value::New(input->vendor_id),
+      crosapi::mojom::UInt16Value::New(input->product_id),
+      ConvertPtrVector<crosapi::mojom::ProbeUsbBusInterfaceInfoPtr>(
+          std::move(input->interfaces)),
+      ConvertProbePtr(std::move(input->fwupd_firmware_version_info)),
+      Convert(input->version), Convert(input->spec_speed));
+}
+
+crosapi::mojom::ProbeBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusInfoPtr input) {
+  switch (input->which()) {
+    case cros_healthd::mojom::internal::BusInfo_Data::BusInfo_Tag::kUsbBusInfo:
+      return crosapi::mojom::ProbeBusInfo::NewUsbBusInfo(
+          ConvertProbePtr(std::move(input->get_usb_bus_info())));
+    case cros_healthd::mojom::internal::BusInfo_Data::BusInfo_Tag::kPciBusInfo:
+    case cros_healthd::mojom::internal::BusInfo_Data::BusInfo_Tag::
+        kThunderboltBusInfo:
+    case cros_healthd::mojom::internal::BusInfo_Data::BusInfo_Tag::
+        kUnmappedField:
+      return nullptr;
+  }
+}
+
+crosapi::mojom::ProbeBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusDevicePtr input) {
+  return ConvertProbePtr(std::move(input->bus_info));
+}
+
+crosapi::mojom::ProbeBusResultPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusResultPtr input) {
+  switch (input->which()) {
+    case cros_healthd::mojom::internal::BusResult_Data::BusResult_Tag::
+        kBusDevices:
+      return crosapi::mojom::ProbeBusResult::NewBusDevicesInfo(
+          ConvertPtrVector<crosapi::mojom::ProbeBusInfoPtr>(
+              std::move(input->get_bus_devices())));
+    case cros_healthd::mojom::internal::BusResult_Data::BusResult_Tag::kError:
+      return crosapi::mojom::ProbeBusResult::NewError(
+          ConvertProbePtr(std::move(input->get_error())));
+  }
+}
+
 crosapi::mojom::ProbeBatteryInfoPtr UncheckedConvertPtr(
     cros_healthd::mojom::BatteryInfoPtr input) {
   return crosapi::mojom::ProbeBatteryInfo::New(
@@ -474,7 +539,8 @@
       std::move(system_result_output.second),
       ConvertProbePtr(std::move(input->network_result)),
       ConvertProbePtr(std::move(input->tpm_result)),
-      ConvertProbePtr(std::move(input->audio_result)));
+      ConvertProbePtr(std::move(input->audio_result)),
+      ConvertProbePtr(std::move(input->bus_result)));
 }
 
 }  // namespace unchecked
@@ -495,6 +561,82 @@
   NOTREACHED();
 }
 
+crosapi::mojom::ProbeUsbVersion Convert(cros_healthd::mojom::UsbVersion input) {
+  switch (input) {
+    case cros_healthd::mojom::UsbVersion::kUnmappedEnumField:
+      return crosapi::mojom::ProbeUsbVersion::kUnknown;
+    case cros_healthd::mojom::UsbVersion::kUnknown:
+      return crosapi::mojom::ProbeUsbVersion::kUnknown;
+    case cros_healthd::mojom::UsbVersion::kUsb1:
+      return crosapi::mojom::ProbeUsbVersion::kUsb1;
+    case cros_healthd::mojom::UsbVersion::kUsb2:
+      return crosapi::mojom::ProbeUsbVersion::kUsb2;
+    case cros_healthd::mojom::UsbVersion::kUsb3:
+      return crosapi::mojom::ProbeUsbVersion::kUsb3;
+  }
+  NOTREACHED();
+}
+
+crosapi::mojom::ProbeUsbSpecSpeed Convert(
+    cros_healthd::mojom::UsbSpecSpeed input) {
+  switch (input) {
+    case cros_healthd::mojom::UsbSpecSpeed::kUnmappedEnumField:
+      return crosapi::mojom::ProbeUsbSpecSpeed::kUnknown;
+    case cros_healthd::mojom::UsbSpecSpeed::kUnknown:
+      return crosapi::mojom::ProbeUsbSpecSpeed::kUnknown;
+    case cros_healthd::mojom::UsbSpecSpeed::k1_5Mbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k1_5Mbps;
+    case cros_healthd::mojom::UsbSpecSpeed::k12Mbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k12Mbps;
+    case cros_healthd::mojom::UsbSpecSpeed::kDeprecateSpeed:
+      return crosapi::mojom::ProbeUsbSpecSpeed::kUnknown;
+    case cros_healthd::mojom::UsbSpecSpeed::k480Mbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k480Mbps;
+    case cros_healthd::mojom::UsbSpecSpeed::k5Gbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k5Gbps;
+    case cros_healthd::mojom::UsbSpecSpeed::k10Gbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k10Gbps;
+    case cros_healthd::mojom::UsbSpecSpeed::k20Gbps:
+      return crosapi::mojom::ProbeUsbSpecSpeed::k20Gbps;
+  }
+  NOTREACHED();
+}
+
+crosapi::mojom::ProbeFwupdVersionFormat Convert(
+    cros_healthd::mojom::FwupdVersionFormat input) {
+  switch (input) {
+    case cros_healthd::mojom::FwupdVersionFormat::kUnmappedEnumField:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kUnknown;
+    case cros_healthd::mojom::FwupdVersionFormat::kUnknown:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kUnknown;
+    case cros_healthd::mojom::FwupdVersionFormat::kPlain:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kPlain;
+    case cros_healthd::mojom::FwupdVersionFormat::kNumber:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kNumber;
+    case cros_healthd::mojom::FwupdVersionFormat::kPair:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kPair;
+    case cros_healthd::mojom::FwupdVersionFormat::kTriplet:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kTriplet;
+    case cros_healthd::mojom::FwupdVersionFormat::kQuad:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kQuad;
+    case cros_healthd::mojom::FwupdVersionFormat::kBcd:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kBcd;
+    case cros_healthd::mojom::FwupdVersionFormat::kIntelMe:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kIntelMe;
+    case cros_healthd::mojom::FwupdVersionFormat::kIntelMe2:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kIntelMe2;
+    case cros_healthd::mojom::FwupdVersionFormat::kSurfaceLegacy:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kSurfaceLegacy;
+    case cros_healthd::mojom::FwupdVersionFormat::kSurface:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kSurface;
+    case cros_healthd::mojom::FwupdVersionFormat::kDellBios:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kDellBios;
+    case cros_healthd::mojom::FwupdVersionFormat::kHex:
+      return crosapi::mojom::ProbeFwupdVersionFormat::kHex;
+  }
+  NOTREACHED();
+}
+
 crosapi::mojom::ProbeCpuArchitectureEnum Convert(
     cros_healthd::mojom::CpuArchitectureEnum input) {
   switch (input) {
diff --git a/chrome/browser/ash/telemetry_extension/probe_service_converters.h b/chrome/browser/ash/telemetry_extension/probe_service_converters.h
index d3d5792e..264b88f6 100644
--- a/chrome/browser/ash/telemetry_extension/probe_service_converters.h
+++ b/chrome/browser/ash/telemetry_extension/probe_service_converters.h
@@ -37,6 +37,24 @@
 crosapi::mojom::ProbeAudioResultPtr UncheckedConvertPtr(
     cros_healthd::mojom::AudioResultPtr input);
 
+crosapi::mojom::ProbeUsbBusInterfaceInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::UsbBusInterfaceInfoPtr input);
+
+crosapi::mojom::ProbeFwupdFirmwareVersionInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::FwupdFirmwareVersionInfoPtr input);
+
+crosapi::mojom::ProbeUsbBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::UsbBusInfoPtr input);
+
+crosapi::mojom::ProbeBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusDevicePtr input);
+
+crosapi::mojom::ProbeBusInfoPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusInfoPtr input);
+
+crosapi::mojom::ProbeBusResultPtr UncheckedConvertPtr(
+    cros_healthd::mojom::BusResultPtr input);
+
 crosapi::mojom::ProbeBatteryInfoPtr UncheckedConvertPtr(
     cros_healthd::mojom::BatteryInfoPtr input);
 
@@ -152,6 +170,14 @@
 crosapi::mojom::ProbeTpmGSCVersion Convert(
     cros_healthd::mojom::TpmGSCVersion input);
 
+crosapi::mojom::ProbeUsbVersion Convert(cros_healthd::mojom::UsbVersion input);
+
+crosapi::mojom::ProbeUsbSpecSpeed Convert(
+    cros_healthd::mojom::UsbSpecSpeed input);
+
+crosapi::mojom::ProbeFwupdVersionFormat Convert(
+    cros_healthd::mojom::FwupdVersionFormat input);
+
 crosapi::mojom::BoolValuePtr Convert(bool input);
 
 crosapi::mojom::DoubleValuePtr Convert(double input);
diff --git a/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc b/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc
index 8a2469b..39412692 100644
--- a/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc
+++ b/chrome/browser/ash/telemetry_extension/probe_service_converters_unittest.cc
@@ -258,6 +258,248 @@
   EXPECT_TRUE(output->is_error());
 }
 
+TEST(ProbeServiceConverters, ProbeUsbVersion) {
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbVersion::kUnmappedEnumField),
+            crosapi::mojom::ProbeUsbVersion::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbVersion::kUnknown),
+            crosapi::mojom::ProbeUsbVersion::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbVersion::kUsb1),
+            crosapi::mojom::ProbeUsbVersion::kUsb1);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbVersion::kUsb2),
+            crosapi::mojom::ProbeUsbVersion::kUsb2);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbVersion::kUsb3),
+            crosapi::mojom::ProbeUsbVersion::kUsb3);
+}
+
+TEST(ProbeServiceConverters, ProbeUsbSpecSpeed) {
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::kUnmappedEnumField),
+            crosapi::mojom::ProbeUsbSpecSpeed::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::kUnknown),
+            crosapi::mojom::ProbeUsbSpecSpeed::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k1_5Mbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k1_5Mbps);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k12Mbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k12Mbps);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::kDeprecateSpeed),
+            crosapi::mojom::ProbeUsbSpecSpeed::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k480Mbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k480Mbps);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k5Gbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k5Gbps);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k10Gbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k10Gbps);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::UsbSpecSpeed::k20Gbps),
+            crosapi::mojom::ProbeUsbSpecSpeed::k20Gbps);
+}
+
+TEST(ProbeServiceConverters, ProbeFwupdVersionFormat) {
+  EXPECT_EQ(
+      Convert(cros_healthd::mojom::FwupdVersionFormat::kUnmappedEnumField),
+      crosapi::mojom::ProbeFwupdVersionFormat::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kUnknown),
+            crosapi::mojom::ProbeFwupdVersionFormat::kUnknown);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kPlain),
+            crosapi::mojom::ProbeFwupdVersionFormat::kPlain);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kNumber),
+            crosapi::mojom::ProbeFwupdVersionFormat::kNumber);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kPair),
+            crosapi::mojom::ProbeFwupdVersionFormat::kPair);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kTriplet),
+            crosapi::mojom::ProbeFwupdVersionFormat::kTriplet);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kBcd),
+            crosapi::mojom::ProbeFwupdVersionFormat::kBcd);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kIntelMe),
+            crosapi::mojom::ProbeFwupdVersionFormat::kIntelMe);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kIntelMe2),
+            crosapi::mojom::ProbeFwupdVersionFormat::kIntelMe2);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kSurfaceLegacy),
+            crosapi::mojom::ProbeFwupdVersionFormat::kSurfaceLegacy);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kSurface),
+            crosapi::mojom::ProbeFwupdVersionFormat::kSurface);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kDellBios),
+            crosapi::mojom::ProbeFwupdVersionFormat::kDellBios);
+
+  EXPECT_EQ(Convert(cros_healthd::mojom::FwupdVersionFormat::kHex),
+            crosapi::mojom::ProbeFwupdVersionFormat::kHex);
+}
+
+TEST(ProbeServiceConverters, ProbeFwupdFirmwareVersionInfoPtr) {
+  constexpr char kVersion[] = "MyVersion";
+
+  auto input = cros_healthd::mojom::FwupdFirmwareVersionInfo::New(
+      kVersion, cros_healthd::mojom::FwupdVersionFormat::kHex);
+
+  EXPECT_EQ(ConvertProbePtr(std::move(input)),
+            crosapi::mojom::ProbeFwupdFirmwareVersionInfo::New(
+                kVersion, crosapi::mojom::ProbeFwupdVersionFormat::kHex));
+}
+
+TEST(ProbeServiceConverters, ProbeUsbBusInterfaceInfoPtr) {
+  constexpr uint8_t kInterfaceNumber = 42;
+  constexpr uint8_t kClassId = 41;
+  constexpr uint8_t kSubclassId = 43;
+  constexpr uint8_t kProtocolId = 43;
+  constexpr char kDriver[] = "MyDriver";
+
+  EXPECT_EQ(ConvertProbePtr(cros_healthd::mojom::UsbBusInterfaceInfo::New(
+                kInterfaceNumber, kClassId, kSubclassId, kProtocolId, kDriver)),
+            crosapi::mojom::ProbeUsbBusInterfaceInfo::New(
+                crosapi::mojom::UInt8Value::New(kInterfaceNumber),
+                crosapi::mojom::UInt8Value::New(kClassId),
+                crosapi::mojom::UInt8Value::New(kSubclassId),
+                crosapi::mojom::UInt8Value::New(kProtocolId), kDriver));
+}
+
+TEST(ProbeServiceConverters, ProbeUsbBusInfoPtr) {
+  constexpr uint8_t kInterfaceNumberInterface = 42;
+  constexpr uint8_t kClassIdInterface = 41;
+  constexpr uint8_t kSubclassIdInterface = 45;
+  constexpr uint8_t kProtocolIdInterface = 43;
+  constexpr char kDriverInterface[] = "MyDriver";
+
+  std::vector<cros_healthd::mojom::UsbBusInterfaceInfoPtr> interfaces;
+  interfaces.push_back(cros_healthd::mojom::UsbBusInterfaceInfo::New(
+      kInterfaceNumberInterface, kClassIdInterface, kSubclassIdInterface,
+      kProtocolIdInterface, kDriverInterface));
+
+  constexpr uint8_t kClassId = 41;
+  constexpr uint8_t kSubclassId = 45;
+  constexpr uint8_t kProtocolId = 43;
+  constexpr uint16_t kVendor = 42;
+  constexpr uint16_t kProductId = 44;
+
+  constexpr char kVersion[] = "MyVersion";
+
+  auto fwupd_version = cros_healthd::mojom::FwupdFirmwareVersionInfo::New(
+      kVersion, cros_healthd::mojom::FwupdVersionFormat::kPair);
+
+  auto input = cros_healthd::mojom::UsbBusInfo::New();
+  input->class_id = kClassId;
+  input->subclass_id = kSubclassId;
+  input->protocol_id = kProtocolId;
+  input->vendor_id = kVendor;
+  input->product_id = kProductId;
+  input->interfaces = std::move(interfaces);
+  input->fwupd_firmware_version_info = std::move(fwupd_version);
+  input->version = cros_healthd::mojom::UsbVersion::kUsb3;
+  input->spec_speed = cros_healthd::mojom::UsbSpecSpeed::k20Gbps;
+
+  std::vector<crosapi::mojom::ProbeUsbBusInterfaceInfoPtr> expected_interfaces;
+  expected_interfaces.push_back(crosapi::mojom::ProbeUsbBusInterfaceInfo::New(
+      crosapi::mojom::UInt8Value::New(kInterfaceNumberInterface),
+      crosapi::mojom::UInt8Value::New(kClassIdInterface),
+      crosapi::mojom::UInt8Value::New(kSubclassIdInterface),
+      crosapi::mojom::UInt8Value::New(kProtocolIdInterface), kDriverInterface));
+
+  auto expected_fwupd_version =
+      crosapi::mojom::ProbeFwupdFirmwareVersionInfo::New(
+          kVersion, crosapi::mojom::ProbeFwupdVersionFormat::kPair);
+
+  EXPECT_EQ(
+      ConvertProbePtr(std::move(input)),
+      crosapi::mojom::ProbeUsbBusInfo::New(
+          crosapi::mojom::UInt8Value::New(kClassId),
+          crosapi::mojom::UInt8Value::New(kSubclassId),
+          crosapi::mojom::UInt8Value::New(kProtocolId),
+          crosapi::mojom::UInt16Value::New(kVendor),
+          crosapi::mojom::UInt16Value::New(kProductId),
+          std::move(expected_interfaces), std::move(expected_fwupd_version),
+          crosapi::mojom::ProbeUsbVersion::kUsb3,
+          crosapi::mojom::ProbeUsbSpecSpeed::k20Gbps));
+}
+
+TEST(ProbeServiceConverters, ProbeBusInfoPtr) {
+  constexpr uint8_t kInterfaceNumberInterface = 42;
+  constexpr uint8_t kClassIdInterface = 41;
+  constexpr uint8_t kSubclassIdInterface = 43;
+  constexpr uint8_t kProtocolIdInterface = 43;
+  constexpr char kDriverInterface[] = "MyDriver";
+
+  std::vector<cros_healthd::mojom::UsbBusInterfaceInfoPtr> interfaces;
+  interfaces.push_back(cros_healthd::mojom::UsbBusInterfaceInfo::New(
+      kInterfaceNumberInterface, kClassIdInterface, kSubclassIdInterface,
+      kProtocolIdInterface, kDriverInterface));
+
+  constexpr char kVersion[] = "MyVersion";
+
+  auto fwupd_version = cros_healthd::mojom::FwupdFirmwareVersionInfo::New(
+      kVersion, cros_healthd::mojom::FwupdVersionFormat::kPair);
+
+  constexpr uint8_t kClassId = 41;
+  constexpr uint8_t kSubclassId = 45;
+  constexpr uint8_t kProtocolId = 43;
+  constexpr uint16_t kVendor = 42;
+  constexpr uint16_t kProductId = 44;
+
+  auto usb_bus_info = cros_healthd::mojom::UsbBusInfo::New();
+  usb_bus_info->class_id = kClassId;
+  usb_bus_info->subclass_id = kSubclassId;
+  usb_bus_info->protocol_id = kProtocolId;
+  usb_bus_info->vendor_id = kVendor;
+  usb_bus_info->product_id = kProductId;
+  usb_bus_info->interfaces = std::move(interfaces);
+  usb_bus_info->fwupd_firmware_version_info = std::move(fwupd_version);
+  usb_bus_info->version = cros_healthd::mojom::UsbVersion::kUsb3;
+  usb_bus_info->spec_speed = cros_healthd::mojom::UsbSpecSpeed::k20Gbps;
+
+  auto bus_info =
+      cros_healthd::mojom::BusInfo::NewUsbBusInfo(std::move(usb_bus_info));
+
+  std::vector<crosapi::mojom::ProbeUsbBusInterfaceInfoPtr> expected_interfaces;
+  expected_interfaces.push_back(crosapi::mojom::ProbeUsbBusInterfaceInfo::New(
+      crosapi::mojom::UInt8Value::New(kInterfaceNumberInterface),
+      crosapi::mojom::UInt8Value::New(kClassIdInterface),
+      crosapi::mojom::UInt8Value::New(kSubclassIdInterface),
+      crosapi::mojom::UInt8Value::New(kProtocolIdInterface), kDriverInterface));
+
+  auto expected_fwupd_version =
+      crosapi::mojom::ProbeFwupdFirmwareVersionInfo::New(
+          kVersion, crosapi::mojom::ProbeFwupdVersionFormat::kPair);
+
+  auto expected_usb_bus_info = crosapi::mojom::ProbeUsbBusInfo::New(
+      crosapi::mojom::UInt8Value::New(kClassId),
+      crosapi::mojom::UInt8Value::New(kSubclassId),
+      crosapi::mojom::UInt8Value::New(kProtocolId),
+      crosapi::mojom::UInt16Value::New(kVendor),
+      crosapi::mojom::UInt16Value::New(kProductId),
+      std::move(expected_interfaces), std::move(expected_fwupd_version),
+      crosapi::mojom::ProbeUsbVersion::kUsb3,
+      crosapi::mojom::ProbeUsbSpecSpeed::k20Gbps);
+
+  auto expected_bus_info = crosapi::mojom::ProbeBusInfo::NewUsbBusInfo(
+      std::move(expected_usb_bus_info));
+
+  EXPECT_EQ(ConvertProbePtr(bus_info->Clone()), expected_bus_info);
+
+  auto device_input = cros_healthd::mojom::BusDevice::New();
+  device_input->bus_info = std::move(bus_info);
+
+  EXPECT_EQ(ConvertProbePtr(std::move(device_input)), expected_bus_info);
+}
+
 TEST(ProbeServiceConverters, BatteryInfoPtr) {
   constexpr int64_t kCycleCount = (1LL << 62) + 45;
   constexpr double kVoltageNow = 1000000000000.2;
@@ -1180,6 +1422,8 @@
         cros_healthd::mojom::TpmInfo::New());
     input->audio_result = cros_healthd::mojom::AudioResult::NewAudioInfo(
         cros_healthd::mojom::AudioInfo::New());
+    input->bus_result = cros_healthd::mojom::BusResult::NewBusDevices(
+        std::vector<cros_healthd::mojom::BusDevicePtr>());
   }
 
   EXPECT_EQ(
@@ -1232,7 +1476,9 @@
                   crosapi::mojom::BoolValue::New(false),
                   crosapi::mojom::UInt32Value::New(0),
                   crosapi::mojom::UInt32Value::New(0), absl::nullopt,
-                  absl::nullopt))));
+                  absl::nullopt)),
+          crosapi::mojom::ProbeBusResult::NewBusDevicesInfo(
+              std::vector<crosapi::mojom::ProbeBusInfoPtr>())));
 }
 
 TEST(ProbeServiceConverters, TelemetryInfoPtrWithNullFields) {
@@ -1251,7 +1497,8 @@
                 crosapi::mojom::ProbeSystemResultPtr(nullptr),
                 crosapi::mojom::ProbeNetworkResultPtr(nullptr),
                 crosapi::mojom::ProbeTpmResultPtr(nullptr),
-                crosapi::mojom::ProbeAudioResultPtr(nullptr)));
+                crosapi::mojom::ProbeAudioResultPtr(nullptr),
+                crosapi::mojom::ProbeBusResultPtr(nullptr)));
 }
 
 }  // namespace ash::converters
diff --git a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
index 2af0d0a..a05adeb1 100644
--- a/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
+++ b/chrome/browser/banners/android/java/src/org/chromium/chrome/browser/banners/AppBannerManagerTest.java
@@ -1121,7 +1121,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             AppMenuCoordinator coordinator = mTabbedActivityTestRule.getAppMenuCoordinator();
             AppMenuTestSupport.showAppMenu(coordinator, null, false);
-            AppMenuTestSupport.callOnItemClick(coordinator, R.id.add_to_homescreen_id);
+            AppMenuTestSupport.callOnItemClick(coordinator, R.id.install_webapp_id);
         });
         mOnEventCallback.waitForCallback(callCount, 1);
 
@@ -1158,7 +1158,7 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             AppMenuCoordinator coordinator = mTabbedActivityTestRule.getAppMenuCoordinator();
             AppMenuTestSupport.showAppMenu(coordinator, null, false);
-            AppMenuTestSupport.callOnItemClick(coordinator, R.id.add_to_homescreen_id);
+            AppMenuTestSupport.callOnItemClick(coordinator, R.id.install_webapp_id);
         });
         mOnEventCallback.waitForCallback(callCount, 1);
 
diff --git a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
index 2b855bb6..c42625d0 100644
--- a/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
+++ b/chrome/browser/browsing_topics/browsing_topics_internals_browsertest.cc
@@ -2,12 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+#include "base/i18n/time_formatting.h"
 #include "chrome/browser/browsing_topics/browsing_topics_service_factory.h"
 #include "chrome/browser/history/history_service_factory.h"
 #include "chrome/browser/optimization_guide/browser_test_util.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h"
 #include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h"
 #include "chrome/browser/optimization_guide/page_content_annotations_service_factory.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/browser.h"
 #include "chrome/test/base/in_process_browser_test.h"
@@ -22,7 +25,10 @@
 #include "components/optimization_guide/core/optimization_guide_features.h"
 #include "components/optimization_guide/core/test_model_info_builder.h"
 #include "components/optimization_guide/core/test_optimization_guide_model_provider.h"
+#include "components/prefs/pref_service.h"
 #include "components/privacy_sandbox/privacy_sandbox_features.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
 #include "content/public/test/browsing_topics_test_util.h"
@@ -30,12 +36,15 @@
 #include "net/test/embedded_test_server/request_handler_util.h"
 #include "third_party/blink/public/common/features.h"
 #include "third_party/re2/src/re2/re2.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace browsing_topics {
 
 namespace {
 
 const char kBrowsingTopicsInternalsUrl[] = "chrome://topics-internals/";
+const char kBrowsingTopicsInternalsConsentInfoUrl[] =
+    "chrome://topics-internals/#consent-info";
 
 std::vector<optimization_guide::WeightedIdentifier> TopicsWithUniformWeight(
     const std::vector<int32_t>& topics,
@@ -266,6 +275,66 @@
 
     return html_content;
   }
+
+  std::string GetConsentInfoTabContent() {
+    std::string html_content = EvalJsInWebUI(R"(
+let result = '';
+
+let consentDivs = document.querySelector('.consent-info-div')
+  .querySelectorAll('div');
+consentDivs.forEach(consentDiv => {
+  result += consentDiv.textContent + '\n';
+});
+
+result
+      )");
+
+    return html_content;
+  }
+
+  std::string BuildExpectedConsentInfoString(int consent_status_string_id,
+                                             int consent_source_string_id) {
+    auto* privacy_sandbox_service =
+        PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
+
+    auto consent_text = privacy_sandbox_service->TopicsConsentLastUpdateText();
+
+    auto last_update_time = browser()->profile()->GetPrefs()->GetTime(
+        prefs::kPrivacySandboxTopicsConsentLastUpdateTime);
+
+    std::string expected_text =
+        "{topicsConsentStatusLabel} {topicsConsentStatus}\n"
+        "{topicsConsentSourceLabel} {topicsConsentSource}\n"
+        "{topicsConsentTimeLabel} {topicsConsentTime}\n"
+        "{topicsConsentTextLabel} {topicsConsentText}\n";
+
+    RE2::Replace(&expected_text, "{topicsConsentStatusLabel}",
+                 l10n_util::GetStringUTF8(
+                     IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL));
+    RE2::Replace(
+        &expected_text, "{topicsConsentSourceLabel}",
+        l10n_util::GetStringUTF8(
+            IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL));
+    RE2::Replace(
+        &expected_text, "{topicsConsentTimeLabel}",
+        l10n_util::GetStringUTF8(
+            IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL));
+    RE2::Replace(
+        &expected_text, "{topicsConsentTextLabel}",
+        l10n_util::GetStringUTF8(
+            IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL));
+
+    RE2::Replace(&expected_text, "{topicsConsentStatus}",
+                 l10n_util::GetStringUTF8(consent_status_string_id));
+    RE2::Replace(&expected_text, "{topicsConsentSource}",
+                 l10n_util::GetStringUTF8(consent_source_string_id));
+    RE2::Replace(&expected_text, "{topicsConsentTime}",
+                 base::UTF16ToUTF8(
+                     base::TimeFormatFriendlyDateAndTime(last_update_time)));
+    RE2::Replace(&expected_text, "{topicsConsentText}", consent_text);
+
+    return expected_text;
+  }
 };
 
 class BrowsingTopicsDisabledInternalsBrowserTest
@@ -278,6 +347,7 @@
             blink::features::kBrowsingTopics,
             features::kPrivacySandboxAdsAPIsOverride,
             privacy_sandbox::kPrivacySandboxSettings3,
+            privacy_sandbox::kPrivacySandboxSettings4,
             optimization_guide::features::kPageContentAnnotations,
             optimization_guide::features::kPageContentAnnotationsValidation,
             optimization_guide::features::kRemotePageMetadata,
@@ -332,6 +402,19 @@
 )");
 }
 
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsDisabledInternalsBrowserTest,
+                       ConsentInfo_ConsentNotRequired) {
+  EXPECT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(kBrowsingTopicsInternalsConsentInfoUrl)));
+
+  auto consent_string = GetConsentInfoTabContent();
+  auto expected_string = BuildExpectedConsentInfoString(
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED,
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT);
+
+  EXPECT_EQ(expected_string, consent_string);
+}
+
 class BrowsingTopicsInternalsBrowserTest
     : public BrowsingTopicsInternalsBrowserTestBase {
  public:
@@ -341,7 +424,9 @@
           {{"number_of_top_topics_per_epoch", "2"},
            {"time_period_per_epoch", "15s"}}},
          {features::kPrivacySandboxAdsAPIsOverride, {}},
-         {privacy_sandbox::kPrivacySandboxSettings3, {}}},
+         {privacy_sandbox::kPrivacySandboxSettings3, {}},
+         {privacy_sandbox::kPrivacySandboxSettings4,
+          {{"consent-required", "true"}}}},
         /*disabled_features=*/{});
   }
 
@@ -717,4 +802,72 @@
 )");
 }
 
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsInternalsBrowserTest,
+                       ConsentInfo_RequiresFragment) {
+  fixed_browsing_topics_service()->SetWebUIGetBrowsingTopicsStateResultOverride(
+      browsing_topics::mojom::WebUIGetBrowsingTopicsStateResult::
+          NewOverrideStatusMessage("Failed to get the topics state."));
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(),
+                                           GURL(kBrowsingTopicsInternalsUrl)));
+
+  constexpr char consent_tab_display[] = R"(
+    let element = document.querySelector('#consent-info')
+    window.getComputedStyle(element).display
+  )";
+
+  EXPECT_EQ("none", EvalJsInWebUI(consent_tab_display))
+      << "Consent info tab should be hidden if not fragment target";
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(kBrowsingTopicsInternalsConsentInfoUrl)));
+
+  EXPECT_EQ("block", EvalJsInWebUI(consent_tab_display))
+      << "Consent info tab should be visible if fragment target";
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsInternalsBrowserTest,
+                       ConsentInfo_ActiveConsent) {
+  fixed_browsing_topics_service()->SetWebUIGetBrowsingTopicsStateResultOverride(
+      browsing_topics::mojom::WebUIGetBrowsingTopicsStateResult::
+          NewOverrideStatusMessage("Failed to get the topics state."));
+
+  auto* privacy_sandbox_service =
+      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
+
+  privacy_sandbox_service->PromptActionOccurred(
+      PrivacySandboxService::PromptAction::kConsentAccepted);
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(kBrowsingTopicsInternalsConsentInfoUrl)));
+
+  auto consent_string = GetConsentInfoTabContent();
+  auto expected_string = BuildExpectedConsentInfoString(
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE,
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION);
+
+  EXPECT_EQ(expected_string, consent_string);
+}
+
+IN_PROC_BROWSER_TEST_F(BrowsingTopicsInternalsBrowserTest,
+                       ConsentInfo_InactiveConsent) {
+  fixed_browsing_topics_service()->SetWebUIGetBrowsingTopicsStateResultOverride(
+      browsing_topics::mojom::WebUIGetBrowsingTopicsStateResult::
+          NewOverrideStatusMessage("Failed to get the topics state."));
+
+  auto* privacy_sandbox_service =
+      PrivacySandboxServiceFactory::GetForProfile(browser()->profile());
+
+  privacy_sandbox_service->TopicsToggleChanged(/*new_value=*/false);
+
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(
+      browser(), GURL(kBrowsingTopicsInternalsConsentInfoUrl)));
+
+  auto consent_string = GetConsentInfoTabContent();
+  auto expected_string = BuildExpectedConsentInfoString(
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE,
+      IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS);
+
+  EXPECT_EQ(expected_string, consent_string);
+}
+
 }  // namespace browsing_topics
diff --git a/chrome/browser/cart/cart_service.h b/chrome/browser/cart/cart_service.h
index a87a1c6..97d3616 100644
--- a/chrome/browser/cart/cart_service.h
+++ b/chrome/browser/cart/cart_service.h
@@ -260,7 +260,7 @@
   std::unique_ptr<DiscountURLLoader> discount_url_loader_;
   raw_ptr<CouponService> coupon_service_;
   PrefChangeRegistrar pref_change_registrar_;
-  raw_ptr<commerce::ShoppingService> shopping_service_;
+  raw_ptr<commerce::ShoppingService, DanglingUntriaged> shopping_service_;
   base::WeakPtrFactory<CartService> weak_ptr_factory_{this};
 };
 
diff --git a/chrome/browser/dips/dips_helper_browsertest.cc b/chrome/browser/dips/dips_helper_browsertest.cc
index 9f7571a1d..86395eb 100644
--- a/chrome/browser/dips/dips_helper_browsertest.cc
+++ b/chrome/browser/dips/dips_helper_browsertest.cc
@@ -216,7 +216,7 @@
   }
 
  private:
-  raw_ptr<WebContents> web_contents_ = nullptr;
+  raw_ptr<WebContents, DanglingUntriaged> web_contents_ = nullptr;
   base::SimpleTestClock test_clock_;
   base::test::ScopedFeatureList scoped_feature_list_;
 };
diff --git a/chrome/browser/dips/dips_state.h b/chrome/browser/dips/dips_state.h
index f233b304..cf56350e 100644
--- a/chrome/browser/dips/dips_state.h
+++ b/chrome/browser/dips/dips_state.h
@@ -70,7 +70,7 @@
   StateValue ToStateValue() const { return state_; }
 
  private:
-  raw_ptr<DIPSStorage> storage_;
+  raw_ptr<DIPSStorage, DanglingUntriaged> storage_;
   std::string site_;
   bool was_loaded_;
   DirtyBit dirty_;
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
index 3a15bde..0bafcee 100644
--- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
+++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.cc
@@ -12,6 +12,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/account_consistency_mode_manager.h"
 #include "chrome/browser/signin/account_reconcilor_factory.h"
+#include "chrome/browser/signin/google_accounts_private_api_host.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/common/chrome_features.h"
 #include "components/signin/core/browser/account_reconcilor.h"
@@ -72,7 +73,8 @@
         WebAuthFlow::GET_AUTH_TOKEN, extension_name_);
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
     // `profile_` may be nullptr in tests.
-    if (profile_) {
+    if (profile_ &&
+        !base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
       AccountReconcilorFactory::GetForProfile(profile_)
           ->GetConsistencyCookieManager()
           ->AddExtraCookieManager(GetCookieManagerForPartition());
@@ -80,11 +82,35 @@
 #endif
   }
 
+  if (base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
+    StartWebFlow();
+    return;
+  }
+
   SetAccountsInCookie();
 }
 
+void GaiaRemoteConsentFlow::StartWebFlow() {
+  network::mojom::CookieManager* cookie_manager =
+      GetCookieManagerForPartition();
+  net::CookieOptions options;
+  for (const auto& cookie : resolution_data_.cookies) {
+    cookie_manager->SetCanonicalCookie(
+        cookie,
+        net::cookie_util::SimulatedCookieSource(cookie, url::kHttpsScheme),
+        options, network::mojom::CookieManager::SetCanonicalCookieCallback());
+  }
+
+  web_flow_->Start();
+  web_flow_started_ = true;
+}
+
 void GaiaRemoteConsentFlow::OnSetAccountsComplete(
     signin::SetAccountsInCookieResult result) {
+  // No need to inject account cookies when the flow is displayed in a browser
+  // tab.
+  DCHECK(!base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab));
+
   set_accounts_in_cookie_task_.reset();
   if (web_flow_started_) {
     return;
@@ -96,16 +122,6 @@
     return;
   }
 
-  network::mojom::CookieManager* cookie_manager =
-      GetCookieManagerForPartition();
-  net::CookieOptions options;
-  for (const auto& cookie : resolution_data_.cookies) {
-    cookie_manager->SetCanonicalCookie(
-        cookie,
-        net::cookie_util::SimulatedCookieSource(cookie, url::kHttpsScheme),
-        options, network::mojom::CookieManager::SetCanonicalCookieCallback());
-  }
-
   identity_api_set_consent_result_subscription_ =
       IdentityAPI::GetFactoryInstance()
           ->Get(profile_)
@@ -114,18 +130,11 @@
                                   base::Unretained(this)));
 
   scoped_observation_.Observe(IdentityManagerFactory::GetForProfile(profile_));
-  web_flow_->Start();
-  web_flow_started_ = true;
+  StartWebFlow();
 }
 
-void GaiaRemoteConsentFlow::OnConsentResultSet(
-    const std::string& consent_result,
-    const std::string& window_id) {
-  if (!web_flow_ || window_id != web_flow_->GetAppWindowKey())
-    return;
-
-  identity_api_set_consent_result_subscription_ = {};
-
+void GaiaRemoteConsentFlow::ReactToConsentResult(
+    const std::string& consent_result) {
   bool consent_approved = false;
   std::string gaia_id;
   if (!gaia::ParseOAuth2MintTokenConsentResult(consent_result,
@@ -143,6 +152,21 @@
   delegate_->OnGaiaRemoteConsentFlowApproved(consent_result, gaia_id);
 }
 
+void GaiaRemoteConsentFlow::OnConsentResultSet(
+    const std::string& consent_result,
+    const std::string& window_id) {
+  // JS hook in a browser tab calls `ReactToConsentResult()` directly.
+  DCHECK(!base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab));
+
+  if (!web_flow_ || window_id != web_flow_->GetAppWindowKey()) {
+    return;
+  }
+
+  identity_api_set_consent_result_subscription_ = {};
+
+  ReactToConsentResult(consent_result);
+}
+
 void GaiaRemoteConsentFlow::OnAuthFlowFailure(WebAuthFlow::Failure failure) {
   GaiaRemoteConsentFlow::Failure gaia_failure;
 
@@ -192,6 +216,9 @@
 }
 
 void GaiaRemoteConsentFlow::OnEndBatchOfRefreshTokenStateChanges() {
+  // No need to copy added accounts when showing the flow in a browser tab.
+  DCHECK(!base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab));
+
 // On ChromeOS, new accounts are added through the account manager. They need to
 // be pushed to the partition used by this flow explicitly.
 // On Desktop, sign-in happens on the Web and a new account is directly added to
@@ -226,6 +253,10 @@
 }
 
 void GaiaRemoteConsentFlow::SetAccountsInCookie() {
+  // No need to inject account cookies when the flow is displayed in a browser
+  // tab.
+  DCHECK(!base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab));
+
   // Reset a task that is already in flight because it contains stale
   // information.
   if (set_accounts_in_cookie_task_)
@@ -278,7 +309,8 @@
 
 #if BUILDFLAG(IS_CHROMEOS_LACROS)
   // `profile_` may be nullptr in tests.
-  if (profile_) {
+  if (profile_ &&
+      !base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
     AccountReconcilorFactory::GetForProfile(profile_)
         ->GetConsistencyCookieManager()
         ->RemoveExtraCookieManager(GetCookieManagerForPartition());
@@ -287,4 +319,18 @@
   web_flow_.release()->DetachDelegateAndDelete();
 }
 
+void GaiaRemoteConsentFlow::OnNavigationFinished(
+    content::NavigationHandle* navigation_handle) {
+  // No need to create the receiver if we are not displaying the auth page
+  // through a Browser Tgab.
+  if (!base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
+    return;
+  }
+
+  GoogleAccountsPrivateApiHost::CreateReceiver(
+      base::BindRepeating(&GaiaRemoteConsentFlow::ReactToConsentResult,
+                          weak_factory.GetWeakPtr()),
+      navigation_handle);
+}
+
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
index dbbe0db..87ae9d59 100644
--- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
+++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h
@@ -7,6 +7,7 @@
 
 #include "base/callback_list.h"
 #include "base/memory/raw_ptr.h"
+#include "base/memory/weak_ptr.h"
 #include "base/scoped_observation.h"
 #include "chrome/browser/extensions/api/identity/extension_token_key.h"
 #include "chrome/browser/extensions/api/identity/web_auth_flow.h"
@@ -66,12 +67,19 @@
   // Set accounts in cookie completion callback.
   void OnSetAccountsComplete(signin::SetAccountsInCookieResult result);
 
-  // setConsentResult() JavaScript callback.
+  // setConsentResult() JavaScript callback when using an App Window to display
+  // the Auth page.
   void OnConsentResultSet(const std::string& consent_result,
                           const std::string& window_id);
 
+  // Handles `consent_result` value when using either a Browser Tab or an App
+  // Window to display the Auth page.
+  void ReactToConsentResult(const std::string& consent_result);
+
   // WebAuthFlow::Delegate:
   void OnAuthFlowFailure(WebAuthFlow::Failure failure) override;
+  void OnNavigationFinished(
+      content::NavigationHandle* navigation_handle) override;
 
   // signin::AccountsCookieMutator::PartitionDelegate:
   std::unique_ptr<GaiaAuthFetcher> CreateGaiaAuthFetcherForPartition(
@@ -87,6 +95,8 @@
   WebAuthFlow* GetWebAuthFlowForTesting() const;
 
  private:
+  void StartWebFlow();
+
   void SetAccountsInCookie();
 
   void GaiaRemoteConsentFlowFailed(Failure failure);
@@ -110,6 +120,8 @@
   base::ScopedObservation<signin::IdentityManager,
                           signin::IdentityManager::Observer>
       scoped_observation_{this};
+
+  base::WeakPtrFactory<GaiaRemoteConsentFlow> weak_factory{this};
 };
 
 }  // namespace extensions
diff --git a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_browsertest.cc b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_browsertest.cc
index 4fb52e8..352414f4 100644
--- a/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_browsertest.cc
+++ b/chrome/browser/extensions/api/identity/gaia_remote_consent_flow_browsertest.cc
@@ -4,15 +4,18 @@
 
 #include "chrome/browser/extensions/api/identity/gaia_remote_consent_flow.h"
 
+#include "base/strings/strcat.h"
 #include "chrome/browser/extensions/api/identity/identity_private_api.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/signin/identity_manager_factory.h"
 #include "chrome/browser/ui/browser.h"
+#include "chrome/common/chrome_features.h"
 #include "chrome/test/base/in_process_browser_test.h"
 #include "components/signin/public/base/consent_level.h"
 #include "components/signin/public/identity_manager/identity_manager.h"
 #include "components/signin/public/identity_manager/identity_test_utils.h"
 #include "content/public/test/browser_test.h"
+#include "content/public/test/browser_test_utils.h"
 #include "content/public/test/test_navigation_observer.h"
 #include "extensions/browser/api_test_utils.h"
 #include "google_apis/gaia/core_account_id.h"
@@ -54,9 +57,11 @@
                     const std::string& gaia_id));
 };
 
-class GaiaRemoteConsentFlowBrowserTest : public InProcessBrowserTest {
+class GaiaRemoteConsentFlowParamBrowserTest
+    : public InProcessBrowserTest,
+      public testing::WithParamInterface<bool> {
  public:
-  GaiaRemoteConsentFlowBrowserTest()
+  GaiaRemoteConsentFlowParamBrowserTest()
       : fake_gaia_test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
     std::unique_ptr<ash::MockNetworkPortalDetector>
@@ -74,6 +79,9 @@
     fake_gaia_test_server()->AddDefaultHandlers(GetChromeTestDataDir());
     fake_gaia_test_server_.RegisterRequestHandler(base::BindRepeating(
         &FakeGaia::HandleRequest, base::Unretained(&fake_gaia_)));
+
+    scoped_feature_list_.InitWithFeatureState(
+        features::kWebAuthFlowInBrowserTab, GetParam());
   }
 
   void SetUp() override {
@@ -148,13 +156,31 @@
     navigation_observer.Wait();
   }
 
-  void SimulateConsentResult(const std::string& consent_value,
-                             const std::string& window_id) {
+  void SimulateConsentResult(const std::string& consent_value) {
+    // When the auth flow is using the browser tab, we are able to properly test
+    // the JS injected script since we rely on the Gaia Origin to filter out
+    // unwanted urls, and in the test we are overriding the value of Gaia
+    // Origin, so we can bypass the filter for testing.
+    if (base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
+      // JS function is properly called but returns nullptr.
+      ASSERT_EQ(nullptr, content::EvalJs(
+                             flow()->GetWebAuthFlowForTesting()->web_contents(),
+                             "window.OAuthConsent.setConsentResult(\"" +
+                                 consent_value + "\")"));
+      return;
+    }
+
+    // Since we cannot bypass the filter that is added in the internal extension
+    // (in it's manifest) we do not directly test the JS function but instead
+    // the layer right above in the API through
+    // `IdentityPrivateSetConsentResultFunction`.
+    std::string consent_result =
+        "[\"" + consent_value + "\", \"" +
+        flow()->GetWebAuthFlowForTesting()->GetAppWindowKey() + "\"]";
     scoped_refptr<ExtensionFunction> func =
         base::MakeRefCounted<IdentityPrivateSetConsentResultFunction>();
-    ASSERT_TRUE(api_test_utils::RunFunction(
-        func.get(), "[\"" + consent_value + "\", \"" + window_id + "\"]",
-        profile()));
+    ASSERT_TRUE(
+        api_test_utils::RunFunction(func.get(), consent_result, profile()));
   }
 
   MockGaiaRemoteConsentFlowDelegate& mock() {
@@ -176,31 +202,31 @@
 
   net::EmbeddedTestServer fake_gaia_test_server_;
   FakeGaia fake_gaia_;
+
+  base::test::ScopedFeatureList scoped_feature_list_;
 };
 
-IN_PROC_BROWSER_TEST_F(GaiaRemoteConsentFlowBrowserTest,
+IN_PROC_BROWSER_TEST_P(GaiaRemoteConsentFlowParamBrowserTest,
                        SimulateInvalidConsent) {
   LaunchAndWaitGaiaRemoteConsentFlow();
 
   EXPECT_CALL(mock(),
               OnGaiaRemoteConsentFlowFailed(
                   GaiaRemoteConsentFlow::Failure::INVALID_CONSENT_RESULT));
-  SimulateConsentResult("invalid_consent",
-                        flow()->GetWebAuthFlowForTesting()->GetAppWindowKey());
+  SimulateConsentResult("invalid_consent");
 }
 
-IN_PROC_BROWSER_TEST_F(GaiaRemoteConsentFlowBrowserTest, SimulateNoGrant) {
+IN_PROC_BROWSER_TEST_P(GaiaRemoteConsentFlowParamBrowserTest, SimulateNoGrant) {
   LaunchAndWaitGaiaRemoteConsentFlow();
 
   EXPECT_CALL(mock(), OnGaiaRemoteConsentFlowFailed(
                           GaiaRemoteConsentFlow::Failure::NO_GRANT));
   std::string declined_consent = gaia::GenerateOAuth2MintTokenConsentResult(
       /*approved=*/false, "consent_not_granted", kGaiaId);
-  SimulateConsentResult(declined_consent,
-                        flow()->GetWebAuthFlowForTesting()->GetAppWindowKey());
+  SimulateConsentResult(declined_consent);
 }
 
-IN_PROC_BROWSER_TEST_F(GaiaRemoteConsentFlowBrowserTest,
+IN_PROC_BROWSER_TEST_P(GaiaRemoteConsentFlowParamBrowserTest,
                        SimulateAccessGranted) {
   LaunchAndWaitGaiaRemoteConsentFlow();
 
@@ -208,9 +234,18 @@
       /*approved=*/true, "consent_granted", kGaiaId);
   EXPECT_CALL(mock(),
               OnGaiaRemoteConsentFlowApproved(approved_consent, kGaiaId));
-  SimulateConsentResult(approved_consent,
-                        flow()->GetWebAuthFlowForTesting()->GetAppWindowKey());
+  SimulateConsentResult(approved_consent);
 }
 
+INSTANTIATE_TEST_SUITE_P(
+    ,
+    GaiaRemoteConsentFlowParamBrowserTest,
+    testing::Bool(),
+    [](const testing::TestParamInfo<
+        GaiaRemoteConsentFlowParamBrowserTest::ParamType>& info) {
+      return base::StrCat({"WebAuthFlowInBrowserTab_",
+                           info.param ? "FeatureOn" : "FeatureOff"});
+    });
+
 }  // namespace extensions
 #endif  // !BUILDFLAG(IS_CHROMEOS_LACROS)
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.cc b/chrome/browser/extensions/api/identity/web_auth_flow.cc
index 9ba2602..1fa41bda 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.cc
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.cc
@@ -136,8 +136,7 @@
   DCHECK(profile_);
   DCHECK(!profile_->IsOffTheRecord());
 
-  if (partition_ == WebAuthFlow::Partition::LAUNCH_WEB_AUTH_FLOW &&
-      base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
+  if (base::FeatureList::IsEnabled(features::kWebAuthFlowInBrowserTab)) {
     using_auth_with_browser_tab_ = true;
 
     content::WebContents::CreateParams params(profile_);
@@ -263,6 +262,11 @@
   }
 }
 
+bool WebAuthFlow::IsDisplayingAuthPageInTab() const {
+  // If web_contents_ is nullptr, then the auth page tab is opened.
+  return using_auth_with_browser_tab_ && !web_contents_;
+}
+
 void WebAuthFlow::BeforeUrlLoaded(const GURL& url) {
   if (delegate_ && IsObservingProviderWebContents())
     delegate_->OnAuthFlowURLChange(url);
@@ -276,8 +280,8 @@
 
   // If `web_contents_` is nullptr, this means that the interactive tab has
   // already been opened once.
-  if (delegate_ && using_auth_with_browser_tab_ &&
-      mode_ == WebAuthFlow::INTERACTIVE && web_contents_) {
+  if (delegate_ && using_auth_with_browser_tab_ && web_contents_ &&
+      mode_ == WebAuthFlow::INTERACTIVE) {
     chrome::ScopedTabbedBrowserDisplayer browser_displayer(profile_);
     NavigateParams params(browser_displayer.browser(),
                           std::move(web_contents_));
@@ -325,11 +329,10 @@
 
 void WebAuthFlow::DidStartNavigation(
     content::NavigationHandle* navigation_handle) {
-  // If web_contents_ is nullptr, then the auth page tab is opened.
   // If the navigation is initiated by the user, the tab will exit the auth
   // flow screen, this should result in a declined authentication and deleting
   // the flow.
-  if (using_auth_with_browser_tab_ && !web_contents_ &&
+  if (IsDisplayingAuthPageInTab() &&
       !navigation_handle->IsRendererInitiated()) {
     // Stop observing the web contents since it is not part of the flow anymore.
     WebContentsObserver::Observe(nullptr);
@@ -357,6 +360,10 @@
   if (!navigation_handle->IsInPrimaryMainFrame())
     return;
 
+  if (delegate_) {
+    delegate_->OnNavigationFinished(navigation_handle);
+  }
+
   bool failed = false;
   if (navigation_handle->GetNetErrorCode() != net::OK) {
     if (navigation_handle->GetURL().spec() == url::kAboutBlankURL) {
diff --git a/chrome/browser/extensions/api/identity/web_auth_flow.h b/chrome/browser/extensions/api/identity/web_auth_flow.h
index 554e142..d501132 100644
--- a/chrome/browser/extensions/api/identity/web_auth_flow.h
+++ b/chrome/browser/extensions/api/identity/web_auth_flow.h
@@ -78,6 +78,10 @@
     virtual void OnAuthFlowURLChange(const GURL& redirect_url) {}
     // Called when the title of the current page changes.
     virtual void OnAuthFlowTitleChange(const std::string& title) {}
+    // Called when the web_contents associated with the flow has finished
+    // navigation.
+    virtual void OnNavigationFinished(
+        content::NavigationHandle* navigation_handle) {}
 
    protected:
     virtual ~Delegate() {}
@@ -149,6 +153,8 @@
   void DisplayInfoBar();
   void CloseInfoBar();
 
+  bool IsDisplayingAuthPageInTab() const;
+
   raw_ptr<Delegate> delegate_ = nullptr;
   const raw_ptr<Profile> profile_;
   const GURL provider_url_;
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
index c322943..f54c13e 100644
--- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
+++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -11,13 +11,10 @@
 #include "ash/constants/ash_features.h"
 #include "ash/public/cpp/clipboard_history_controller.h"
 #include "ash/public/cpp/clipboard_image_model_factory.h"
-#include "ash/public/cpp/keyboard/keyboard_switches.h"
 #include "ash/public/cpp/keyboard/keyboard_types.h"
 #include "base/check.h"
-#include "base/command_line.h"
 #include "base/feature_list.h"
 #include "base/functional/bind.h"
-#include "base/metrics/field_trial_params.h"
 #include "base/metrics/user_metrics.h"
 #include "base/metrics/user_metrics_action.h"
 #include "base/values.h"
@@ -26,8 +23,7 @@
 #include "chrome/browser/profiles/profile_manager.h"
 #include "chrome/browser/ui/ash/keyboard/chrome_keyboard_controller_client.h"
 #include "chrome/browser/ui/settings_window_manager_chromeos.h"
-#include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom.h"
-#include "chrome/common/url_constants.h"
+#include "chrome/browser/ui/webui/settings/chromeos/constants/routes.mojom-forward.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "components/user_manager/user_manager.h"
 #include "content/public/browser/audio_service.h"
diff --git a/chrome/browser/extensions/extension_service_unittest.cc b/chrome/browser/extensions/extension_service_unittest.cc
index a4ce12c..8aaafbd 100644
--- a/chrome/browser/extensions/extension_service_unittest.cc
+++ b/chrome/browser/extensions/extension_service_unittest.cc
@@ -34,6 +34,7 @@
 #include "base/strings/utf_string_conversions.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/test/bind.h"
+#include "base/test/test_future.h"
 #include "base/time/time.h"
 #include "base/values.h"
 #include "base/version.h"
@@ -5204,15 +5205,10 @@
       blink::StorageKey(url::Origin::Create(ext_url)),
       area.BindNewPipeAndPassReceiver());
   {
-    bool success = false;
-    base::RunLoop run_loop;
+    base::test::TestFuture<bool> future;
     area->Put({'k', 'e', 'y'}, {'v', 'a', 'l', 'u', 'e'}, absl::nullopt,
-              "source", base::BindLambdaForTesting([&](bool success_in) {
-                success = success_in;
-                run_loop.Quit();
-              }));
-    run_loop.Run();
-    ASSERT_TRUE(success);
+              "source", future.GetCallback());
+    ASSERT_TRUE(future.Get());
   }
 
   // Create indexed db. It is enough to only simulate this by
@@ -5271,35 +5267,21 @@
   task_environment()->RunUntilIdle();
 
   // Check that the localStorage data been removed.
-  std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos;
   {
-    base::RunLoop run_loop;
-    local_storage_control->GetUsage(base::BindLambdaForTesting(
-        [&](std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos_in) {
-          usage_infos.swap(usage_infos_in);
-          run_loop.Quit();
-        }));
-    run_loop.Run();
+    base::test::TestFuture<std::vector<storage::mojom::StorageUsageInfoPtr>>
+        future;
+    local_storage_control->GetUsage(future.GetCallback());
+    EXPECT_TRUE(future.Get().empty());
   }
-  EXPECT_TRUE(usage_infos.empty());
 
   // Check if the indexed db has disappeared too.
   EXPECT_FALSE(base::DirectoryExists(idb_path));
 }
 
-void SetCookieSaveData(bool* result_out,
-                       base::OnceClosure callback,
-                       net::CookieAccessResult result) {
-  *result_out = result.status.IsInclude();
-  std::move(callback).Run();
-}
-
-void GetCookiesSaveData(std::vector<net::CanonicalCookie>* result_out,
-                        base::OnceClosure callback,
-                        const net::CookieAccessResultList& result,
-                        const net::CookieAccessResultList& excluded_cookies) {
-  *result_out = net::cookie_util::StripAccessResults(result);
-  std::move(callback).Run();
+std::vector<net::CanonicalCookie> IncludedCookies(
+    const net::CookieAccessResultList& result,
+    const net::CookieAccessResultList& excluded) {
+  return net::cookie_util::StripAccessResults(result);
 }
 
 // Verifies app state is removed upon uninstall.
@@ -5351,26 +5333,22 @@
   ASSERT_TRUE(cc.get());
 
   {
-    bool set_result = false;
-    base::RunLoop run_loop;
+    base::test::TestFuture<bool> future;
     cookie_manager_remote->SetCanonicalCookie(
         *cc.get(), origin1, net::CookieOptions::MakeAllInclusive(),
-        base::BindOnce(&SetCookieSaveData, &set_result,
-                       run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_TRUE(set_result);
+        base::BindOnce([](net::CookieAccessResult result) {
+          return result.status.IsInclude();
+        }).Then(future.GetCallback()));
+    EXPECT_TRUE(future.Get());
   }
 
   {
-    base::RunLoop run_loop;
-    std::vector<net::CanonicalCookie> cookies_result;
+    base::test::TestFuture<std::vector<net::CanonicalCookie>> future;
     cookie_manager_remote->GetCookieList(
         origin1, net::CookieOptions::MakeAllInclusive(),
         net::CookiePartitionKeyCollection(),
-        base::BindOnce(&GetCookiesSaveData, &cookies_result,
-                       run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_EQ(1U, cookies_result.size());
+        base::BindOnce(IncludedCookies).Then(future.GetCallback()));
+    EXPECT_EQ(1U, future.Get().size());
   }
 
   // Open a database.
@@ -5389,15 +5367,10 @@
       blink::StorageKey(url::Origin::Create(origin1)),
       area.BindNewPipeAndPassReceiver());
   {
-    bool success = false;
-    base::RunLoop run_loop;
+    base::test::TestFuture<bool> future;
     area->Put({'k', 'e', 'y'}, {'v', 'a', 'l', 'u', 'e'}, absl::nullopt,
-              "source", base::BindLambdaForTesting([&](bool success_in) {
-                success = success_in;
-                run_loop.Quit();
-              }));
-    run_loop.Run();
-    ASSERT_TRUE(success);
+              "source", future.GetCallback());
+    ASSERT_TRUE(future.Get());
   }
 
   // Create indexed db. It is enough to only simulate this by
@@ -5436,15 +5409,12 @@
 
   {
     // Check that the cookie is still there.
-    base::RunLoop run_loop;
-    std::vector<net::CanonicalCookie> cookies_result;
+    base::test::TestFuture<std::vector<net::CanonicalCookie>> future;
     cookie_manager_remote->GetCookieList(
         origin1, net::CookieOptions::MakeAllInclusive(),
         net::CookiePartitionKeyCollection(),
-        base::BindOnce(&GetCookiesSaveData, &cookies_result,
-                       run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_EQ(1U, cookies_result.size());
+        base::BindOnce(IncludedCookies).Then(future.GetCallback()));
+    EXPECT_EQ(1U, future.Get().size());
   }
 
   // Now uninstall the other. Storage should be cleared for the apps.
@@ -5456,15 +5426,12 @@
 
   {
     // Check that the cookie is gone.
-    base::RunLoop run_loop;
-    std::vector<net::CanonicalCookie> cookies_result;
+    base::test::TestFuture<std::vector<net::CanonicalCookie>> future;
     cookie_manager_remote->GetCookieList(
         origin1, net::CookieOptions::MakeAllInclusive(),
         net::CookiePartitionKeyCollection(),
-        base::BindOnce(&GetCookiesSaveData, &cookies_result,
-                       run_loop.QuitClosure()));
-    run_loop.Run();
-    EXPECT_EQ(0U, cookies_result.size());
+        base::BindOnce(IncludedCookies).Then(future.GetCallback()));
+    EXPECT_EQ(0U, future.Get().size());
   }
 
   // The database should have vanished as well.
@@ -5479,17 +5446,12 @@
   task_environment()->RunUntilIdle();
 
   // Check that the localStorage data been removed.
-  std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos;
   {
-    base::RunLoop run_loop;
-    local_storage_control->GetUsage(base::BindLambdaForTesting(
-        [&](std::vector<storage::mojom::StorageUsageInfoPtr> usage_infos_in) {
-          usage_infos.swap(usage_infos_in);
-          run_loop.Quit();
-        }));
-    run_loop.Run();
+    base::test::TestFuture<std::vector<storage::mojom::StorageUsageInfoPtr>>
+        future;
+    local_storage_control->GetUsage(future.GetCallback());
+    EXPECT_TRUE(future.Get().empty());
   }
-  EXPECT_TRUE(usage_infos.empty());
 
   // Check if the indexed db has disappeared too.
   EXPECT_FALSE(base::DirectoryExists(idb_path));
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRenderer.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRenderer.java
index ead17f21..ef20145 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRenderer.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRenderer.java
@@ -172,7 +172,8 @@
 
         @Override
         public boolean setColumnCount(int columnCount) {
-            return false;
+            // no-op operation for LinearLayout. Consider as success.
+            return true;
         }
     }
 }
diff --git a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRendererTest.java b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRendererTest.java
index f891f8f..fe63d22 100644
--- a/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRendererTest.java
+++ b/chrome/browser/feed/android/java/src/org/chromium/chrome/browser/feed/NativeViewListRendererTest.java
@@ -6,10 +6,10 @@
 
 import static org.hamcrest.CoreMatchers.instanceOf;
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
@@ -213,6 +213,6 @@
         mRenderer.bind(mManager);
 
         boolean res = mRenderer.getListLayoutHelper().setColumnCount(3);
-        assertFalse("Failed to set column count.", res);
+        assertTrue("Failed to set column count.", res);
     }
 }
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json
index cb587ba..2864e00 100644
--- a/chrome/browser/flag-metadata.json
+++ b/chrome/browser/flag-metadata.json
@@ -2746,11 +2746,6 @@
     "expiry_milestone": 115
   },
   {
-    "name": "enable-new-bookmarks-implementation",
-    "owners": [ "jlebel", "chrome-signin-team" ],
-    "expiry_milestone": 130
-  },
-  {
     "name": "enable-new-download-api",
     "owners": [ "sdefresne", "bling-flags@google.com" ],
     "expiry_milestone": 130
@@ -4387,6 +4382,11 @@
     "expiry_milestone": 109
   },
   {
+    "name": "ios-tabstrip-context-menu",
+    "owners": [ "ewannpv", "gambard", "bling-flags@google.com" ],
+    "expiry_milestone": 118
+  },
+  {
     "name": "ios-webpage-intent-annotations",
     "owners": [ "djean", "bling-flags@google.com" ],
     "expiry_milestone": 112
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index f2ae3e7..620e47e 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -310,6 +310,7 @@
     public static final String FEED_LOADING_PLACEHOLDER = "FeedLoadingPlaceholder";
     public static final String FEED_MULTI_COLUMN = "DiscoverFeedMultiColumn";
     public static final String FEED_NO_VIEW_CACHE = "FeedNoViewCache";
+    public static final String FEED_INTERACTIVE_REFRESH = "FeedInteractiveRefresh";
     public static final String FEED_PERFORMANCE_STUDY = "FeedPerformanceStudy";
     public static final String FEED_POSITION_ANDROID = "FeedPositionAndroid";
     public static final String FEED_SHOW_SIGN_IN_COMMAND = "FeedShowSignInCommand";
diff --git a/chrome/browser/hid/hid_status_icon.h b/chrome/browser/hid/hid_status_icon.h
index aa6d793..b914a78 100644
--- a/chrome/browser/hid/hid_status_icon.h
+++ b/chrome/browser/hid/hid_status_icon.h
@@ -39,7 +39,7 @@
   void RefreshIcon();
 
   // Reference to our status icon (if any) - owned by the StatusTray.
-  raw_ptr<StatusIcon> status_icon_ = nullptr;
+  raw_ptr<StatusIcon, DanglingUntriaged> status_icon_ = nullptr;
 
   // A list of profiles being tracked, each profile has an entry in the context
   // menu of the system tray icon. Each entry in |profiles_| is expected to be
diff --git a/chrome/browser/interest_group/interest_group_permissions_browsertest.cc b/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
index a3aa5be..cbee5c8 100644
--- a/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
+++ b/chrome/browser/interest_group/interest_group_permissions_browsertest.cc
@@ -16,6 +16,7 @@
 #include "components/content_settings/core/common/content_settings.h"
 #include "components/content_settings/core/common/pref_names.h"
 #include "components/prefs/pref_service.h"
+#include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "components/privacy_sandbox/privacy_sandbox_settings.h"
 #include "content/public/common/content_features.h"
 #include "content/public/test/browser_test.h"
@@ -32,9 +33,11 @@
         /*enabled_features=*/
         {blink::features::kInterestGroupStorage,
          blink::features::kAdInterestGroupAPI, blink::features::kFledge,
-         features::kPrivacySandboxAdsAPIsOverride},
+         features::kPrivacySandboxAdsAPIsOverride,
+         privacy_sandbox::kPrivacySandboxSettings4},
         /*disabled_features=*/
-        {blink::features::kFencedFrames});
+        {blink::features::kFencedFrames,
+         privacy_sandbox::kPrivacySandboxSettings3});
   }
 
   void SetUpOnMainThread() override {
@@ -346,12 +349,12 @@
 
 IN_PROC_BROWSER_TEST_F(InterestGroupPermissionsBrowserTest,
                        ThirdPartyCookiesBlocked) {
-  // With no cookies, API does nothing.
+  // With no 3PC cookies, API still works.
   SetAllowThirdPartyCookies(false);
   ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url()));
 
   ASSERT_TRUE(HasInterestGroupApi(web_contents()));
-  EXPECT_FALSE(CanRunAuction(web_contents()));
+  EXPECT_TRUE(CanRunAuction(web_contents()));
 }
 
 IN_PROC_BROWSER_TEST_F(InterestGroupPermissionsBrowserTest,
@@ -364,6 +367,33 @@
   EXPECT_FALSE(CanRunAuction(web_contents()));
 }
 
+class InterestGroupPermissionsPrivacySandbox3BrowserTest
+    : public InterestGroupPermissionsBrowserTest {
+ public:
+  InterestGroupPermissionsPrivacySandbox3BrowserTest() {
+    scoped_feature_list_.InitWithFeatures(
+        /*enabled_features=*/
+        {blink::features::kInterestGroupStorage,
+         blink::features::kAdInterestGroupAPI, blink::features::kFledge,
+         features::kPrivacySandboxAdsAPIsOverride,
+         privacy_sandbox::kPrivacySandboxSettings3},
+        /*disabled_features=*/
+        {blink::features::kFencedFrames,
+         privacy_sandbox::kPrivacySandboxSettings4});
+  }
+  base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_F(InterestGroupPermissionsPrivacySandbox3BrowserTest,
+                       ThirdPartyCookiesBlocked) {
+  // With no cookies, API does nothing.
+  SetAllowThirdPartyCookies(false);
+  ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_url()));
+
+  ASSERT_TRUE(HasInterestGroupApi(web_contents()));
+  EXPECT_FALSE(CanRunAuction(web_contents()));
+}
+
 class FledgePermissionBrowserTestBaseFeatureDisabled
     : public InterestGroupPermissionsBrowserTest {
  public:
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc
index ddfefc9a..d0a8c6e 100644
--- a/chrome/browser/pdf/pdf_extension_test.cc
+++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -4381,6 +4381,8 @@
   ASSERT_TRUE(link_node);
 
   // Invoke action on a link and wait for navigation to complete.
+  EXPECT_EQ(ax::mojom::DefaultActionVerb::kJump,
+            link_node->GetData().GetDefaultActionVerb());
   content::AccessibilityNotificationWaiter event_waiter(
       GetActiveWebContents(), ui::kAXModeComplete,
       ax::mojom::Event::kLoadComplete);
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
index a670737..774f7b7 100644
--- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
+++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxDialogTest.java
@@ -313,6 +313,7 @@
 
     @Test
     @SmallTest
+    @Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
     public void testControllerShowsBottomSheet() {
         PrivacySandboxDialogController.setShowNewNoticeForTesting(true);
         mFakePrivacySandboxBridge.setRequiredPromptType(PromptType.NOTICE);
diff --git a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java
index 88210d2..dced11e 100644
--- a/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java
+++ b/chrome/browser/privacy_sandbox/android/javatests/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragmentV3Test.java
@@ -76,6 +76,7 @@
 @Batch(Batch.PER_CLASS)
 @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
 @Features.EnableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_3)
+@Features.DisableFeatures(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS_4)
 public final class PrivacySandboxSettingsFragmentV3Test {
     private static final String REFERRER_HISTOGRAM =
             "Settings.PrivacySandbox.PrivacySandboxReferrer";
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
index c34af92..2944e103 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.cc
@@ -312,11 +312,15 @@
     pref_service_->SetBoolean(prefs::kPrivacySandboxM1ConsentDecisionMade,
                               true);
     pref_service_->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
+    RecordUpdatedTopicsConsent(
+        privacy_sandbox::TopicsConsentUpdateSource::kConfirmation, true);
   } else if (PromptAction::kConsentDeclined == action) {
     DCHECK(privacy_sandbox::kPrivacySandboxSettings4ConsentRequired.Get());
     pref_service_->SetBoolean(prefs::kPrivacySandboxM1ConsentDecisionMade,
                               true);
     pref_service_->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, false);
+    RecordUpdatedTopicsConsent(
+        privacy_sandbox::TopicsConsentUpdateSource::kConfirmation, false);
   }
 }
 
@@ -810,7 +814,9 @@
 std::vector<privacy_sandbox::CanonicalTopic>
 PrivacySandboxService::GetCurrentTopTopics() const {
   if (privacy_sandbox::kPrivacySandboxSettings3ShowSampleDataForTesting.Get() ||
-      privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting.Get()) {
+      (pref_service_->GetBoolean(prefs::kPrivacySandboxM1TopicsEnabled) &&
+       privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting
+           .Get())) {
     return {fake_current_topics_.begin(), fake_current_topics_.end()};
   }
 
@@ -955,20 +961,13 @@
   return first_party_sets_policy_service_->IsSiteInManagedSet(site);
 }
 
-void PrivacySandboxService::TopicsConfirmationDecisionMade(
-    bool confirmed) const {
-  RecordUpdatedTopicsConsent(
-      privacy_sandbox::TopicsConsentUpdateSource::kConfirmation, confirmed);
-}
-
 void PrivacySandboxService::TopicsToggleChanged(bool new_value) const {
   RecordUpdatedTopicsConsent(
       privacy_sandbox::TopicsConsentUpdateSource::kSettings, new_value);
 }
 
-void PrivacySandboxService::TopicsConsentRequired() const {
-  // TODO(crbug.com/1332513): Implement + Test.
-  NOTIMPLEMENTED();
+bool PrivacySandboxService::TopicsConsentRequired() const {
+  return privacy_sandbox::kPrivacySandboxSettings4ConsentRequired.Get();
 }
 
 bool PrivacySandboxService::TopicsHasActiveConsent() const {
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
index c38ab39..4f9e642 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service.h
@@ -279,12 +279,6 @@
   virtual bool IsPartOfManagedFirstPartySet(
       const net::SchemefulSite& site) const;
 
-  // Informs the service that a user made a decision during the confirmation
-  // moment, so that the current topics consent information can be updated.
-  // TODO (crbug.com/1378703): Determine if this should just rely on the already
-  // reported prompt actions, and be made protected, or be called separately.
-  void TopicsConfirmationDecisionMade(bool confirmed) const;
-
   // Inform the service that the user changed the Topics toggle in settings,
   // so that the current topics consent information can be updated.
   // TODO (crbug.com/1378703): Determine whether changes to the preference,
@@ -293,7 +287,7 @@
   virtual void TopicsToggleChanged(bool new_value) const;
 
   // Whether the current profile requires consent for Topics to operate.
-  void TopicsConsentRequired() const;
+  bool TopicsConsentRequired() const;
 
   // Whether there is an active consent for Topics currently recorded.
   bool TopicsHasActiveConsent() const;
diff --git a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
index 23a0a54..f3304ee 100644
--- a/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
+++ b/chrome/browser/privacy_sandbox/privacy_sandbox_service_unittest.cc
@@ -96,8 +96,6 @@
 // using enum privacy_sandbox_test_util::InputKey;
 using privacy_sandbox_test_util::InputKey;
 constexpr auto kTopicsToggleNewValue = InputKey::kTopicsToggleNewValue;
-constexpr auto kTopicsConfirmationDecisionConfirmed =
-    InputKey::kTopicsConfirmationDecisionConfirmed;
 constexpr auto kTopFrameOrigin = InputKey::kTopFrameOrigin;
 constexpr auto kAdMeasurementReportingOrigin =
     InputKey::kAdMeasurementReportingOrigin;
@@ -138,9 +136,6 @@
   void TopicsToggleChanged(bool new_value) const override {
     service_->TopicsToggleChanged(new_value);
   }
-  void TopicsConfirmationDecisionMade(bool confirmed) const override {
-    service_->TopicsConfirmationDecisionMade(confirmed);
-  }
   void SetTopicAllowed(privacy_sandbox::CanonicalTopic topic,
                        bool allowed) override {
     service_->SetTopicAllowed(topic, allowed);
@@ -1680,6 +1675,27 @@
   EXPECT_THAT(service->GetBlockedTopics(), testing::IsEmpty());
 }
 
+TEST_F(PrivacySandboxServiceTest, TestNoFakeTopicsPrefOff) {
+  // Sample data won't be returned for current topics when the pref is off, only
+  // the blocked list.
+  prefs()->SetUserPref(prefs::kPrivacySandboxM1TopicsEnabled,
+                       std::make_unique<base::Value>(false));
+
+  feature_list()->InitWithFeaturesAndParameters(
+      {{privacy_sandbox::kPrivacySandboxSettings4,
+        {{privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting
+              .name,
+          "true"}}}},
+      {});
+
+  CanonicalTopic topic3(Topic(3), CanonicalTopic::AVAILABLE_TAXONOMY);
+  CanonicalTopic topic4(Topic(4), CanonicalTopic::AVAILABLE_TAXONOMY);
+
+  auto* service = privacy_sandbox_service();
+  EXPECT_THAT(service->GetCurrentTopTopics(), testing::IsEmpty());
+  EXPECT_THAT(service->GetBlockedTopics(), ElementsAre(topic3, topic4));
+}
+
 TEST_F(PrivacySandboxServiceTest, TestFakeTopics) {
   std::vector<base::test::FeatureRefAndParams> test_features = {
       {privacy_sandbox::kPrivacySandboxSettings3,
@@ -1689,6 +1705,10 @@
        {{privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting.name,
          "true"}}}};
 
+  // Sample data for current topics is only returned when the pref is on.
+  prefs()->SetUserPref(prefs::kPrivacySandboxM1TopicsEnabled,
+                       std::make_unique<base::Value>(true));
+
   for (const auto& feature : test_features) {
     feature_list()->Reset();
     feature_list()->InitWithFeaturesAndParameters({feature}, {});
@@ -3260,40 +3280,6 @@
       });
 }
 
-TEST_F(PrivacySandboxServiceM1Test, TopicsConsentConfirmation_Accepted) {
-  RunTestCase(
-      TestState{{kActiveTopicsConsent, false},
-                {kAdvanceClockBy, base::Hours(1)}},
-      TestInput{
-          {kTopicsConfirmationDecisionConfirmed, true},
-      },
-      TestOutput{
-          {kTopicsConsentGiven, true},
-          {kTopicsConsentLastUpdateReason,
-           privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
-          {kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
-          {kTopicsConsentStringIdentifiers,
-           GetTopicsConfirmationStringIdentifiers()},
-      });
-}
-
-TEST_F(PrivacySandboxServiceM1Test, TopicsConsentConfirmation_Declined) {
-  RunTestCase(
-      TestState{{kActiveTopicsConsent, true},
-                {kAdvanceClockBy, base::Hours(1)}},
-      TestInput{
-          {kTopicsConfirmationDecisionConfirmed, true},
-      },
-      TestOutput{
-          {kTopicsConsentGiven, true},
-          {kTopicsConsentLastUpdateReason,
-           privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
-          {kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
-          {kTopicsConsentStringIdentifiers,
-           GetTopicsConfirmationStringIdentifiers()},
-      });
-}
-
 TEST_F(PrivacySandboxServiceM1Test,
        RecordPrivacySandbox4StartupMetrics_PromptSuppressed_Explicitly) {
   base::HistogramTester histogram_tester;
@@ -3706,21 +3692,39 @@
 TEST_F(PrivacySandboxServiceM1ConsentPromptTest, PromptAction_ConsentAccepted) {
   // Confirm that when the service is informed that the consent prompt was
   // accepted, it correctly adjusts the Privacy Sandbox prefs.
-  RunTestCase(TestState{},
-              TestInput{{InputKey::kPromptAction,
-                         static_cast<int>(PromptAction::kConsentAccepted)}},
-              TestOutput{{OutputKey::kM1ConsentDecisionMade, true},
-                         {OutputKey::kM1TopicsEnabled, true}});
+  RunTestCase(
+      TestState{{kActiveTopicsConsent, false},
+                {kAdvanceClockBy, base::Hours(1)}},
+      TestInput{{InputKey::kPromptAction,
+                 static_cast<int>(PromptAction::kConsentAccepted)}},
+      TestOutput{
+          {OutputKey::kM1ConsentDecisionMade, true},
+          {OutputKey::kM1TopicsEnabled, true},
+          {OutputKey::kTopicsConsentGiven, true},
+          {OutputKey::kTopicsConsentLastUpdateReason,
+           privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
+          {kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
+          {kTopicsConsentStringIdentifiers,
+           GetTopicsConfirmationStringIdentifiers()}});
 }
 
 TEST_F(PrivacySandboxServiceM1ConsentPromptTest, PromptAction_ConsentDeclined) {
   // Confirm that when the service is informed that the consent prompt was
   // declined, it correctly adjusts the Privacy Sandbox prefs.
-  RunTestCase(TestState{},
-              TestInput{{InputKey::kPromptAction,
-                         static_cast<int>(PromptAction::kConsentDeclined)}},
-              TestOutput{{OutputKey::kM1ConsentDecisionMade, true},
-                         {OutputKey::kM1TopicsEnabled, false}});
+  RunTestCase(
+      TestState{{kActiveTopicsConsent, true},
+                {kAdvanceClockBy, base::Hours(1)}},
+      TestInput{{InputKey::kPromptAction,
+                 static_cast<int>(PromptAction::kConsentDeclined)}},
+      TestOutput{
+          {OutputKey::kM1ConsentDecisionMade, true},
+          {OutputKey::kM1TopicsEnabled, false},
+          {OutputKey::kTopicsConsentGiven, false},
+          {OutputKey::kTopicsConsentLastUpdateReason,
+           privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
+          {kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
+          {kTopicsConsentStringIdentifiers,
+           GetTopicsConfirmationStringIdentifiers()}});
 }
 
 TEST_F(PrivacySandboxServiceM1ConsentPromptTest,
@@ -3734,13 +3738,17 @@
               TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
                          {OutputKey::kM1FledgeEnabled, true},
                          {OutputKey::kM1AdMeasurementEnabled, true}});
-  RunTestCase(TestState{{StateKey::kM1ConsentDecisionMade, true},
-                        {StateKey::kM1EEANoticeAcknowledged, false}},
-              TestInput{{InputKey::kPromptAction,
-                         static_cast<int>(PromptAction::kNoticeOpenSettings)}},
-              TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
-                         {OutputKey::kM1FledgeEnabled, true},
-                         {OutputKey::kM1AdMeasurementEnabled, true}});
+  RunTestCase(
+      TestState{{StateKey::kM1ConsentDecisionMade, true},
+                {StateKey::kM1EEANoticeAcknowledged, false}},
+      TestInput{{InputKey::kPromptAction,
+                 static_cast<int>(PromptAction::kNoticeOpenSettings)}},
+      TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
+                 {OutputKey::kM1FledgeEnabled, true},
+                 {OutputKey::kM1AdMeasurementEnabled, true},
+                 {OutputKey::kTopicsConsentGiven, false},
+                 {OutputKey::kTopicsConsentLastUpdateReason,
+                  privacy_sandbox::TopicsConsentUpdateSource::kDefaultValue}});
 }
 
 class PrivacySandboxServiceM1NoticePromptTest
@@ -3852,7 +3860,8 @@
               TestOutput{{OutputKey::kM1RowNoticeAcknowledged, true},
                          {OutputKey::kM1TopicsEnabled, true},
                          {OutputKey::kM1FledgeEnabled, true},
-                         {OutputKey::kM1AdMeasurementEnabled, true}});
+                         {OutputKey::kM1AdMeasurementEnabled, true},
+                         {OutputKey::kTopicsConsentGiven, false}});
 }
 
 TEST_F(PrivacySandboxServiceM1NoticePromptTest, PromptAction_OpenSettings) {
@@ -3864,7 +3873,8 @@
               TestOutput{{OutputKey::kM1RowNoticeAcknowledged, true},
                          {OutputKey::kM1TopicsEnabled, true},
                          {OutputKey::kM1FledgeEnabled, true},
-                         {OutputKey::kM1AdMeasurementEnabled, true}});
+                         {OutputKey::kM1AdMeasurementEnabled, true},
+                         {OutputKey::kTopicsConsentGiven, false}});
 }
 
 TEST_F(PrivacySandboxServiceM1Test, DisablePrivacySandboxPromptPolicy) {
diff --git a/chrome/browser/resources/browsing_topics/browsing_topics_internals.css b/chrome/browser/resources/browsing_topics/browsing_topics_internals.css
index 60ccee2..1f0af5e 100644
--- a/chrome/browser/resources/browsing_topics/browsing_topics_internals.css
+++ b/chrome/browser/resources/browsing_topics/browsing_topics_internals.css
@@ -130,7 +130,8 @@
 .hosts-classification-result-div,
 .hosts-classification-input-validation-error-div,
 .features-and-parameters-div,
-.classification-input-div {
+.classification-input-div,
+.consent-info-div {
   font-size: 1rem;
   line-height: 1.5;
   padding: 10px;
@@ -182,3 +183,7 @@
   padding-inline-start: 5px;
   white-space: nowrap;
 }
+
+#consent-info:not(:target) {
+  display: none;
+}
diff --git a/chrome/browser/resources/browsing_topics/browsing_topics_internals.html b/chrome/browser/resources/browsing_topics/browsing_topics_internals.html
index 7e63bb63..6e2cce4 100644
--- a/chrome/browser/resources/browsing_topics/browsing_topics_internals.html
+++ b/chrome/browser/resources/browsing_topics/browsing_topics_internals.html
@@ -25,6 +25,7 @@
   <div slot="tab">Topics State</div>
   <div slot="tab">Classifier</div>
   <div slot="tab">Features and Parameters</div>
+  <div slot="tab" id="consent-info">Consent Info</div>
   <div id="topics-state-slot" slot="panel" class="panel">
     <div class="refresh-state-buttons-div">
       <button type="button" id="refresh-topics-state-button" class="refresh-state-button">Refresh</button>
@@ -82,6 +83,14 @@
       <div id="taxonomy-version-div">BrowsingTopics:taxonomy_version: </div>
     </div>
   </div>
+  <div id="consent-info-slot" slot="panel" class="panel">
+    <div class="consent-info-div">
+      <div>$i18n{topicsConsentStatusLabel} $i18n{topicsConsentStatus}</div>
+      <div>$i18n{topicsConsentSourceLabel} $i18n{topicsConsentSource}</div>
+      <div>$i18n{topicsConsentTimeLabel} $i18n{topicsConsentTime}</div>
+      <div>$i18n{topicsConsentTextLabel} $i18n{topicsConsentText}</div>
+    </div>
+  </div>
 </cr-tab-box>
 
 <template id="classification-result-host-row-template">
diff --git a/chrome/browser/signin/google_accounts_private_api_host.cc b/chrome/browser/signin/google_accounts_private_api_host.cc
index 3365b5f..226a9129 100644
--- a/chrome/browser/signin/google_accounts_private_api_host.cc
+++ b/chrome/browser/signin/google_accounts_private_api_host.cc
@@ -7,10 +7,15 @@
 #include "chrome/browser/signin/google_accounts_private_api_util.h"
 #include "content/public/browser/document_user_data.h"
 #include "content/public/browser/navigation_handle.h"
+#include "content/public/browser/render_frame_host.h"
 
 GoogleAccountsPrivateApiHost::GoogleAccountsPrivateApiHost(
-    content::RenderFrameHost* rfh)
-    : DocumentUserData<GoogleAccountsPrivateApiHost>(rfh), receiver_(this) {}
+    content::RenderFrameHost* rfh,
+    base::RepeatingCallback<void(const std::string&)>
+        on_consent_result_callback)
+    : DocumentUserData<GoogleAccountsPrivateApiHost>(rfh),
+      receiver_(this),
+      on_consent_result_callback_(std::move(on_consent_result_callback)) {}
 
 GoogleAccountsPrivateApiHost::~GoogleAccountsPrivateApiHost() = default;
 
@@ -24,8 +29,14 @@
 
 void GoogleAccountsPrivateApiHost::SetConsentResult(
     const std::string& consent_result) {
-  // To be implemented.
-  // TODO: Add a check for non-primary pages.
+#if !BUILDFLAG(IS_ANDROID)
+  if (!render_frame_host().IsInPrimaryMainFrame() ||
+      !on_consent_result_callback_) {
+    return;
+  }
+
+  on_consent_result_callback_.Run(consent_result);
+#endif  // !BUILDFLAG(IS_ANDROID)
 }
 
 // static
@@ -44,6 +55,8 @@
 
 // static
 void GoogleAccountsPrivateApiHost::CreateReceiver(
+    base::RepeatingCallback<void(const std::string&)>
+        on_consent_result_callback,
     content::NavigationHandle* navigation_handle) {
   if (navigation_handle->IsSameDocument()) {
     return;
@@ -51,6 +64,7 @@
 
   if (ShouldExposeGoogleAccountsPrivateApi(navigation_handle)) {
     GoogleAccountsPrivateApiHost::CreateForCurrentDocument(
-        navigation_handle->GetRenderFrameHost());
+        navigation_handle->GetRenderFrameHost(),
+        std::move(on_consent_result_callback));
   }
 }
diff --git a/chrome/browser/signin/google_accounts_private_api_host.h b/chrome/browser/signin/google_accounts_private_api_host.h
index 72808ab8..9851e7a 100644
--- a/chrome/browser/signin/google_accounts_private_api_host.h
+++ b/chrome/browser/signin/google_accounts_private_api_host.h
@@ -7,6 +7,7 @@
 
 #include <string>
 
+#include "base/functional/callback.h"
 #include "chrome/common/google_accounts_private_api_extension.mojom.h"
 #include "content/public/browser/document_user_data.h"
 #include "mojo/public/cpp/bindings/associated_receiver.h"
@@ -27,7 +28,9 @@
   GoogleAccountsPrivateApiHost& operator=(const GoogleAccountsPrivateApiHost&) =
       delete;
 
-  static void CreateReceiver(content::NavigationHandle* navigation_handle);
+  static void CreateReceiver(base::RepeatingCallback<void(const std::string&)>
+                                 on_consent_result_callback,
+                             content::NavigationHandle* navigation_handle);
   static void BindHost(
       mojo::PendingAssociatedReceiver<
           chrome::mojom::GoogleAccountsPrivateApiExtension> receiver,
@@ -40,13 +43,18 @@
   void SetConsentResult(const std::string& consent_result) override;
 
  private:
-  explicit GoogleAccountsPrivateApiHost(content::RenderFrameHost* rfh);
+  explicit GoogleAccountsPrivateApiHost(
+      content::RenderFrameHost* rfh,
+      base::RepeatingCallback<void(const std::string&)>
+          on_consent_result_callback);
 
   friend DocumentUserData;
   DOCUMENT_USER_DATA_KEY_DECL();
 
   mojo::AssociatedReceiver<chrome::mojom::GoogleAccountsPrivateApiExtension>
       receiver_;
+
+  base::RepeatingCallback<void(const std::string&)> on_consent_result_callback_;
 };
 
 #endif  // CHROME_BROWSER_SIGNIN_GOOGLE_ACCOUNTS_PRIVATE_API_HOST_H_
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc
index 0409bf0..809410c3c 100644
--- a/chrome/browser/spellchecker/spellcheck_service.cc
+++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -38,6 +38,8 @@
 #include "components/user_prefs/user_prefs.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/browser_thread.h"
+#include "content/public/browser/notification_service.h"
+#include "content/public/browser/notification_types.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/storage_partition.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -156,6 +158,9 @@
   custom_dictionary_->AddObserver(this);
   custom_dictionary_->Load();
 
+  registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CREATED,
+                 content::NotificationService::AllSources());
+
 #if BUILDFLAG(IS_WIN)
   if (spellcheck::UseBrowserSpellChecker() &&
       base::FeatureList::IsEnabled(
@@ -515,9 +520,11 @@
          (!hunspell_dictionaries_.empty() || enable_if_uninitialized);
 }
 
-void SpellcheckService::OnRenderProcessHostCreated(
-    content::RenderProcessHost* host) {
-  InitForRenderer(host);
+void SpellcheckService::Observe(int type,
+                                const content::NotificationSource& source,
+                                const content::NotificationDetails& details) {
+  DCHECK_EQ(content::NOTIFICATION_RENDERER_PROCESS_CREATED, type);
+  InitForRenderer(content::Source<content::RenderProcessHost>(source).ptr());
 }
 
 void SpellcheckService::OnCustomDictionaryLoaded() {
diff --git a/chrome/browser/spellchecker/spellcheck_service.h b/chrome/browser/spellchecker/spellcheck_service.h
index 00e613b..17b0aae 100644
--- a/chrome/browser/spellchecker/spellcheck_service.h
+++ b/chrome/browser/spellchecker/spellcheck_service.h
@@ -24,7 +24,8 @@
 #include "components/spellcheck/browser/platform_spell_checker.h"
 #include "components/spellcheck/common/spellcheck.mojom-forward.h"
 #include "components/spellcheck/spellcheck_buildflags.h"
-#include "content/public/browser/render_process_host_creation_observer.h"
+#include "content/public/browser/notification_observer.h"
+#include "content/public/browser/notification_registrar.h"
 #include "mojo/public/cpp/bindings/remote.h"
 
 class SpellCheckHostMetrics;
@@ -35,6 +36,8 @@
 
 namespace content {
 class BrowserContext;
+class NotificationDetails;
+class NotificationSource;
 class RenderProcessHost;
 }
 
@@ -48,7 +51,7 @@
 // profile and each is created by the SpellCheckServiceFactory.  The
 // SpellcheckService maintains any per-profile information about spellcheck.
 class SpellcheckService : public KeyedService,
-                          public content::RenderProcessHostCreationObserver,
+                          public content::NotificationObserver,
                           public SpellcheckCustomDictionary::Observer,
                           public SpellcheckHunspellDictionary::Observer {
  public:
@@ -135,8 +138,10 @@
   // dictionaries available.
   bool IsSpellcheckEnabled() const;
 
-  // content::RenderProcessHostCreationObserver implementation.
-  void OnRenderProcessHostCreated(content::RenderProcessHost* host) override;
+  // NotificationProfile implementation.
+  void Observe(int type,
+               const content::NotificationSource& source,
+               const content::NotificationDetails& details) override;
 
   // SpellcheckCustomDictionary::Observer implementation.
   void OnCustomDictionaryLoaded() override;
@@ -295,6 +300,7 @@
   std::unique_ptr<PlatformSpellChecker> platform_spell_checker_;
 
   PrefChangeRegistrar pref_change_registrar_;
+  content::NotificationRegistrar registrar_;
 
   // A pointer to the BrowserContext which this service refers to.
   raw_ptr<content::BrowserContext> context_;
diff --git a/chrome/browser/storage/shared_storage_browsertest.cc b/chrome/browser/storage/shared_storage_browsertest.cc
index 56087aa..addd9667 100644
--- a/chrome/browser/storage/shared_storage_browsertest.cc
+++ b/chrome/browser/storage/shared_storage_browsertest.cc
@@ -204,11 +204,12 @@
   SharedStorageChromeBrowserTest() {
     base::test::TaskEnvironment task_environment;
 
+    // TODO(crbug.com/1378703): Update the tests to support Privacy Sandbox 4.
     scoped_feature_list_.InitWithFeatures(
         /*enabled_features=*/{blink::features::kSharedStorageAPI,
                               privacy_sandbox::kPrivacySandboxSettings3,
                               features::kPrivacySandboxAdsAPIsOverride},
-        /*disabled_features=*/{});
+        /*disabled_features=*/{privacy_sandbox::kPrivacySandboxSettings4});
   }
 
   void SetUpOnMainThread() override {
diff --git a/chrome/browser/sync/test/integration/sync_test.h b/chrome/browser/sync/test/integration/sync_test.h
index 2cd0dde..e7a26a7 100644
--- a/chrome/browser/sync/test/integration/sync_test.h
+++ b/chrome/browser/sync/test/integration/sync_test.h
@@ -404,7 +404,7 @@
   // directory. Profiles are owned by the ProfileManager.
   // TODO(crbug.com/1349349): store |profiles_|, |browsers_| and |clients_| in
   // one structure.
-  std::vector<raw_ptr<Profile>> profiles_;
+  std::vector<raw_ptr<Profile, DanglingUntriaged>> profiles_;
 
   // List of temporary directories that need to be deleted when the test is
   // completed, used for two-client tests with external server.
@@ -415,7 +415,7 @@
   // instance is created for each sync profile. Browser object lifetime is
   // managed by BrowserList, so we don't use a std::vector<std::unique_ptr<>>
   // here.
-  std::vector<raw_ptr<Browser>> browsers_;
+  std::vector<raw_ptr<Browser, DanglingUntriaged>> browsers_;
 
   class ClosedBrowserObserver;
   std::unique_ptr<ClosedBrowserObserver> browser_list_observer_;
@@ -438,7 +438,8 @@
 
   // Used to deliver invalidations to different profiles within
   // FakeSyncServerInvalidationSender.
-  std::map<raw_ptr<Profile>, raw_ptr<FakeSyncGCMDriver>>
+  std::map<raw_ptr<Profile, DanglingUntriaged>,
+           raw_ptr<FakeSyncGCMDriver, DanglingUntriaged>>
       profile_to_fake_gcm_driver_;
 
   base::CallbackListSubscription create_services_subscription_;
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
index 1724fb3..7069a2ea 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/CriticalPersistedTabData.java
@@ -346,6 +346,8 @@
                 return TabLaunchType.FROM_START_SURFACE;
             case LaunchTypeAtCreation.FROM_TAB_GROUP_UI:
                 return TabLaunchType.FROM_TAB_GROUP_UI;
+            case LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI:
+                return TabLaunchType.FROM_TAB_SWITCHER_UI;
             case LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
                 return TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
             case LaunchTypeAtCreation.FROM_APP_WIDGET:
@@ -402,6 +404,8 @@
                 return LaunchTypeAtCreation.FROM_START_SURFACE;
             case TabLaunchType.FROM_TAB_GROUP_UI:
                 return LaunchTypeAtCreation.FROM_TAB_GROUP_UI;
+            case TabLaunchType.FROM_TAB_SWITCHER_UI:
+                return LaunchTypeAtCreation.FROM_TAB_SWITCHER_UI;
             case TabLaunchType.FROM_LONGPRESS_BACKGROUND_IN_GROUP:
                 return LaunchTypeAtCreation.FROM_LONGPRESS_BACKGROUND_IN_GROUP;
             case TabLaunchType.FROM_APP_WIDGET:
diff --git a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
index 0f68c654..fb23deeb 100644
--- a/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
+++ b/chrome/browser/tab/java/src/org/chromium/chrome/browser/tab/state/flatbuffer/critical_persisted_tab_data.fbs
@@ -36,6 +36,7 @@
     FROM_LONGPRESS_INCOGNITO = 16,
     FROM_RECENT_TABS = 17,
     FROM_READING_LIST = 18,
+    FROM_TAB_SWITCHER_UI = 19,
     // Add new values here and don't change existing values
     // as they are persisted across restarts. Changing existing
     // values will lead to backwards compatibility issues crbug.com/1286984.
diff --git a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java
index 7564b3e..e17b1c8e 100644
--- a/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java
+++ b/chrome/browser/tab_group/java/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilter.java
@@ -309,6 +309,8 @@
         int destinationGroupId = getRootId(destinationTab);
         List<Tab> tabsToMerge = getRelatedTabList(sourceTabId);
         int destinationIndexInTabModel = getTabModelDestinationIndex(destinationTab);
+        List<Integer> originalIndexes = new ArrayList<>();
+        List<Integer> originalRootIds = new ArrayList<>();
 
         if (skipUpdateTabModel || !needToUpdateTabModel(tabsToMerge, destinationIndexInTabModel)) {
             for (Observer observer : mGroupFilterObserver) {
@@ -316,7 +318,13 @@
                         tabsToMerge.get(tabsToMerge.size() - 1), destinationGroupId);
             }
             for (int i = 0; i < tabsToMerge.size(); i++) {
-                setRootId(tabsToMerge.get(i), destinationGroupId);
+                Tab tab = tabsToMerge.get(i);
+                int index = TabModelUtils.getTabIndexById(getTabModel(), tab.getId());
+                assert index != TabModel.INVALID_TAB_INDEX;
+
+                originalIndexes.add(index);
+                originalRootIds.add(getRootId(tab));
+                setRootId(tab, destinationGroupId);
             }
             resetFilterState();
 
@@ -325,12 +333,11 @@
             for (Observer observer : mGroupFilterObserver) {
                 observer.didMergeTabToGroup(
                         tabsToMerge.get(tabsToMerge.size() - 1), group.getLastShownTabId());
+                observer.didCreateGroup(tabsToMerge, originalIndexes, originalRootIds);
             }
         } else {
-            mergeListOfTabsToGroup(tabsToMerge, destinationTab, true, false);
+            mergeListOfTabsToGroup(tabsToMerge, destinationTab, true, true);
         }
-        // TODO(978508): Send didCreateGroup signal to activate the
-        // {@link UndoGroupSnackbarController}.
     }
 
     /**
diff --git a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java b/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java
index 4f37b28..0bc1dce 100644
--- a/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java
+++ b/chrome/browser/tab_group/junit/src/org/chromium/chrome/browser/tasks/tab_groups/TabGroupModelFilterUnitTest.java
@@ -199,7 +199,7 @@
         mTabModel.addTab(
                 tab, index, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                tab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                tab, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
         return tab;
     }
 
@@ -213,37 +213,37 @@
         mTabModel.addTab(
                 mTab1, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         doReturn(isIncognito).when(mTab2).isIncognito();
         mTabModel.addTab(
                 mTab2, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab2, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab2, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         doReturn(isIncognito).when(mTab3).isIncognito();
         mTabModel.addTab(
                 mTab3, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab3, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab3, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         doReturn(isIncognito).when(mTab4).isIncognito();
         mTabModel.addTab(
                 mTab4, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab4, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab4, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         doReturn(isIncognito).when(mTab5).isIncognito();
         mTabModel.addTab(
                 mTab5, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab5, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab5, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         doReturn(isIncognito).when(mTab6).isIncognito();
         mTabModel.addTab(
                 mTab6, -1, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
         mTabModelObserverCaptor.getValue().didAddTab(
-                mTab6, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND);
+                mTab6, TabLaunchType.FROM_CHROME_UI, TabCreationState.LIVE_IN_FOREGROUND, false);
 
         if (isTabRestoreCompleted) {
             mTabGroupModelFilter.restoreCompleted();
@@ -1194,4 +1194,67 @@
         int totalTabCount = mTabGroupModelFilter.getTotalTabCount();
         assertThat("Should have 6 total tabs", totalTabCount, equalTo(6));
     }
+
+    @Test
+    public void mergeGroupToGroupNonAdjacent_notifyFilterObserver() {
+        // Non adjacent group merges affect the indices, so the expectedGroup reflects that.
+        List<Tab> expectedGroup = new ArrayList<>(Arrays.asList(mTab5, mTab6, mTab2, mTab3));
+        List<Tab> expectedSourceTabs = mTabGroupModelFilter.getRelatedTabList(mTab2.getId());
+        List<Integer> originalIndexes = new ArrayList<>();
+        List<Integer> originalRootIds = new ArrayList<>();
+
+        for (Tab tab : expectedSourceTabs) {
+            // Use tab2 initial index for both related tabs index as the logic moves tab2 after
+            // saving its index but before retrieving index for related tab3.
+            originalIndexes.add(TabModelUtils.getTabIndexById(
+                    mTabGroupModelFilter.getTabModel(), mTab2.getId()));
+            originalRootIds.add(mTabGroupModelFilter.getRootId(tab));
+        }
+
+        mTabGroupModelFilter.mergeTabsToGroup(mTab2.getId(), mTab5.getId(), false);
+        verify(mTabGroupModelFilterObserver)
+                .didCreateGroup(expectedSourceTabs, originalIndexes, originalRootIds);
+        assertArrayEquals(mTabGroupModelFilter.getRelatedTabList(mTab2.getId()).toArray(),
+                expectedGroup.toArray());
+    }
+
+    @Test
+    public void mergeGroupToTabAdjacent_notifyFilterObserver() {
+        List<Tab> expectedGroup = new ArrayList<>(Arrays.asList(mTab2, mTab3, mTab4));
+        List<Tab> expectedSourceTabs = mTabGroupModelFilter.getRelatedTabList(mTab3.getId());
+        List<Integer> originalIndexes = new ArrayList<>();
+        List<Integer> originalRootIds = new ArrayList<>();
+
+        for (Tab tab : expectedSourceTabs) {
+            originalIndexes.add(
+                    TabModelUtils.getTabIndexById(mTabGroupModelFilter.getTabModel(), tab.getId()));
+            originalRootIds.add(mTabGroupModelFilter.getRootId(tab));
+        }
+
+        mTabGroupModelFilter.mergeTabsToGroup(mTab3.getId(), mTab4.getId(), true);
+        verify(mTabGroupModelFilterObserver)
+                .didCreateGroup(expectedSourceTabs, originalIndexes, originalRootIds);
+        assertArrayEquals(mTabGroupModelFilter.getRelatedTabList(mTab2.getId()).toArray(),
+                expectedGroup.toArray());
+    }
+
+    @Test
+    public void mergeTabToTab_notifyFilterObserver() {
+        List<Tab> expectedGroup = new ArrayList<>(Arrays.asList(mTab1, mTab4));
+        List<Tab> expectedSourceTabs = mTabGroupModelFilter.getRelatedTabList(mTab1.getId());
+        List<Integer> originalIndexes = new ArrayList<>();
+        List<Integer> originalRootIds = new ArrayList<>();
+
+        for (Tab tab : expectedSourceTabs) {
+            originalIndexes.add(
+                    TabModelUtils.getTabIndexById(mTabGroupModelFilter.getTabModel(), tab.getId()));
+            originalRootIds.add(mTabGroupModelFilter.getRootId(tab));
+        }
+
+        mTabGroupModelFilter.mergeTabsToGroup(mTab1.getId(), mTab4.getId(), true);
+        verify(mTabGroupModelFilterObserver)
+                .didCreateGroup(expectedSourceTabs, originalIndexes, originalRootIds);
+        assertArrayEquals(mTabGroupModelFilter.getRelatedTabList(mTab1.getId()).toArray(),
+                expectedGroup.toArray());
+    }
 }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
index 71e6f2a..d66ed8a 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabCreator.java
@@ -104,9 +104,16 @@
      * Creates a new tab and loads the NTP.
      */
     public final void launchNTP() {
+        launchNTP(TabLaunchType.FROM_CHROME_UI);
+    }
+
+    /**
+     * Creates a new tab and loads the NTP.
+     */
+    public final void launchNTP(@TabLaunchType int type) {
         try {
             TraceEvent.begin("TabCreator.launchNTP");
-            launchUrl(UrlConstants.NTP_URL, TabLaunchType.FROM_CHROME_UI);
+            launchUrl(UrlConstants.NTP_URL, type);
         } finally {
             TraceEvent.end("TabCreator.launchNTP");
         }
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
index 2327fa3..f748b753 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelFilter.java
@@ -274,10 +274,11 @@
     }
 
     @Override
-    public void didAddTab(Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+    public void didAddTab(Tab tab, @TabLaunchType int type, @TabCreationState int creationState,
+            boolean markedForSelection) {
         addTab(tab);
         for (TabModelObserver observer : mFilteredObservers) {
-            observer.didAddTab(tab, type, creationState);
+            observer.didAddTab(tab, type, creationState, markedForSelection);
         }
     }
 
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java
index 06f7f20..5b62f77 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelObserver.java
@@ -68,8 +68,10 @@
      * @param tab The newly added tab.
      * @param type The type of tab launch.
      * @param creationState How the tab was created.
+     * @param markedForSelection Indicates whether the added tab will be selected.
      */
-    default void didAddTab(Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {}
+    default void didAddTab(Tab tab, @TabLaunchType int type, @TabCreationState int creationState,
+            boolean markedForSelection) {}
 
     /**
      * Called after a tab has been moved from one position in the {@link TabModel} to another.
diff --git a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabRegistrationObserver.java b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabRegistrationObserver.java
index ae1b979..c745a63 100644
--- a/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabRegistrationObserver.java
+++ b/chrome/browser/tabmodel/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorTabRegistrationObserver.java
@@ -55,8 +55,8 @@
     public TabModelSelectorTabRegistrationObserver(TabModelSelector selector) {
         mTabModelObserver = new TabModelSelectorTabModelObserver(selector) {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 // This observer is automatically removed by tab when it is destroyed.
                 onTabRegistered(tab);
             }
diff --git a/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc b/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc
index a7501f9..8966346 100644
--- a/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc
+++ b/chrome/browser/top_level_storage_access_api/request_storage_access_for_origin_browsertest.cc
@@ -56,7 +56,8 @@
 constexpr char kHostC[] = "c.test";
 constexpr char kHostD[] = "d.test";
 
-constexpr char kRequestOutcomeHistogram[] = "API.StorageAccess.RequestOutcome";
+constexpr char kRequestOutcomeHistogram[] =
+    "API.TopLevelStorageAccess.RequestOutcome";
 
 class RequestStorageAccessForOriginBaseBrowserTest
     : public InProcessBrowserTest {
diff --git a/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context.cc b/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context.cc
index ec51c4c..2aea06bb 100644
--- a/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context.cc
+++ b/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context.cc
@@ -40,9 +40,9 @@
 
 constexpr base::TimeDelta kGrantDuration = base::Hours(24);
 
-// TODO(crbug.com/1385156): Switch to non-StorageAccessAPI metrics.
 void RecordOutcomeSample(CookieRequestOutcome outcome) {
-  base::UmaHistogramEnumeration("API.StorageAccess.RequestOutcome", outcome);
+  base::UmaHistogramEnumeration("API.TopLevelStorageAccess.RequestOutcome",
+                                outcome);
 }
 
 }  // namespace
@@ -198,9 +198,6 @@
     return;
   }
 
-  // TODO(crbug.com/1385156): Switch to non-StorageAccessAPI metrics.
-  base::UmaHistogramBoolean("API.StorageAccess.GrantIsImplicit", true);
-
   HostContentSettingsMap* settings_map =
       HostContentSettingsMapFactory::GetForProfile(browser_context());
   DCHECK(settings_map);
diff --git a/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc b/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc
index 128b7ef..5fcf066a 100644
--- a/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc
+++ b/chrome/browser/top_level_storage_access_api/top_level_storage_access_permission_context_unittest.cc
@@ -30,9 +30,8 @@
 
 namespace {
 
-constexpr char kGrantIsImplicitHistogram[] =
-    "API.StorageAccess.GrantIsImplicit";
-constexpr char kRequestOutcomeHistogram[] = "API.StorageAccess.RequestOutcome";
+constexpr char kRequestOutcomeHistogram[] =
+    "API.TopLevelStorageAccess.RequestOutcome";
 
 GURL GetTopLevelURL() {
   return GURL("https://embedder.example.com");
@@ -232,9 +231,6 @@
                 kRequestOutcomeHistogram,
                 CookieRequestOutcome::kGrantedByFirstPartySet),
             1);
-  histogram_tester().ExpectTotalCount(kGrantIsImplicitHistogram, 1);
-  histogram_tester().ExpectBucketCount(kGrantIsImplicitHistogram,
-                                       /*sample=*/true, 1);
 
   // Check the `SessionModel::NonRestorableUserSession` settings granted by FPS.
   settings_map->GetSettingsForOneType(
diff --git a/chrome/browser/ui/android/tab_model/tab_model.h b/chrome/browser/ui/android/tab_model/tab_model.h
index 7fe0fff..3df944f 100644
--- a/chrome/browser/ui/android/tab_model/tab_model.h
+++ b/chrome/browser/ui/android/tab_model/tab_model.h
@@ -106,6 +106,8 @@
     // Opened from a Reading list. When going "back" on Android, the Reading
     // list should be reopened.
     FROM_READING_LIST,
+    // Opened from Tab Switcher UI.
+    FROM_TAB_SWITCHER_UI,
     // Must be last.
     SIZE
   };
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
index 92b737a..64ce0b95 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProvider.java
@@ -101,8 +101,8 @@
 
         mTabModelFilterObserver = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 updateTabCount();
             }
 
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProviderUnitTest.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProviderUnitTest.java
index a34f371..c346d89 100644
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProviderUnitTest.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/TabCountProviderUnitTest.java
@@ -104,7 +104,7 @@
 
         int tabCount1 = 10;
         when(mMockTabModelFilter.getTotalTabCount()).thenReturn(tabCount1);
-        observer.didAddTab(null, 0, 0);
+        observer.didAddTab(null, 0, 0, false);
         assertEquals("Tab count from provider is not same as expected", tabCount1,
                 mProvider.getTabCount());
 
diff --git a/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc b/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc
index eefd88d..9d4869b 100644
--- a/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/commerce/price_tracking_icon_view_interactive_uitest.cc
@@ -148,7 +148,8 @@
 
  protected:
   base::UserActionTester user_action_tester_;
-  raw_ptr<commerce::MockShoppingService> mock_shopping_service_;
+  raw_ptr<commerce::MockShoppingService, DanglingUntriaged>
+      mock_shopping_service_;
   raw_ptr<MockShoppingListUiTabHelper, DanglingUntriaged> mock_tab_helper_;
 
  private:
diff --git a/chrome/browser/ui/views/extensions/device_chooser_extension_browsertest.cc b/chrome/browser/ui/views/extensions/device_chooser_extension_browsertest.cc
index f68cdbd..ea6559a9 100644
--- a/chrome/browser/ui/views/extensions/device_chooser_extension_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/device_chooser_extension_browsertest.cc
@@ -133,7 +133,7 @@
   }
 
  private:
-  raw_ptr<const extensions::Extension> extension_ = nullptr;
+  raw_ptr<const extensions::Extension, DanglingUntriaged> extension_ = nullptr;
 };
 
 IN_PROC_BROWSER_TEST_P(DeviceChooserExtensionBrowserTest,
diff --git a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc
index b594314..4869986 100644
--- a/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc
+++ b/chrome/browser/ui/views/frame/picture_in_picture_browser_frame_view_interactive_uitest.cc
@@ -84,7 +84,8 @@
 
  private:
   base::test::ScopedFeatureList scoped_feature_list_;
-  raw_ptr<PictureInPictureBrowserFrameView> pip_frame_view_ = nullptr;
+  raw_ptr<PictureInPictureBrowserFrameView, DanglingUntriaged> pip_frame_view_ =
+      nullptr;
 };
 
 #if BUILDFLAG(IS_WIN)
diff --git a/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc b/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc
index cddab7e..e6b5c2d 100644
--- a/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc
+++ b/chrome/browser/ui/views/page_info/page_info_bubble_view_dialog_browsertest.cc
@@ -560,14 +560,17 @@
 }
 
 class PageInfoBubbleViewPrivacySandboxDialogBrowserTest
-    : public DialogBrowserTest {
+    : public DialogBrowserTest,
+      public testing::WithParamInterface<bool> {
  public:
   PageInfoBubbleViewPrivacySandboxDialogBrowserTest() {
     // TODO(crbug.com/1344787): Clean up when PageSpecificSiteDataDialog is
     // launched.
-    feature_list_.InitWithFeatures({privacy_sandbox::kPrivacySandboxSettings3},
-                                   {page_info::kPageSpecificSiteDataDialog,
-                                    page_info::kPageInfoCookiesSubpage});
+    feature_list_.InitWithFeatures(
+        {GetParam() ? privacy_sandbox::kPrivacySandboxSettings4
+                    : privacy_sandbox::kPrivacySandboxSettings3},
+        {page_info::kPageSpecificSiteDataDialog,
+         page_info::kPageInfoCookiesSubpage});
   }
 
   void SetUpOnMainThread() override {
@@ -579,11 +582,14 @@
   }
 
   // DialogBrowserTest:
-  void ShowUi(const std::string& name) override {
+  void ShowUi(const std::string& name_with_param_suffix) override {
     // Bubble dialogs' bounds may exceed the display's work area.
     // https://crbug.com/893292.
     set_should_verify_dialog_bounds(false);
 
+    const std::string& name =
+        name_with_param_suffix.substr(0, name_with_param_suffix.find("/"));
+
     ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), GetUrl("a.test")));
 
     // TODO(crbug.com/1286276): It would be better to actually access the
@@ -628,16 +634,20 @@
   net::EmbeddedTestServer https_server_{net::EmbeddedTestServer::TYPE_HTTPS};
 };
 
-IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewPrivacySandboxDialogBrowserTest,
+IN_PROC_BROWSER_TEST_P(PageInfoBubbleViewPrivacySandboxDialogBrowserTest,
                        InvokeUi_PrivacySandboxMain) {
   ShowAndVerifyUi();
 }
 
-IN_PROC_BROWSER_TEST_F(PageInfoBubbleViewPrivacySandboxDialogBrowserTest,
+IN_PROC_BROWSER_TEST_P(PageInfoBubbleViewPrivacySandboxDialogBrowserTest,
                        InvokeUi_PrivacySandboxSubpage) {
   ShowAndVerifyUi();
 }
 
+INSTANTIATE_TEST_SUITE_P(All,
+                         PageInfoBubbleViewPrivacySandboxDialogBrowserTest,
+                         testing::Bool());
+
 class PageInfoBubbleViewHistoryDialogBrowserTest : public DialogBrowserTest {
  public:
   PageInfoBubbleViewHistoryDialogBrowserTest() {
diff --git a/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc b/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
index 6122bda1..883be32 100644
--- a/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
+++ b/chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.cc
@@ -4,6 +4,9 @@
 
 #include "chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_ui.h"
 
+#include "base/i18n/time_formatting.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
+#include "chrome/browser/privacy_sandbox/privacy_sandbox_service_factory.h"
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/ui/webui/browsing_topics/browsing_topics_internals_page_handler.h"
 #include "chrome/browser/ui/webui/webui_util.h"
@@ -11,16 +14,92 @@
 #include "chrome/grit/browsing_topics_internals_resources.h"
 #include "chrome/grit/browsing_topics_internals_resources_map.h"
 #include "components/browsing_topics/mojom/browsing_topics_internals.mojom.h"
+#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
+#include "components/strings/grit/components_strings.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/browser/web_ui_data_source.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
 
+namespace {
+
+void AddTopicsConsentStrings(content::WebUIDataSource* html_source,
+                             Profile* profile) {
+  auto* privacy_sandbox_service =
+      PrivacySandboxServiceFactory::GetForProfile(profile);
+
+  // Regardless of profile type, the service should always exist.
+  DCHECK(privacy_sandbox_service);
+
+  int consent_status_string_id = 0;
+  if (!privacy_sandbox_service->TopicsConsentRequired()) {
+    consent_status_string_id = IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED;
+  } else if (privacy_sandbox_service->TopicsHasActiveConsent()) {
+    DCHECK(privacy_sandbox_service->TopicsConsentRequired());
+    consent_status_string_id = IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE;
+  } else {
+    DCHECK(!privacy_sandbox_service->TopicsHasActiveConsent());
+    DCHECK(privacy_sandbox_service->TopicsConsentRequired());
+    consent_status_string_id = IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE;
+  }
+  DCHECK(consent_status_string_id);
+  html_source->AddLocalizedString("topicsConsentStatus",
+                                  consent_status_string_id);
+
+  int consent_source_string_id = 0;
+  switch (privacy_sandbox_service->TopicsConsentLastUpdateSource()) {
+    case (privacy_sandbox::TopicsConsentUpdateSource::kDefaultValue): {
+      consent_source_string_id =
+          IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT;
+      break;
+    }
+    case (privacy_sandbox::TopicsConsentUpdateSource::kSettings): {
+      consent_source_string_id =
+          IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS;
+      break;
+    }
+    case (privacy_sandbox::TopicsConsentUpdateSource::kConfirmation): {
+      consent_source_string_id =
+          IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION;
+      break;
+    }
+  }
+  DCHECK(consent_source_string_id);
+  html_source->AddLocalizedString("topicsConsentSource",
+                                  consent_source_string_id);
+
+  html_source->AddString(
+      "topicsConsentTime",
+      base::TimeFormatFriendlyDateAndTime(
+          privacy_sandbox_service->TopicsConsentLastUpdateTime()));
+
+  html_source->AddString(
+      "topicsConsentText",
+      privacy_sandbox_service->TopicsConsentLastUpdateText());
+
+  // Static strings
+  static constexpr webui::LocalizedString kLocalizedStrings[] = {
+      {"topicsConsentStatusLabel",
+       IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL},
+      {"topicsConsentSourceLabel",
+       IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL},
+      {"topicsConsentTimeLabel",
+       IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL},
+      {"topicsConsentTextLabel",
+       IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL},
+  };
+  html_source->AddLocalizedStrings(kLocalizedStrings);
+}
+
+}  // namespace
+
 BrowsingTopicsInternalsUI::BrowsingTopicsInternalsUI(content::WebUI* web_ui)
     : ui::MojoWebUIController(web_ui, true) {
   content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
       web_ui->GetWebContents()->GetBrowserContext(),
       chrome::kChromeUIBrowsingTopicsInternalsHost);
 
+  AddTopicsConsentStrings(source, Profile::FromWebUI(web_ui));
+
   webui::SetupWebUIDataSource(
       source,
       base::make_span(kBrowsingTopicsInternalsResources,
diff --git a/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc b/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc
index ba48bad..9058e6f 100644
--- a/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc
+++ b/chrome/browser/ui/webui/settings/settings_interactive_uitest.cc
@@ -12,6 +12,7 @@
 #include "chrome/test/base/in_process_browser_test.h"
 #include "chrome/test/interaction/tracked_element_webcontents.h"
 #include "chrome/test/interaction/webcontents_interaction_test_util.h"
+#include "components/privacy_sandbox/privacy_sandbox_features.h"
 #include "content/public/test/browser_test.h"
 #include "net/dns/mock_host_resolver.h"
 #include "ui/base/interaction/expect_call_in_scope.h"
@@ -98,15 +99,31 @@
   }
 };
 
-IN_PROC_BROWSER_TEST_F(SettingsInteractiveUiTest,
+class CookieSettingsInteractiveUiTest
+    : public SettingsInteractiveUiTest,
+      public testing::WithParamInterface<bool> {
+ public:
+  CookieSettingsInteractiveUiTest() {
+    feature_list_.InitWithFeatureState(
+        privacy_sandbox::kPrivacySandboxSettings4, GetParam());
+  }
+
+ private:
+  base::test::ScopedFeatureList feature_list_;
+};
+
+IN_PROC_BROWSER_TEST_P(CookieSettingsInteractiveUiTest,
                        CheckQuestionMarkIsPresentUnderCookiesAndSiteData) {
   UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::CompletedCallback, completed);
   UNCALLED_MOCK_CALLBACK(ui::InteractionSequence::AbortedCallback, aborted);
 
+  const std::string cookie_row_selector =
+      GetParam() ? "cr-link-row#thirdPartyCookiesLinkRow"
+                 : "cr-link-row#cookiesLinkRow";
   const GURL cookie_setting_url("chrome://settings/privacy");
   const WebContentsInteractionTestUtil::DeepQuery cookies_link_row = {
       "settings-ui", "settings-main", "settings-basic-page",
-      "settings-privacy-page", "cr-link-row#cookiesLinkRow"};
+      "settings-privacy-page", cookie_row_selector};
   const WebContentsInteractionTestUtil::DeepQuery
       cookies_setting_page_help_icon = {
           "settings-ui",
@@ -153,6 +170,8 @@
   EXPECT_CALL_IN_SCOPE(completed, Run, sequence->RunSynchronouslyForTesting());
 }
 
+INSTANTIATE_TEST_SUITE_P(All, CookieSettingsInteractiveUiTest, testing::Bool());
+
 class ThemeSettingsInteractiveUiTest : public SettingsInteractiveUiTest {
  public:
   void SetUpCommandLine(base::CommandLine* command_line) override {
diff --git a/chrome/browser/web_applications/locks/app_lock.h b/chrome/browser/web_applications/locks/app_lock.h
index 048162b..821dcb80 100644
--- a/chrome/browser/web_applications/locks/app_lock.h
+++ b/chrome/browser/web_applications/locks/app_lock.h
@@ -70,14 +70,14 @@
   WebAppUiManager& ui_manager() { return *ui_manager_; }
 
  private:
-  raw_ref<WebAppRegistrar> registrar_;
-  raw_ref<WebAppSyncBridge> sync_bridge_;
-  raw_ref<WebAppInstallFinalizer> install_finalizer_;
-  raw_ref<OsIntegrationManager> os_integration_manager_;
-  raw_ref<WebAppInstallManager> install_manager_;
-  raw_ref<WebAppIconManager> icon_manager_;
-  raw_ref<WebAppTranslationManager> translation_manager_;
-  raw_ref<WebAppUiManager> ui_manager_;
+  raw_ref<WebAppRegistrar, DanglingUntriaged> registrar_;
+  raw_ref<WebAppSyncBridge, DanglingUntriaged> sync_bridge_;
+  raw_ref<WebAppInstallFinalizer, DanglingUntriaged> install_finalizer_;
+  raw_ref<OsIntegrationManager, DanglingUntriaged> os_integration_manager_;
+  raw_ref<WebAppInstallManager, DanglingUntriaged> install_manager_;
+  raw_ref<WebAppIconManager, DanglingUntriaged> icon_manager_;
+  raw_ref<WebAppTranslationManager, DanglingUntriaged> translation_manager_;
+  raw_ref<WebAppUiManager, DanglingUntriaged> ui_manager_;
 };
 
 class AppLock : public Lock, public WithAppResources {
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 81b8bab..7b6464d 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-main-1674604749-2573612e327fada4d2a3eef5b62618d63b60fd7c.profdata
+chrome-linux-main-1674646908-1a2d9a197184ed4b416c08a6181483277cb38b8f.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt
index eb9dd14..bd48743 100644
--- a/chrome/build/mac-arm.pgo.txt
+++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@
-chrome-mac-arm-main-1674626180-20a40fc31ff63f4a0c2c8d23d54b09e5f9cbccf7.profdata
+chrome-mac-arm-main-1674646908-a2d994ed1749852d4163793acba88863a3bd0db4.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index 373c9217e..11c5598 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-main-1674626180-4cd6a2c3d4a6d3297156651844ac51d3aa634472.profdata
+chrome-mac-main-1674646908-6581c73c66d969ff1fa5207cc95448dfbe304661.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index a22c247..9747b2a 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-main-1674604749-3ca2650cdd0404ebd362226c4505692ecfa31579.profdata
+chrome-win32-main-1674635826-61327aa41d1d20f1514dcd09bbb557ed8b02aa3f.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index aee578267..3e76a8c 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-main-1674626180-1f4f82d9f6fac67836dc4d3c3d29011b0eee86ab.profdata
+chrome-win64-main-1674635826-88ea6c4857218afde61b53f2e8d382a84c2450fb.profdata
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
index 1166f8e..a482d34 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/ChromeTabbedActivityTestRule.java
@@ -144,8 +144,8 @@
         TabModel incognitoTabModel = getActivity().getTabModelSelector().getModel(true);
         TabModelObserver observer = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 createdCallback.notifyCalled();
             }
 
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
index 36418cac..af7a24f 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/ChromeTabUtils.java
@@ -386,8 +386,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             normalTabModel.addObserver(new TabModelObserver() {
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     createdCallback.notifyCalled();
                     normalTabModel.removeObserver(this);
                 }
@@ -434,8 +434,8 @@
         TabModel tabModel = activity.getTabModelSelector().getModel(incognito);
         TabModelObserver observer = new TabModelObserver() {
             @Override
-            public void didAddTab(
-                    Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+            public void didAddTab(Tab tab, @TabLaunchType int type,
+                    @TabCreationState int creationState, boolean markedForSelection) {
                 createdCallback.notifyCalled();
             }
 
@@ -750,8 +750,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             tabModel.addObserver(new TabModelObserver() {
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     if (TextUtils.equals(expectedUrl, tab.getUrl().getSpec())) {
                         createdCallback.notifyCalled();
                         tabModel.removeObserver(this);
@@ -802,8 +802,8 @@
         TestThreadUtils.runOnUiThreadBlocking(() -> {
             tabModel.addObserver(new TabModelObserver() {
                 @Override
-                public void didAddTab(
-                        Tab tab, @TabLaunchType int type, @TabCreationState int creationState) {
+                public void didAddTab(Tab tab, @TabLaunchType int type,
+                        @TabCreationState int creationState, boolean markedForSelection) {
                     if (TextUtils.equals(expectedUrl, tab.getUrl().getSpec())) {
                         createdCallback.notifyCalled();
                         tabModel.removeObserver(this);
diff --git a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModel.java b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModel.java
index f94aaab..8d08f578 100644
--- a/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModel.java
+++ b/chrome/test/android/javatests/src/org/chromium/chrome/test/util/browser/tabmodel/MockTabModel.java
@@ -70,7 +70,9 @@
             }
         }
 
-        for (TabModelObserver observer : mObservers) observer.didAddTab(tab, type, creationState);
+        for (TabModelObserver observer : mObservers) {
+            observer.didAddTab(tab, type, creationState, false);
+        }
     }
 
     @Override
diff --git a/chromeos/ash/components/dbus/biod/OWNERS b/chromeos/ash/components/dbus/biod/OWNERS
new file mode 100644
index 0000000..20e41d6
--- /dev/null
+++ b/chromeos/ash/components/dbus/biod/OWNERS
@@ -0,0 +1 @@
+file://ash/login/LOGIN_LOCK_OWNERS
diff --git a/chromeos/ash/components/network/cellular_metrics_logger.cc b/chromeos/ash/components/network/cellular_metrics_logger.cc
index 37cb6f6c..e02a1b8 100644
--- a/chromeos/ash/components/network/cellular_metrics_logger.cc
+++ b/chromeos/ash/components/network/cellular_metrics_logger.cc
@@ -162,6 +162,8 @@
     return SimPinOperationResult::kErrorPinRequired;
   if (shill_error_name == shill::kErrorResultNotFound)
     return SimPinOperationResult::kErrorDeviceMissing;
+  if (shill_error_name == shill::kErrorResultWrongState)
+    return SimPinOperationResult::kErrorWrongState;
   return SimPinOperationResult::kErrorUnknown;
 }
 
diff --git a/chromeos/ash/components/network/cellular_metrics_logger.h b/chromeos/ash/components/network/cellular_metrics_logger.h
index 04fd1dc..c16d90ff 100644
--- a/chromeos/ash/components/network/cellular_metrics_logger.h
+++ b/chromeos/ash/components/network/cellular_metrics_logger.h
@@ -261,7 +261,8 @@
     kErrorPinRequired = 7,
     kErrorTimeout = 8,
     kErrorUnknown = 9,
-    kMaxValue = kErrorUnknown,
+    kErrorWrongState = 10,
+    kMaxValue = kErrorWrongState,
   };
 
   // This enum is used to track the connection results from
diff --git a/chromeos/crosapi/mojom/nullable_primitives.mojom b/chromeos/crosapi/mojom/nullable_primitives.mojom
index ca66327a..78d45d4 100644
--- a/chromeos/crosapi/mojom/nullable_primitives.mojom
+++ b/chromeos/crosapi/mojom/nullable_primitives.mojom
@@ -25,6 +25,12 @@
   uint8 value@0;
 };
 
+[Stable]
+struct UInt16Value {
+  // The value of the uint16.
+  uint16 value@0;
+};
+
 [Stable, RenamedFrom="ash.health.mojom.UInt32Value"]
 struct UInt32Value {
   // The value of the uint32.
diff --git a/chromeos/crosapi/mojom/probe_service.mojom b/chromeos/crosapi/mojom/probe_service.mojom
index 401e3a62..f864bb0 100644
--- a/chromeos/crosapi/mojom/probe_service.mojom
+++ b/chromeos/crosapi/mojom/probe_service.mojom
@@ -39,6 +39,9 @@
 //           can easily be more than uint32 range.
 //   4) ProbeMemoryInfo: use uint64 to store page_faults_since_last_boot instead
 //      of uint32, it can be more than uint32 range.
+//   5) ProbeBusResult: Holds a list of ProbeBusInfo.
+//      This is a subset of DeviceInfo containing the fields that can be exposed
+//      to third party code. Note: DeviceInfo is used by cros_healthd.
 
 module crosapi.mojom;
 
@@ -71,7 +74,7 @@
 
 // An enumeration of each category of information that cros_healthd can report.
 //
-// Next ID: 15
+// Next ID: 16
 [Stable, Extensible]
 enum ProbeCategoryEnum {
   [Default] kUnknown = 11,
@@ -89,6 +92,7 @@
   kNetwork = 12,
   kTpm = 13,
   kAudio = 14,
+  kBus = 15,
 };
 
 // An enumeration of the different categories of errors that can occur when
@@ -170,6 +174,156 @@
   ProbeError error;
 };
 
+// The info related to usb interfaces.
+//
+// NextMinVersion: 1, NextIndex: 5
+[Stable]
+struct ProbeUsbBusInterfaceInfo {
+  // The zero-based number (index) of the interface.
+  UInt8Value? interface_number@0;
+  // These fields can be used to classify / identify the usb interfaces. See the
+  // usb.ids database for the values, e.g. https://github.com/gentoo/hwids.
+  UInt8Value? class_id@1;
+  UInt8Value? subclass_id@2;
+  UInt8Value? protocol_id@3;
+  // The driver used by the device. This is the name of the matched driver which
+  // is registered in the kernel. See "{kernel root}/drivers/" for the list of
+  // the built in drivers.
+  string? driver@4;
+};
+
+// An enumeration of the formats of firmware version in fwpud. See the fwupd
+// repo for the values. (https://github.com/fwupd/fwupd)
+//
+// NextMinVersion: 1, NextIndex: 14
+[Stable, Extensible]
+enum ProbeFwupdVersionFormat {
+  // Unknown version format.
+  [Default] kUnknown = 0,
+  // An unidentified format text string.
+  kPlain = 1,
+  // A single integer version number.
+  kNumber = 2,
+  // Two AABB.CCDD version numbers.
+  kPair = 3,
+  // Microsoft-style AA.BB.CCDD version numbers.
+  kTriplet = 4,
+  // UEFI-style AA.BB.CC.DD version numbers.
+  kQuad = 5,
+  // Binary coded decimal notation.
+  kBcd = 6,
+  // Intel ME-style bitshifted notation.
+  kIntelMe = 7,
+  // Intel ME-style A.B.CC.DDDD notation.
+  kIntelMe2 = 8,
+  // Legacy Microsoft Surface 10b.12b.10b.
+  kSurfaceLegacy = 9,
+  // Microsoft Surface 8b.16b.8b.
+  kSurface = 10,
+  // Dell BIOS BB.CC.DD style.
+  kDellBios = 11,
+  // Hexadecimal 0xAABCCDD style.
+  kHex = 12,
+};
+
+// The info related to a firmware version obtained from fwupd.
+//
+// NextMinVersion: 1, NextIndex: 2
+[Stable]
+struct ProbeFwupdFirmwareVersionInfo {
+  // The string form of the firmware version.
+  string? version@0;
+  // The format for parsing the version string.
+  ProbeFwupdVersionFormat version_format@1;
+};
+
+// An enumeration of the usb version.
+//
+// NextMinVersion: 1, NextIndex: 5
+[Stable, Extensible]
+enum ProbeUsbVersion {
+  // Can't determine the usb version.
+  [Default] kUnknown = 0,
+  // Usb 1.
+  kUsb1 = 1,
+  // Usb 2.
+  kUsb2 = 2,
+  // Usb 3.
+  kUsb3 = 3,
+};
+
+// An enumeration of the usb spec speed in Mbps.
+// Source:
+//   - https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-bus-usb
+//   - https://www.kernel.org/doc/Documentation/ABI/stable/sysfs-bus-usb
+//   - https://en.wikipedia.org/wiki/USB
+//
+// NextMinVersion: 1, NextIndex: 8
+[Stable, Extensible]
+enum ProbeUsbSpecSpeed {
+  // Unknown speed.
+  [Default] kUnknown = 0,
+  // Low speed.
+  k1_5Mbps = 1,
+  // Full speed.
+  k12Mbps = 2,
+  // High Speed.
+  k480Mbps = 3,
+  // Super Speed.
+  k5Gbps = 4,
+  // Super Speed+.
+  k10Gbps = 5,
+  // Super Speed+ Gen 2x2.
+  k20Gbps = 6,
+};
+
+// The info related to usb.
+//
+// NextMinVersion: 1, NextIndex: 9
+[Stable]
+struct ProbeUsbBusInfo {
+  // These fields can be used to classify / identify the usb devices. See the
+  // usb.ids database for the values. (https://github.com/gentoo/hwids)
+  UInt8Value? class_id@0;
+  UInt8Value? subclass_id@1;
+  UInt8Value? protocol_id@2;
+  UInt16Value? vendor_id@3;
+  UInt16Value product_id@4;
+  // The usb interfaces belonging to the device. A usb device has at least one
+  // interface. Each interface may or may not work independently, based on each
+  // device. This allows a usb device to provide multiple features.
+  // The interfaces are sorted by the |interface_number| field.
+  array<ProbeUsbBusInterfaceInfo>? interfaces@5;
+  // The firmware version obtained from fwupd.
+  ProbeFwupdFirmwareVersionInfo? fwupd_firmware_version_info@6;
+  // The recognized usb version. It may not be the highest USB version supported
+  // by the hardware.
+  ProbeUsbVersion version@7;
+  // The spec usb speed.
+  ProbeUsbSpecSpeed spec_speed@8;
+};
+
+// The info related to a specific bus type.
+//
+// NextMinVersion: 1, NextIndex: 2
+[Stable, Extensible]
+union ProbeBusInfo {
+  // Do not use, exists for forwards compatibility.
+  [Default] bool unmapped_field@0;
+  // The info related to usb.
+  ProbeUsbBusInfo usb_bus_info@1;
+};
+
+// Bus probe result. Can either be populated with the ProbeBusInfo or an error
+// retrieving the information.
+[Stable]
+union ProbeBusResult {
+  // Valid ProbeBusInfo.
+  array<ProbeBusInfo> bus_devices_info;
+  // The error that occurred attempting to retrieve the ProbeBusInfo.
+  ProbeError error;
+};
+
 // Information related to a specific non-removable block device.
 //
 // Next ID: 12
@@ -666,7 +820,8 @@
 // attempt to fetch that information, and size zero if cros_healthd did attempt
 // to fetch that information, but was unable to.
 //
-// Next ID: 14
+// Next ID: 15
+// Next MinVersion: 3
 [Stable]
 struct ProbeTelemetryInfo {
   // Information about the device's main battery. Only present when kBattery was
@@ -714,6 +869,9 @@
   // Information about the audio devices. Only present when kAudio was included
   // in the categories input to ProbeTelemetryInfo.
   [MinVersion=1] ProbeAudioResult? audio_result@13;
+  // Information about the bus devices. Only present when kBus was included
+  // in the categories input to ProbeTelemetryInfo.
+  [MinVersion=2] ProbeBusResult? bus_result@14;
 };
 
 // Result of running /usr/share/cros/oemdata.sh script.
diff --git a/chromeos/profiles/arm.afdo.newest.txt b/chromeos/profiles/arm.afdo.newest.txt
index 95766974..fb50e3a3 100644
--- a/chromeos/profiles/arm.afdo.newest.txt
+++ b/chromeos/profiles/arm.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-arm-none-111-5481.32-1673869449-benchmark-111.0.5550.0-r1-redacted.afdo.xz
+chromeos-chrome-arm-none-111-5481.41-1674470533-benchmark-111.0.5557.0-r1-redacted.afdo.xz
diff --git a/chromeos/profiles/bigcore.afdo.newest.txt b/chromeos/profiles/bigcore.afdo.newest.txt
index e12060a..18f1436e 100644
--- a/chromeos/profiles/bigcore.afdo.newest.txt
+++ b/chromeos/profiles/bigcore.afdo.newest.txt
@@ -1 +1 @@
-chromeos-chrome-amd64-bigcore-111-5481.21-1673865504-benchmark-111.0.5550.0-r1-redacted.afdo.xz
+chromeos-chrome-amd64-bigcore-111-5481.41-1674472805-benchmark-111.0.5557.0-r1-redacted.afdo.xz
diff --git a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
index 1c90fa1b..639b38f 100644
--- a/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_factory_unittest.cc
@@ -92,11 +92,6 @@
   MOCK_METHOD(void, SetSecureContextRequired, (bool required), (override));
   MOCK_METHOD(void, SetFocusRequiresScroll, (bool require), (override));
   MOCK_METHOD(void, SetQueryPasswordSuggestion, (bool query), (override));
-  MOCK_METHOD(void,
-              GetElementFormAndFieldDataForDevToolsNodeId,
-              (int32_t backend_node_id,
-               GetElementFormAndFieldDataForDevToolsNodeIdCallback callback),
-              (override));
   MOCK_METHOD(void, EnableHeavyFormDataScraping, (), (override));
   MOCK_METHOD(void,
               SetFieldsEligibleForManualFilling,
diff --git a/components/autofill/content/browser/content_autofill_driver_unittest.cc b/components/autofill/content/browser/content_autofill_driver_unittest.cc
index 20d3db6..0f15a299 100644
--- a/components/autofill/content/browser/content_autofill_driver_unittest.cc
+++ b/components/autofill/content/browser/content_autofill_driver_unittest.cc
@@ -230,10 +230,6 @@
 
   void SetQueryPasswordSuggestion(bool query) override {}
 
-  void GetElementFormAndFieldDataForDevToolsNodeId(
-      int backend_node_id,
-      GetElementFormAndFieldDataForDevToolsNodeIdCallback callback) override {}
-
   void SetFieldsEligibleForManualFilling(
       const std::vector<FieldRendererId>& fields) override {}
 
diff --git a/components/autofill/content/common/mojom/autofill_agent.mojom b/components/autofill/content/common/mojom/autofill_agent.mojom
index 034ea1d..eca17ea 100644
--- a/components/autofill/content/common/mojom/autofill_agent.mojom
+++ b/components/autofill/content/common/mojom/autofill_agent.mojom
@@ -78,13 +78,6 @@
   // Configures whether AutofillAgent will query password field autofill suggestions. The default is false.
   SetQueryPasswordSuggestion(bool query);
 
-  // Get form element's form and field data. The form field is given by a
-  // stable devtools node identifier in the backend node id.
-  // https://chromedevtools.github.io/devtools-protocol/tot/DOM/#type-BackendNodeId
-  // The corresponding entity in the renderer is the DOMNodeIds.
-  GetElementFormAndFieldDataForDevToolsNodeId(int32 backend_node_id) => (
-      autofill.mojom.FormData form, autofill.mojom.FormFieldData field);
-
   // Allows heavy scraping of form data (e.g., button titles for
   // unowned forms).
   EnableHeavyFormDataScraping();
diff --git a/components/autofill/content/renderer/autofill_agent.cc b/components/autofill/content/renderer/autofill_agent.cc
index ce92239..36f3139 100644
--- a/components/autofill/content/renderer/autofill_agent.cc
+++ b/components/autofill/content/renderer/autofill_agent.cc
@@ -841,38 +841,6 @@
   focus_requires_scroll_ = require;
 }
 
-void AutofillAgent::GetElementFormAndFieldDataForDevToolsNodeId(
-    const int backend_node_id,
-    GetElementFormAndFieldDataForDevToolsNodeIdCallback callback) {
-  blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
-  if (!frame)
-    return;
-
-  blink::WebElement target_element =
-      frame->GetDocument().GetElementByDevToolsNodeId(backend_node_id);
-
-  FormData form;
-  FormFieldData field;
-
-  if (target_element.IsNull() || !target_element.IsFormControlElement()) {
-    return std::move(callback).Run(form, field);
-  }
-
-  blink::WebFormControlElement target_form_control_element =
-      target_element.To<blink::WebFormControlElement>();
-  bool success = FindFormAndFieldForFormControlElement(
-      target_form_control_element, field_data_manager_.get(), &form, &field);
-  if (success) {
-    // Remember this element so as to autofill the form without focusing the
-    // field for Autofill Assistant.
-    element_ = target_form_control_element;
-  }
-  // Do not expect failure.
-  DCHECK(success);
-
-  return std::move(callback).Run(form, field);
-}
-
 void AutofillAgent::EnableHeavyFormDataScraping() {
   is_heavy_form_data_scraping_enabled_ = true;
 }
diff --git a/components/autofill/content/renderer/autofill_agent.h b/components/autofill/content/renderer/autofill_agent.h
index a738882..7494da2 100644
--- a/components/autofill/content/renderer/autofill_agent.h
+++ b/components/autofill/content/renderer/autofill_agent.h
@@ -112,9 +112,6 @@
   void SetSecureContextRequired(bool required) override;
   void SetFocusRequiresScroll(bool require) override;
   void SetQueryPasswordSuggestion(bool required) override;
-  void GetElementFormAndFieldDataForDevToolsNodeId(
-      int backend_node_id,
-      GetElementFormAndFieldDataForDevToolsNodeIdCallback callback) override;
   void EnableHeavyFormDataScraping() override;
   void SetFieldsEligibleForManualFilling(
       const std::vector<FieldRendererId>& fields) override;
diff --git a/components/certificate_transparency/data/log_list.json b/components/certificate_transparency/data/log_list.json
index 6eb25b1..dfeaa31 100644
--- a/components/certificate_transparency/data/log_list.json
+++ b/components/certificate_transparency/data/log_list.json
@@ -1,6 +1,6 @@
 {
-  "version": "17.54",
-  "log_list_timestamp": "2023-01-24T12:55:45Z",
+  "version": "17.55",
+  "log_list_timestamp": "2023-01-25T12:54:57Z",
   "operators": [
     {
       "name": "Google",
diff --git a/components/content_settings/core/browser/cookie_settings.cc b/components/content_settings/core/browser/cookie_settings.cc
index eafff99..ffc05b6 100644
--- a/components/content_settings/core/browser/cookie_settings.cc
+++ b/components/content_settings/core/browser/cookie_settings.cc
@@ -228,9 +228,9 @@
 
     if (host_setting == CONTENT_SETTING_ALLOW) {
       block = false;
-      // TODO(crbug.com/1385156): Move to separate metric names.
-      FireStorageAccessHistogram(net::cookie_util::StorageAccessResult::
-                                     ACCESS_ALLOWED_STORAGE_ACCESS_GRANT);
+      FireStorageAccessHistogram(
+          net::cookie_util::StorageAccessResult::
+              ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT);
     }
   }
 #endif
diff --git a/components/content_settings/core/browser/cookie_settings_unittest.cc b/components/content_settings/core/browser/cookie_settings_unittest.cc
index ff45f317..9df434b 100644
--- a/components/content_settings/core/browser/cookie_settings_unittest.cc
+++ b/components/content_settings/core/browser/cookie_settings_unittest.cc
@@ -183,6 +183,18 @@
     return net::cookie_util::StorageAccessResult::ACCESS_BLOCKED;
   }
 
+  net::cookie_util::StorageAccessResult
+  BlockedStorageAccessResultWithTopLevelOverride() const {
+    if (IsStorageAccessAPIEnabled()) {
+      return net::cookie_util::StorageAccessResult::
+          ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT;
+    }
+    if (IsForceAllowThirdPartyCookies()) {
+      return net::cookie_util::StorageAccessResult::ACCESS_ALLOWED_FORCED;
+    }
+    return net::cookie_util::StorageAccessResult::ACCESS_BLOCKED;
+  }
+
  protected:
   bool ShouldDeleteCookieOnExit(const std::string& domain, bool is_https) {
     return cookie_settings_->ShouldDeleteCookieOnExit(
@@ -776,7 +788,7 @@
   histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
   histogram_tester.ExpectBucketCount(
       kAllowedRequestsHistogram,
-      static_cast<int>(BlockedStorageAccessResultWithEitherOverride()), 1);
+      static_cast<int>(BlockedStorageAccessResultWithTopLevelOverride()), 1);
 
   // Invalid pair the |top_level_url| granting access to |url| is now
   // being loaded under |url| as the top level url.
diff --git a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java
index 978b928..5d4fe90 100644
--- a/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java
+++ b/components/embedder_support/android/java/src/org/chromium/components/embedder_support/util/UrlUtilities.java
@@ -81,17 +81,6 @@
     }
 
     /**
-     * @param uri A URI.
-     *
-     * @return True if the URI's scheme is one that ContentView can handle.
-     * @deprecated use {@link #isAcceptedScheme(GURL)} instead.
-     */
-    @Deprecated
-    public static boolean isAcceptedScheme(String uri) {
-        return isAcceptedScheme(new GURL(uri));
-    }
-
-    /**
      * @param url A GURL.
      *
      * @return True if the GURL's scheme is one that ContentView can handle.
diff --git a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
index 1ed6304..3512f59a 100644
--- a/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
+++ b/components/embedder_support/android/javatests/src/org/chromium/components/embedder_support/util/UrlUtilitiesUnitTest.java
@@ -90,24 +90,26 @@
     @Test
     @SmallTest
     public void testIsAcceptedScheme() {
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("about:awesome"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("data:data"));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("about:awesome")));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("data:data")));
         Assert.assertTrue(UrlUtilities.isAcceptedScheme(
-                "https://user:pass@awesome.com:9000/bad-scheme/#fake"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("http://awesome.example.com/"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("file://hostname/path/to/file"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("inline:skates.co.uk"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("javascript:alert(1)"));
-        Assert.assertTrue(UrlUtilities.isAcceptedScheme("http://foo.bar/has[square].html"));
+                new GURL("https://user:pass@awesome.com:9000/bad-scheme/#fake")));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("http://awesome.example.com/")));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("file://hostname/path/to/file")));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("inline:skates.co.uk")));
+        Assert.assertTrue(UrlUtilities.isAcceptedScheme(new GURL("javascript:alert(1)")));
+        Assert.assertTrue(
+                UrlUtilities.isAcceptedScheme(new GURL("http://foo.bar/has[square].html")));
 
-        Assert.assertFalse(UrlUtilities.isAcceptedScheme("super:awesome"));
-        Assert.assertFalse(UrlUtilities.isAcceptedScheme("ftp://https:password@example.com/"));
+        Assert.assertFalse(UrlUtilities.isAcceptedScheme(new GURL("super:awesome")));
         Assert.assertFalse(
-                UrlUtilities.isAcceptedScheme("ftp://https:password@example.com/?http:#http:"));
+                UrlUtilities.isAcceptedScheme(new GURL("ftp://https:password@example.com/")));
         Assert.assertFalse(UrlUtilities.isAcceptedScheme(
-                "google-search://https:password@example.com/?http:#http:"));
-        Assert.assertFalse(UrlUtilities.isAcceptedScheme("chrome://http://version"));
-        Assert.assertFalse(UrlUtilities.isAcceptedScheme(""));
+                new GURL("ftp://https:password@example.com/?http:#http:")));
+        Assert.assertFalse(UrlUtilities.isAcceptedScheme(
+                new GURL("google-search://https:password@example.com/?http:#http:")));
+        Assert.assertFalse(UrlUtilities.isAcceptedScheme(new GURL("chrome://http://version")));
+        Assert.assertFalse(UrlUtilities.isAcceptedScheme(GURL.emptyGURL()));
     }
 
     @Test
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
index 842e0b2..0d027de5 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationDelegate.java
@@ -135,7 +135,7 @@
      * Whether the Activity launch should be aborted if the disambiguation prompt is going to be
      * shown and Chrome is able to handle the navigation.
      */
-    boolean shouldAvoidDisambiguationDialog(Intent intent);
+    boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl);
 
     /**
      * Whether navigations started by the embedder (i.e. not by the renderer) should stay in the
diff --git a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
index 537f654a..3bb3073 100644
--- a/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
+++ b/components/external_intents/android/java/src/org/chromium/components/external_intents/ExternalNavigationHandler.java
@@ -1572,7 +1572,7 @@
         }
 
         if (shouldAvoidShowingDisambiguationPrompt(
-                    isExternalProtocol, targetIntent, resolvingInfos, resolveActivity)) {
+                    isExternalProtocol, intentDataUrl, resolvingInfos, resolveActivity)) {
             return OverrideUrlLoadingResult.forNoOverride();
         }
 
@@ -1598,7 +1598,7 @@
     }
 
     private boolean shouldAvoidShowingDisambiguationPrompt(boolean isExternalProtocol,
-            Intent intent, QueryIntentActivitiesSupplier resolvingInfosSupplier,
+            GURL intentDataUrl, QueryIntentActivitiesSupplier resolvingInfosSupplier,
             ResolveActivitySupplier resolveActivitySupplier) {
         // For navigations Chrome can't handle, it's fine to show the disambiguation dialog
         // regardless of the embedder's preference.
@@ -1606,7 +1606,7 @@
 
         // Don't bother performing the package manager checks if the delegate is fine with the
         // disambiguation prompt.
-        if (!mDelegate.shouldAvoidDisambiguationDialog(intent)) return false;
+        if (!mDelegate.shouldAvoidDisambiguationDialog(intentDataUrl)) return false;
 
         ResolveInfo resolveActivity = resolveActivitySupplier.get();
 
diff --git a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
index dfb6a65..caceda69 100644
--- a/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
+++ b/components/external_intents/android/javatests/src/org/chromium/components/external_intents/ExternalNavigationHandlerTest.java
@@ -2895,7 +2895,7 @@
         }
 
         @Override
-        public boolean shouldAvoidDisambiguationDialog(Intent intent) {
+        public boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl) {
             return mShouldAvoidDisambiguationDialog;
         }
 
diff --git a/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h b/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
index 916d640..ee071139 100644
--- a/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
+++ b/components/password_manager/core/browser/affiliation/affiliations_prefetcher.h
@@ -52,7 +52,7 @@
 
   void InitializeWithPasswordStores();
 
-  raw_ptr<AffiliationService> affiliation_service_ = nullptr;
+  raw_ptr<AffiliationService, DanglingUntriaged> affiliation_service_ = nullptr;
 
   // Password stores registered via RegisterPasswordStore but aren't observed
   // yet.
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java
index 8150e71a..0a71266 100644
--- a/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java
+++ b/components/payments/content/android/java/src/org/chromium/components/payments/PaymentFeatureList.java
@@ -20,6 +20,8 @@
     /** Alphabetical: */
     public static final String ADD_IDENTITY_IN_CAN_MAKE_PAYMENT_EVENT =
             "AddIdentityInCanMakePaymentEvent";
+    public static final String ALLOW_DISCOVERABLE_CREDENTIALS_FOR_SECURE_PAYMENT_CONFIRMATION =
+            "AllowDiscoverableCredentialsForSecurePaymentConfirmation";
     public static final String ANDROID_APP_PAYMENT_UPDATE_EVENTS = "AndroidAppPaymentUpdateEvents";
     public static final String ENFORCE_FULL_DELEGATION = "EnforceFullDelegation";
     public static final String GPAY_APP_DYNAMIC_UPDATE = "GPayAppDynamicUpdate";
diff --git a/components/payments/content/android/payment_feature_list.cc b/components/payments/content/android/payment_feature_list.cc
index 06d6345..250a03bd 100644
--- a/components/payments/content/android/payment_feature_list.cc
+++ b/components/payments/content/android/payment_feature_list.cc
@@ -24,6 +24,8 @@
 // Android only features).
 const base::Feature* const kFeaturesExposedToJava[] = {
     &::blink::features::kAddIdentityInCanMakePaymentEvent,
+    &::blink::features::
+        kAllowDiscoverableCredentialsForSecurePaymentConfirmation,
     &::features::kSecurePaymentConfirmation,
     &::features::kServiceWorkerPaymentApps,
     &::features::kWebPayments,
diff --git a/components/pdf/renderer/pdf_accessibility_tree.cc b/components/pdf/renderer/pdf_accessibility_tree.cc
index 7385fb2f..d47c9beb 100644
--- a/components/pdf/renderer/pdf_accessibility_tree.cc
+++ b/components/pdf/renderer/pdf_accessibility_tree.cc
@@ -703,6 +703,7 @@
     link_node->AddStringAttribute(ax::mojom::StringAttribute::kName,
                                   std::string());
     link_node->relative_bounds.bounds = link.bounds;
+    link_node->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kJump);
     node_id_to_annotation_info_->emplace(
         link_node->id,
         PdfAccessibilityTree::AnnotationInfo(page_index_, link.index_in_page));
diff --git a/components/policy/core/browser/policy_pref_mapping_test.cc b/components/policy/core/browser/policy_pref_mapping_test.cc
index 5ecd7bb7..8a0b4ede 100644
--- a/components/policy/core/browser/policy_pref_mapping_test.cc
+++ b/components/policy/core/browser/policy_pref_mapping_test.cc
@@ -48,8 +48,8 @@
   kLocalState,
 };
 
-PrefLocation GetPrefLocation(const base::Value& settings) {
-  const std::string* location = settings.FindStringKey("location");
+PrefLocation GetPrefLocation(const base::Value::Dict& settings) {
+  const std::string* location = settings.FindString("location");
   if (!location || *location == "user_profile")
     return PrefLocation::kUserProfile;
   if (*location == "local_state")
@@ -136,14 +136,14 @@
 // chrome/test/data/policy/policy_test_cases.json.
 class PrefTestCase {
  public:
-  explicit PrefTestCase(const std::string& name, const base::Value& settings) {
-    const base::Value* value = settings.FindKey("value");
-    const base::Value* default_value = settings.FindKey("default_value");
+  PrefTestCase(const std::string& name, const base::Value::Dict& settings) {
+    const base::Value* value = settings.Find("value");
+    const base::Value* default_value = settings.Find("default_value");
     location_ = GetPrefLocation(settings);
     check_for_mandatory_ =
-        settings.FindBoolKey("check_for_mandatory").value_or(true);
+        settings.FindBool("check_for_mandatory").value_or(true);
     check_for_recommended_ =
-        settings.FindBoolKey("check_for_recommended").value_or(true);
+        settings.FindBool("check_for_recommended").value_or(true);
 
     pref_ = name;
     if (value)
@@ -210,7 +210,8 @@
           ADD_FAILURE() << "prefs item " << name << " is not dict";
           continue;
         }
-        prefs_.push_back(std::make_unique<PrefTestCase>(name, setting));
+        prefs_.push_back(
+            std::make_unique<PrefTestCase>(name, setting.GetDict()));
       }
     }
     if (prefs_.empty()) {
diff --git a/components/policy/core/common/policy_loader_common_unittest.cc b/components/policy/core/common/policy_loader_common_unittest.cc
index 2e2bbea..3d6d62c 100644
--- a/components/policy/core/common/policy_loader_common_unittest.cc
+++ b/components/policy/core/common/policy_loader_common_unittest.cc
@@ -16,28 +16,28 @@
 
 namespace policy {
 namespace {
-base::Value ToListValue(const std::vector<std::string>& values) {
+base::Value::List ToList(const std::vector<std::string>& values) {
   base::Value::List storage;
   storage.reserve(values.size());
   for (const auto& value : values)
     storage.Append(value);
 
-  return base::Value(std::move(storage));
+  return storage;
 }
 
-base::Value ToDictValue(const std::string& json) {
-  absl::optional<base::Value> value = base::JSONReader::Read(json);
-  return std::move(value.value());
+base::Value::Dict ToDict(const std::string& json) {
+  return base::JSONReader::Read(json).value().TakeDict();
 }
 
 }  // namespace
 
 class SensitivePolicyFilterTest : public ::testing::Test {
  public:
-  void AddNewPolicy(const std::string& name, const base::Value& value) {
+  void AddNewPolicy(const std::string& name, base::Value value) {
     policies_.Set(name, PolicyLevel::POLICY_LEVEL_MANDATORY,
                   PolicyScope::POLICY_SCOPE_MACHINE,
-                  PolicySource::POLICY_SOURCE_PLATFORM, value.Clone(), nullptr);
+                  PolicySource::POLICY_SOURCE_PLATFORM, std::move(value),
+                  nullptr);
   }
 
   PolicyMap* policies() { return &policies_; }
@@ -60,10 +60,10 @@
 }
 
 TEST_F(SensitivePolicyFilterTest, TestExtensionInstallForceListFilter) {
-  base::Value policy = ToListValue(
-      {"extension0", "extension1;example.com", "extension2;",
-       "extension3;https://clients2.google.com/service/update2/crx"});
-  AddNewPolicy(key::kExtensionInstallForcelist, policy);
+  base::Value::List policy =
+      ToList({"extension0", "extension1;example.com", "extension2;",
+              "extension3;https://clients2.google.com/service/update2/crx"});
+  AddNewPolicy(key::kExtensionInstallForcelist, base::Value(std::move(policy)));
 
   EXPECT_TRUE(policies()->Get(key::kExtensionInstallForcelist));
 
@@ -72,14 +72,14 @@
   const auto* actual_filtered_policy = policies()->GetValue(
       key::kExtensionInstallForcelist, base::Value::Type::LIST);
   ASSERT_TRUE(actual_filtered_policy);
-  base::Value expected_filtered_policy = ToListValue(
+  base::Value::List expected_filtered_policy = ToList(
       {"extension0", "[BLOCKED]extension1;example.com", "[BLOCKED]extension2;",
        "extension3;https://clients2.google.com/service/update2/crx"});
   EXPECT_EQ(expected_filtered_policy, *actual_filtered_policy);
 }
 
 TEST_F(SensitivePolicyFilterTest, TestExtensionSettingsFilter) {
-  base::Value policy = ToDictValue(R"({
+  base::Value::Dict policy = ToDict(R"({
     "*": {
       "installation_mode": "force_installed",
       "update_url": "https://example.com"
@@ -108,22 +108,23 @@
     },
     "invalid": "settings"
   })");
-  AddNewPolicy(key::kExtensionSettings, policy);
+  AddNewPolicy(key::kExtensionSettings, base::Value(policy.Clone()));
 
   EXPECT_TRUE(policies()->Get(key::kExtensionSettings));
 
   FilterSensitivePolicies(policies());
 
-  const auto* filtered_policy =
-      policies()->GetValue(key::kExtensionSettings, base::Value::Type::DICT);
-  ASSERT_TRUE(filtered_policy);
-  EXPECT_EQ(policy.DictSize(), filtered_policy->DictSize());
-  for (const auto entry : policy.DictItems()) {
+  const base::Value::Dict& filtered_policy =
+      policies()
+          ->GetValue(key::kExtensionSettings, base::Value::Type::DICT)
+          ->GetDict();
+  EXPECT_EQ(policy.size(), filtered_policy.size());
+  for (const auto entry : policy) {
     std::string extension = entry.first;
     if (extension == "extension4" || extension == "extension5")
       extension = "[BLOCKED]" + extension;
 
-    const base::Value* filtered_setting = filtered_policy->FindKey(extension);
+    const base::Value* filtered_setting = filtered_policy.Find(extension);
     ASSERT_TRUE(filtered_setting);
     EXPECT_EQ(entry.second, *filtered_setting)
         << "Mismatch for extension: " + extension;
diff --git a/components/policy/resources/templates/policy_definitions/Miscellaneous/PhoneHubCameraRollAllowed.yaml b/components/policy/resources/templates/policy_definitions/Miscellaneous/PhoneHubCameraRollAllowed.yaml
index 327d646..fcb9d51 100644
--- a/components/policy/resources/templates/policy_definitions/Miscellaneous/PhoneHubCameraRollAllowed.yaml
+++ b/components/policy/resources/templates/policy_definitions/Miscellaneous/PhoneHubCameraRollAllowed.yaml
@@ -11,8 +11,8 @@
 features:
   dynamic_refresh: true
   per_profile: true
-future_on:
-- chrome_os
+supported_on:
+- chrome_os:111-
 items:
 - caption: Allows users who have opted in to Phone Hub to access recent photos and
     videos taken on their phone
diff --git a/components/power_bookmarks/storage/power_bookmark_backend.h b/components/power_bookmarks/storage/power_bookmark_backend.h
index 3f4ce90..690f427 100644
--- a/components/power_bookmarks/storage/power_bookmark_backend.h
+++ b/components/power_bookmarks/storage/power_bookmark_backend.h
@@ -104,7 +104,7 @@
 
   // Observer that serves the frontend of power bookmarks.
   // Needs to be called on the frontend task runner.
-  raw_ptr<PowerBookmarkObserver> service_observer_;
+  raw_ptr<PowerBookmarkObserver, DanglingUntriaged> service_observer_;
 
   SEQUENCE_CHECKER(sequence_checker_);
 };
diff --git a/components/power_bookmarks/storage/power_bookmark_sync_bridge.h b/components/power_bookmarks/storage/power_bookmark_sync_bridge.h
index 30883c7..730d6cf 100644
--- a/components/power_bookmarks/storage/power_bookmark_sync_bridge.h
+++ b/components/power_bookmarks/storage/power_bookmark_sync_bridge.h
@@ -104,8 +104,8 @@
       syncer::EntityChangeList& entity_changes,
       bool is_initial_merge);
 
-  const raw_ptr<syncer::SyncMetadataStore> meta_db_;
-  const raw_ptr<Delegate> delegate_;
+  const raw_ptr<syncer::SyncMetadataStore, DanglingUntriaged> meta_db_;
+  const raw_ptr<Delegate, DanglingUntriaged> delegate_;
 };
 
 }  // namespace power_bookmarks
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util.cc b/components/privacy_sandbox/privacy_sandbox_test_util.cc
index f23660b..6d1ce177 100644
--- a/components/privacy_sandbox/privacy_sandbox_test_util.cc
+++ b/components/privacy_sandbox/privacy_sandbox_test_util.cc
@@ -283,9 +283,9 @@
           GetItemValue<bool>(input_value));
       return;
     }
-    case (InputKey::kTopicsConfirmationDecisionConfirmed): {
-      privacy_sandbox_service->TopicsConfirmationDecisionMade(
-          GetItemValue<bool>(input_value));
+    case (InputKey::kPromptAction): {
+      privacy_sandbox_service->PromptActionOccurred(
+          GetItemValue<int>(input_value));
       return;
     }
     default: {
@@ -594,9 +594,6 @@
     case (OutputKey::kM1ConsentDecisionMade): {
       SCOPED_TRACE("Check Output: M1 consent decision made");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1ConsentDecisionMade));
       return;
@@ -604,9 +601,6 @@
     case (OutputKey::kM1EEANoticeAcknowledged): {
       SCOPED_TRACE("Check Output: M1 eea notice acknowledged");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1EEANoticeAcknowledged));
       return;
@@ -614,9 +608,6 @@
     case (OutputKey::kM1RowNoticeAcknowledged): {
       SCOPED_TRACE("Check Output: M1 row notice acknowledged");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1RowNoticeAcknowledged));
       return;
@@ -624,9 +615,6 @@
     case (OutputKey::kM1TopicsEnabled): {
       SCOPED_TRACE("Check Output: M1 topics enabled");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1TopicsEnabled));
       return;
@@ -634,9 +622,6 @@
     case (OutputKey::kM1FledgeEnabled): {
       SCOPED_TRACE("Check Output: M1 fledge enabled");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1FledgeEnabled));
       return;
@@ -644,9 +629,6 @@
     case (OutputKey::kM1AdMeasurementEnabled): {
       SCOPED_TRACE("Check Output: M1 ad measurement enabled");
       bool expected = GetItemValue<bool>(output_value);
-      int prompt_action =
-          GetItemValueForKey<int>(InputKey::kPromptAction, input);
-      privacy_sandbox_service->PromptActionOccurred(prompt_action);
       EXPECT_EQ(expected, testing_pref_service->GetBoolean(
                               prefs::kPrivacySandboxM1AdMeasurementEnabled));
       return;
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util.h b/components/privacy_sandbox/privacy_sandbox_test_util.h
index b7533ca..e94ffd8c 100644
--- a/components/privacy_sandbox/privacy_sandbox_test_util.h
+++ b/components/privacy_sandbox/privacy_sandbox_test_util.h
@@ -29,7 +29,6 @@
 class PrivacySandboxServiceTestInterface {
  public:
   virtual void TopicsToggleChanged(bool new_value) const = 0;
-  virtual void TopicsConfirmationDecisionMade(bool confirmed) const = 0;
   virtual void SetTopicAllowed(privacy_sandbox::CanonicalTopic topic,
                                bool allowed) = 0;
   virtual bool TopicsHasActiveConsent() const = 0;
@@ -113,9 +112,8 @@
   kAdMeasurementDestinationOrigin = 6,
   kAccessingOrigin = 7,
   kTopicsToggleNewValue = 8,
-  kTopicsConfirmationDecisionConfirmed = 9,
-  kForceChromeBuild = 10,
-  kPromptAction = 11,
+  kForceChromeBuild = 9,
+  kPromptAction = 10,
 };
 
 // Defines the expected output of the functions under test, when the profile is
diff --git a/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc b/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
index 78706dc1..f88d000 100644
--- a/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
+++ b/components/privacy_sandbox/privacy_sandbox_test_util_unittest.cc
@@ -25,7 +25,6 @@
     : public PrivacySandboxServiceTestInterface {
  public:
   MOCK_METHOD(void, TopicsToggleChanged, (bool), (override, const));
-  MOCK_METHOD(void, TopicsConfirmationDecisionMade, (bool), (override, const));
   MOCK_METHOD(void,
               SetTopicAllowed,
               (privacy_sandbox::CanonicalTopic, bool),
@@ -298,15 +297,12 @@
   }
 }
 
-TEST_F(PrivacySandboxTestUtilTest,
-       InputKey_TopicsConfirmationDecisionConfirmed) {
-  std::vector<bool> states = {true, false};
-  for (bool state : states) {
-    testing::Mock::VerifyAndClearExpectations(mock_privacy_sandbox_service());
-    EXPECT_CALL(*mock_privacy_sandbox_service(),
-                TopicsConfirmationDecisionMade(state));
-    ProvideInput(InputKey::kTopicsConfirmationDecisionConfirmed, state);
-  }
+TEST_F(PrivacySandboxTestUtilTest, InputKey_PromptActionOccurred) {
+  constexpr int kArbitraryValue = 7;
+  testing::Mock::VerifyAndClearExpectations(mock_privacy_sandbox_service());
+  EXPECT_CALL(*mock_privacy_sandbox_service(),
+              PromptActionOccurred(kArbitraryValue));
+  ProvideInput(InputKey::kPromptAction, kArbitraryValue);
 }
 
 TEST_F(PrivacySandboxTestUtilTest, OutputKey_IsTopicsAllowedForContext) {
diff --git a/components/privacy_sandbox_strings.grdp b/components/privacy_sandbox_strings.grdp
index 483c027..bd321382 100644
--- a/components/privacy_sandbox_strings.grdp
+++ b/components/privacy_sandbox_strings.grdp
@@ -241,6 +241,39 @@
       Topics footer. Quisque eu auctor purus, id tempus nulla. Pellentesque porta orci purus. Donec dictum, fledge settings, cookie settings, sit amet molestie quam arcu id urna. Donec vulputate dui ut lorem egestas, ac sollicitudin metus fermentum.
   </message>
 
+  <!-- Privacy Sandbox v4 - Topics Consent Details -->
+  <!-- TODO(crbug.com/1378703) - Update and mark translateable. -->
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_STATUS_LABEL" translateable="false">
+    Consent Status:
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TIME_LABEL" translateable="false">
+    Consent Last Update Time:
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_SOURCE_LABEL" translateable="false">
+    Consent Last Update Source:
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_LAST_UPDATE_TEXT_LABEL" translateable="false">
+    Consent Last Update Text:
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_SETTINGS" translateable="false">
+    Chrome Settings
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_DEFAULT" translateable="false">
+    Default Value
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_UPDATE_SOURCE_CONFIRMATION" translateable="false">
+    Blocking Confirmation Moment
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_ACTIVE" translateable="false">
+    Active
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_INACTIVE" translateable="false">
+    Inactive
+  </message>
+  <message name="IDS_PRIVACY_SANDBOX_TOPICS_CONSENT_NOT_REQUIRED" translateable="false">
+    Not Required
+  </message>
+
 
   <!-- Topics API Taxonomy -->
   <!-- These entries have been script generated to ensure consistent mappings. If you are editing these directly, you are likely doing something wrong -->
diff --git a/components/safe_browsing/content/resources/download_file_types.asciipb b/components/safe_browsing/content/resources/download_file_types.asciipb
index 530e246..5abb788 100644
--- a/components/safe_browsing/content/resources/download_file_types.asciipb
+++ b/components/safe_browsing/content/resources/download_file_types.asciipb
@@ -8,7 +8,7 @@
 ##
 ## Top level settings
 ##
-version_id: 57
+version_id: 58
 sampled_ping_probability: 0.01
 max_archived_binaries_to_report: 10
 default_file_type {
@@ -1790,6 +1790,26 @@
     auto_open_hint: DISALLOW_AUTO_OPEN
   }
 }
+file_types {
+  extension: "ftploc"
+  uma_value: 404
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_TYPE_MAC
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: DISALLOW_AUTO_OPEN
+  }
+}
+file_types {
+  extension: "atloc"
+  uma_value: 405
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_TYPE_MAC
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: DISALLOW_AUTO_OPEN
+  }
+}
 
 # VBScript files. May open with Windows Script Host and execute with
 # user privileges.
diff --git a/components/safe_browsing/content/resources/download_file_types_experiment.asciipb b/components/safe_browsing/content/resources/download_file_types_experiment.asciipb
index 6a159788..8e67596 100644
--- a/components/safe_browsing/content/resources/download_file_types_experiment.asciipb
+++ b/components/safe_browsing/content/resources/download_file_types_experiment.asciipb
@@ -12,7 +12,7 @@
 ## version id is larger than the version id in download_file_types.asciipb. If
 ## there isn't an ongoing experiment, this version id is equal to the version id
 ## in download_file_types.asciipb.
-version_id: 57
+version_id: 58
 sampled_ping_probability: 0.01
 max_archived_binaries_to_report: 10
 default_file_type {
@@ -1794,6 +1794,26 @@
     auto_open_hint: DISALLOW_AUTO_OPEN
   }
 }
+file_types {
+  extension: "ftploc"
+  uma_value: 404
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_TYPE_MAC
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: DISALLOW_AUTO_OPEN
+  }
+}
+file_types {
+  extension: "atloc"
+  uma_value: 405
+  ping_setting: FULL_PING
+  platform_settings {
+    platform: PLATFORM_TYPE_MAC
+    danger_level: ALLOW_ON_USER_GESTURE
+    auto_open_hint: DISALLOW_AUTO_OPEN
+  }
+}
 
 # VBScript files. May open with Windows Script Host and execute with
 # user privileges.
diff --git a/components/segmentation_platform/internal/selection/request_dispatcher.h b/components/segmentation_platform/internal/selection/request_dispatcher.h
index 81882a0..c0071e7 100644
--- a/components/segmentation_platform/internal/selection/request_dispatcher.h
+++ b/components/segmentation_platform/internal/selection/request_dispatcher.h
@@ -67,7 +67,8 @@
   std::map<std::string, std::unique_ptr<RequestHandler>> request_handlers_;
 
   // Delegate to provide cached results for all clients, shared among clients.
-  const raw_ptr<CachedResultProvider> cached_result_provider_;
+  const raw_ptr<CachedResultProvider, DanglingUntriaged>
+      cached_result_provider_;
 
   // Storage initialization status.
   absl::optional<bool> storage_init_status_;
diff --git a/components/segmentation_platform/internal/selection/segment_selector_impl.h b/components/segmentation_platform/internal/selection/segment_selector_impl.h
index fe0319a2..9358d4f 100644
--- a/components/segmentation_platform/internal/selection/segment_selector_impl.h
+++ b/components/segmentation_platform/internal/selection/segment_selector_impl.h
@@ -148,7 +148,7 @@
   SegmentSelectionResult selected_segment_last_session_;
 
   // Pointer to the training data collector.
-  raw_ptr<TrainingDataCollector> training_data_collector_{};
+  raw_ptr<TrainingDataCollector, DanglingUntriaged> training_data_collector_{};
 
   base::WeakPtrFactory<SegmentSelectorImpl> weak_ptr_factory_{this};
 };
diff --git a/components/sync/base/features.cc b/components/sync/base/features.cc
index 62bab3b..f9eac4e 100644
--- a/components/sync/base/features.cc
+++ b/components/sync/base/features.cc
@@ -72,6 +72,10 @@
              "SyncTrustedVaultDegradedRecoverabilityHandler",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kSyncTrustedVaultPassphrasePromo,
+             "SyncTrustedVaultPassphrasePromo",
+             base::FEATURE_ENABLED_BY_DEFAULT);
+
 // Keep this entry in sync with the equivalent name in
 // ChromeFeatureList.java.
 BASE_FEATURE(kSyncTrustedVaultVerifyDeviceRegistration,
diff --git a/components/sync/base/features.h b/components/sync/base/features.h
index b7664db..509c47e 100644
--- a/components/sync/base/features.h
+++ b/components/sync/base/features.h
@@ -101,6 +101,10 @@
         "kSyncTrustedVaultShortPeriodDegradedRecoverabilityPolling",
         base::Hours(1)};
 
+// Whether the entry point to opt in to trusted vault in settings should be
+// shown.
+BASE_DECLARE_FEATURE(kSyncTrustedVaultPassphrasePromo);
+
 // Enables logging a UMA metric that requires first communicating with the
 // trusted vault server, in order to verify that the local notion of the device
 // being registered is consistent with the server-side state.
diff --git a/components/sync/driver/sync_service_utils.cc b/components/sync/driver/sync_service_utils.cc
index f714708..c7beccf5 100644
--- a/components/sync/driver/sync_service_utils.cc
+++ b/components/sync/driver/sync_service_utils.cc
@@ -4,8 +4,10 @@
 
 #include "components/sync/driver/sync_service_utils.h"
 
+#include "base/feature_list.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "components/sync/base/features.h"
 #include "components/sync/base/passphrase_enums.h"
 #include "components/sync/driver/sync_service.h"
 #include "components/sync/driver/sync_user_settings.h"
@@ -112,8 +114,11 @@
       // passphrase type to trusted vault is disallowed.
       return false;
     case PassphraseType::kKeystorePassphrase:
-      // Passphrase required should be extremely rare.
-      return !service->GetUserSettings()->IsPassphraseRequired();
+      if (service->GetUserSettings()->IsPassphraseRequired()) {
+        // This should be extremely rare.
+        return false;
+      }
+      return base::FeatureList::IsEnabled(kSyncTrustedVaultPassphrasePromo);
   }
 }
 
diff --git a/components/test/data/payments/alicepay.test/app1/index.html b/components/test/data/payments/alicepay.test/app1/index.html
deleted file mode 100644
index d81ba41..0000000
--- a/components/test/data/payments/alicepay.test/app1/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<!--
-Copyright 2017 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
-    <title>Alice Pay 1</title>
-    <link rel="manifest" href="../app.json">
-  </head>
-  <body>
-    <script src="index.js"></script>
-  </body>
-</html>
diff --git a/components/test/data/payments/alicepay.test/app1/index.js b/components/test/data/payments/alicepay.test/app1/index.js
deleted file mode 100644
index 893c00ad..0000000
--- a/components/test/data/payments/alicepay.test/app1/index.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 The Chromium Authors
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * Prints output.
- * @param {String} src - Where the message is coming from.
- * @param {String} txt - The text to print.
- */
-function output(src, txt) {
-  // Handle DOMException:
-  if (txt.message) {
-    txt = txt.message;
-  }
-  txt = src + ': ' + txt;
-  if (!domAutomationController) {
-    txt += ' window.domAutomationController not found.';
-  } else {
-    domAutomationController.send(txt);
-  }
-  console.warn(txt);
-}
-
-/**
- * Installs a payment app.
- * @param {String} method - The payment method name that this app supports.
- */
-function install(method) {
-  if (!navigator.serviceWorker) {
-    output('install()', 'ServiceWorker API not found.');
-    return;
-  }
-
-  navigator.serviceWorker.getRegistration('app.js')
-      .then((registration) => {
-        if (registration) {
-          output(
-              'serviceWorker.getRegistration()',
-              'The ServiceWorker is already installed.');
-          return;
-        }
-        navigator.serviceWorker.register('app.js')
-            .then(() => {
-              return navigator.serviceWorker.ready;
-            })
-            .then((registration) => {
-              if (!registration.paymentManager) {
-                output(
-                    'serviceWorker.register()',
-                    'PaymentManager API not found.');
-                return;
-              }
-
-              registration.paymentManager.instruments
-                  .set('123456', {name: 'Alice Pay', method: method})
-                  .then(() => {
-                    output(
-                        'instruments.set()',
-                        'Payment app for "' + method + '" method installed.');
-                  })
-                  .catch((error) => {
-                    output('instruments.set()', error);
-                  });
-            })
-            .catch((error) => {
-              output('serviceWorker.register()', error);
-            });
-      })
-      .catch((error) => {
-        output('serviceWorker.getRegistration()', error);
-      });
-}
diff --git a/components/test/data/payments/alicepay.test/app2/index.html b/components/test/data/payments/alicepay.test/app2/index.html
deleted file mode 100644
index bb0b9f0..0000000
--- a/components/test/data/payments/alicepay.test/app2/index.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<!doctype html>
-<!--
-Copyright 2017 The Chromium Authors
-Use of this source code is governed by a BSD-style license that can be
-found in the LICENSE file.
--->
-<html lang="en">
-  <head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
-    <title>Alice Pay 2</title>
-    <link rel="manifest" href="../app.json">
-  </head>
-  <body>
-    <script src="index.js"></script>
-  </body>
-</html>
diff --git a/components/test/data/payments/alicepay.test/app2/index.js b/components/test/data/payments/alicepay.test/app2/index.js
deleted file mode 100644
index 893c00ad..0000000
--- a/components/test/data/payments/alicepay.test/app2/index.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 The Chromium Authors
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * Prints output.
- * @param {String} src - Where the message is coming from.
- * @param {String} txt - The text to print.
- */
-function output(src, txt) {
-  // Handle DOMException:
-  if (txt.message) {
-    txt = txt.message;
-  }
-  txt = src + ': ' + txt;
-  if (!domAutomationController) {
-    txt += ' window.domAutomationController not found.';
-  } else {
-    domAutomationController.send(txt);
-  }
-  console.warn(txt);
-}
-
-/**
- * Installs a payment app.
- * @param {String} method - The payment method name that this app supports.
- */
-function install(method) {
-  if (!navigator.serviceWorker) {
-    output('install()', 'ServiceWorker API not found.');
-    return;
-  }
-
-  navigator.serviceWorker.getRegistration('app.js')
-      .then((registration) => {
-        if (registration) {
-          output(
-              'serviceWorker.getRegistration()',
-              'The ServiceWorker is already installed.');
-          return;
-        }
-        navigator.serviceWorker.register('app.js')
-            .then(() => {
-              return navigator.serviceWorker.ready;
-            })
-            .then((registration) => {
-              if (!registration.paymentManager) {
-                output(
-                    'serviceWorker.register()',
-                    'PaymentManager API not found.');
-                return;
-              }
-
-              registration.paymentManager.instruments
-                  .set('123456', {name: 'Alice Pay', method: method})
-                  .then(() => {
-                    output(
-                        'instruments.set()',
-                        'Payment app for "' + method + '" method installed.');
-                  })
-                  .catch((error) => {
-                    output('instruments.set()', error);
-                  });
-            })
-            .catch((error) => {
-              output('serviceWorker.register()', error);
-            });
-      })
-      .catch((error) => {
-        output('serviceWorker.getRegistration()', error);
-      });
-}
diff --git a/components/test/data/payments/app_store_billing_tests/index.html b/components/test/data/payments/app_store_billing_tests/index.html
index cb1be676..df66c5e 100644
--- a/components/test/data/payments/app_store_billing_tests/index.html
+++ b/components/test/data/payments/app_store_billing_tests/index.html
@@ -5,7 +5,6 @@
     <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
   </head>
   <body>
-    <button onclick="install()">install</button>
     <button onclick="addSupportedMethod('https://play.google.com/billing')">addSupportedMethod('https://play.google.com/billing')</button>
     <button onclick="createPaymentRequest()">create PaymentRequest</button>
     <button onclick="show()">show</button>
diff --git a/components/test/data/payments/app_store_billing_tests/index.js b/components/test/data/payments/app_store_billing_tests/index.js
index 81c4d555..90ea1ff9 100644
--- a/components/test/data/payments/app_store_billing_tests/index.js
+++ b/components/test/data/payments/app_store_billing_tests/index.js
@@ -9,33 +9,6 @@
 let supportedInstruments = [];
 
 /**
- * Install a payment app.
- * @return {string} - a message indicating whether the installation is
- *  successful.
- */
-async function install() {
-  info('installing');
-
-  await navigator.serviceWorker.register('empty_app.js');
-  const registration = await navigator.serviceWorker.ready;
-  if (!registration.paymentManager) {
-    return 'No payment handler capability in this browser. Is' +
-        'chrome://flags/#service-worker-payment-apps enabled?';
-  }
-
-  if (!registration.paymentManager.instruments) {
-    return 'Payment handler is not fully implemented. ' +
-        'Cannot set the instruments.';
-  }
-  await registration.paymentManager.instruments.set('instrument-key', {
-    // Chrome uses name and icon from the web app manifest
-    name: 'MaxPay',
-    method: methodName,
-  });
-  return 'success';
-}
-
-/**
  * Add a payment method to the payment request.
  * @param {string} method - the payment method.
  * @return {string} - a message indicating whether the operation is successful.
diff --git a/components/test/data/payments/bobpay.test/app1/index.html b/components/test/data/payments/bobpay.test/app1/index.html
index c85a8707..9edf87d 100644
--- a/components/test/data/payments/bobpay.test/app1/index.html
+++ b/components/test/data/payments/bobpay.test/app1/index.html
@@ -9,9 +9,5 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
     <title>Bob Pay 1</title>
-    <link rel="manifest" href="../app.json">
   </head>
-  <body>
-    <script src="index.js"></script>
-  </body>
 </html>
diff --git a/components/test/data/payments/bobpay.test/app1/index.js b/components/test/data/payments/bobpay.test/app1/index.js
deleted file mode 100644
index 854aa126..0000000
--- a/components/test/data/payments/bobpay.test/app1/index.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2018 The Chromium Authors
- * Use of this source code is governed by a BSD-style license that can be
- * found in the LICENSE file.
- */
-
-/**
- * Prints output.
- * @param {String} src - Where the message is coming from.
- * @param {String} txt - The text to print.
- */
-function output(src, txt) {
-  // Handle DOMException:
-  if (txt.message) {
-    txt = txt.message;
-  }
-  txt = src + ': ' + txt;
-  if (!domAutomationController) {
-    txt += ' window.domAutomationController not found.';
-  } else {
-    domAutomationController.send(txt);
-  }
-  console.warn(txt);
-}
-
-/**
- * Installs a payment app.
- * @param {String} method - The payment method name that this app supports.
- */
-function install(method) {
-  if (!navigator.serviceWorker) {
-    output('install()', 'ServiceWorker API not found.');
-    return;
-  }
-
-  navigator.serviceWorker.getRegistration('app.js')
-      .then((registration) => {
-        if (registration) {
-          output(
-              'serviceWorker.getRegistration()',
-              'The ServiceWorker is already installed.');
-          return;
-        }
-        navigator.serviceWorker.register('app.js')
-            .then(() => {
-              return navigator.serviceWorker.ready;
-            })
-            .then((registration) => {
-              if (!registration.paymentManager) {
-                output(
-                    'serviceWorker.register()',
-                    'PaymentManager API not found.');
-                return;
-              }
-
-              registration.paymentManager.instruments
-                  .set('123456', {name: 'Bob Pay', method: method})
-                  .then(() => {
-                    output(
-                        'instruments.set()',
-                        'Payment app for "' + method + '" method installed.');
-                  })
-                  .catch((error) => {
-                    output('instruments.set()', error);
-                  });
-            })
-            .catch((error) => {
-              output('serviceWorker.register()', error);
-            });
-      })
-      .catch((error) => {
-        output('serviceWorker.getRegistration()', error);
-      });
-}
diff --git a/components/test/data/payments/enforce_full_delegation.test/index.html b/components/test/data/payments/enforce_full_delegation.test/index.html
index 4b7d4b6..f2f75c3f 100644
--- a/components/test/data/payments/enforce_full_delegation.test/index.html
+++ b/components/test/data/payments/enforce_full_delegation.test/index.html
@@ -8,7 +8,6 @@
   <head>
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
-    <link rel="manifest" href="app_manifest.json">
     <title>Enforce Full Delegation Tests</title>
   </head>
   <style>
@@ -17,8 +16,6 @@
     }
   </style>
   <body>
-    <div><button onclick="install()">install</button>
-      <button onclick="uninstall()">uninstall</button></div>
     <div><button onclick="enableDelegations(['payerName'])">enableDelegations(['payerName'])</button></div>
     <div><button onclick="addSupportedMethod('https://play.google.com/billing')">addSupportedMethod('https://play.google.com/billing')</button>
         <button onclick="addDefaultSupportedMethod()">addDefaultSupportedMethod()</button></div>
diff --git a/components/test/data/payments/enforce_full_delegation.test/index.js b/components/test/data/payments/enforce_full_delegation.test/index.js
index d357b6c..18c2980 100644
--- a/components/test/data/payments/enforce_full_delegation.test/index.js
+++ b/components/test/data/payments/enforce_full_delegation.test/index.js
@@ -12,68 +12,6 @@
 let supportedInstruments = [];
 
 /**
- * Installs the given payment handler with the given payment method.
- * @param {string} method - The payment method that this service worker
- *    supports.
- * @return {Promise<string>} - 'success' or error message on failure.
- */
-async function install(method = METHOD_NAME) {
-  info('installing');
-  try {
-    const registration = await navigator.serviceWorker.register(SW_SRC_URL);
-    await activation(registration);
-    await registration.paymentManager.instruments.set(
-        'instrument-for-' + method, {name: 'Instrument Name', method});
-    return 'success';
-  } catch (e) {
-    return e.message;
-  }
-}
-
-/**
- * Returns a promise that resolves when the service worker of the given
- * registration has activated.
- * @param {ServiceWorkerRegistration} registration - A service worker
- * registration.
- * @return {Promise<void>} - A promise that resolves when the service worker
- * has activated.
- */
-async function activation(registration) {
-  return new Promise((resolve) => {
-    if (registration.active) {
-      resolve();
-      return;
-    }
-    registration.addEventListener('updatefound', () => {
-      const newWorker = registration.installing;
-      if (newWorker.state == 'activated') {
-        resolve();
-        return;
-      }
-      newWorker.addEventListener('statechange', () => {
-        if (newWorker.state == 'activated') {
-          resolve();
-        }
-      });
-    });
-  });
-}
-
-/**
- * Uninstall the payment handler.
- * @return {string} - the message about the uninstallation result.
- */
-async function uninstall() {
-  info('uninstall');
-  let registration = await navigator.serviceWorker.getRegistration(SW_SRC_URL);
-  if (!registration) {
-    return 'The Payment handler has not been installed yet.';
-  }
-  await registration.unregister();
-  return 'success';
-}
-
-/**
  * Delegates handling of the provided options to the payment handler.
  * @param {Array<string>} delegations The list of payment options to delegate.
  * @return {string} The 'success' or error message.
diff --git a/components/test/data/payments/kylepay.test/index.html b/components/test/data/payments/kylepay.test/index.html
index 265b68c..518365e 100644
--- a/components/test/data/payments/kylepay.test/index.html
+++ b/components/test/data/payments/kylepay.test/index.html
@@ -9,7 +9,6 @@
     <meta charset="utf-8">
     <meta name="viewport" content="width=device-width, initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5">
     <title>Kyle Pay</title>
-    <link rel="manifest" href="app.json">
   </head>
   <body>
     <script src="index.js"></script>
diff --git a/components/test/data/payments/kylepay.test/index.js b/components/test/data/payments/kylepay.test/index.js
index b852ec6..7750254 100644
--- a/components/test/data/payments/kylepay.test/index.js
+++ b/components/test/data/payments/kylepay.test/index.js
@@ -5,35 +5,6 @@
  */
 
 /**
- * Installs KylePay payment app.
- * @param {String} method - The payment method name that this app supports.
- * @return {string} The 'success' or error message.
- */
-async function install(method) {
-  try {
-    let registration = await navigator.serviceWorker.getRegistration('app.js');
-    if (registration) {
-      return 'The payment handler is already installed.';
-    }
-    await navigator.serviceWorker.register('app.js');
-    await navigator.serviceWorker.ready;
-    if (!registration.paymentManager) {
-      return 'PaymentManager API not found.';
-    }
-    if (!registration.paymentManager.instruments) {
-      return 'PaymentInstruments API not found.';
-    }
-    await registration.paymentManager.instruments.set('instrument-id', {
-      name: 'Kyle Pay',
-      method,
-    });
-    return enableDelegations();
-  } catch (e) {
-    return e.toString();
-  }
-}
-
-/**
  * Enables the delegations for this payment method.
  * @return {Promise<string>} - Either "success" or an error message.
  */
diff --git a/components/test/data/payments/maxpay.test/installer.js b/components/test/data/payments/maxpay.test/installer.js
index 683859e..3191751 100644
--- a/components/test/data/payments/maxpay.test/installer.js
+++ b/components/test/data/payments/maxpay.test/installer.js
@@ -9,19 +9,6 @@
 let resultPromise;
 
 /**
- * Update the installation status in the widget called 'installationStatus'.
- */
-async function updateStatusView() {
-  const installationStatusViewId = 'installationStatus';
-  const registration = await navigator.serviceWorker.getRegistration(swSrcUrl);
-  if (registration) {
-    document.getElementById(installationStatusViewId).innerText = 'installed';
-  } else {
-    document.getElementById(installationStatusViewId).innerText = 'uninstalled';
-  }
-}
-
-/**
  * Insert a message to the widget called 'log'.
  * @param {string} text - the text that is intended to be inserted into the log.
  */
@@ -31,50 +18,6 @@
 }
 
 /**
- * Installs the payment handler.
- * @return {string} - the message about the installation result.
- */
-async function install() {
-  try {
-    let registration =
-        await navigator.serviceWorker.getRegistration(swSrcUrl);
-    if (registration) {
-      return 'The payment handler is already installed.';
-    }
-
-    await navigator.serviceWorker.register(swSrcUrl);
-    registration = await navigator.serviceWorker.ready;
-    await updateStatusView();
-
-    if (!registration.paymentManager) {
-      return 'PaymentManager API not found.';
-    }
-
-    await registration.paymentManager.instruments.set('instrument-id', {
-      name: 'Instrument Name',
-      method: methodName,
-    });
-    return 'success';
-  } catch (e) {
-    return e.message;
-  }
-}
-
-/**
- * Uninstall the payment handler.
- * @return {string} - the message about the uninstallation result.
- */
-async function uninstall() {
-  let registration = await navigator.serviceWorker.getRegistration(swSrcUrl);
-  if (!registration) {
-    return 'The Payment handler has not been installed yet.';
-  }
-  await registration.unregister();
-  await updateStatusView();
-  return 'Uninstall successfully.';
-}
-
-/**
  * Launches the payment handler and waits until its window is ready.
  * @param {string} url - The URL to open in the payment handler window.
  * @param {string} paymentMethod - The payment method identifier.
@@ -120,5 +63,3 @@
     return e.message;
   }
 }
-
-updateStatusView();
diff --git a/components/test/data/payments/maxpay.test/merchant.html b/components/test/data/payments/maxpay.test/merchant.html
index a8dd4d4..d4463ac7 100644
--- a/components/test/data/payments/maxpay.test/merchant.html
+++ b/components/test/data/payments/maxpay.test/merchant.html
@@ -30,14 +30,6 @@
   </style>
   <body>
     <script>
-      async function onInstallClicked() {
-        const result = await install();
-        updateLogView(result);
-      }
-      async function onUninstallClicked() {
-        const result = await uninstall();
-        updateLogView(result);
-      }
       async function onLaunchClicked(url) {
         const result = await launchAndWaitUntilReady(url);
         updateLogView(result);
@@ -47,13 +39,10 @@
     </script>
     <h1>Use Max Pay</h1>
     <div id="controllers">
-      <button onclick="onInstallClicked()">Install</button>
-      <button onclick="onUninstallClicked()">Uninstall</button>
       <button onclick="onLaunchClicked()">Launch</button>
       <button onclick="onLaunchClicked('http://info.cern.ch')">Launch http app</button>
     </div>
     <div>
-      <div>Installation Status: <span id="installationStatus"></span></div>
       <div>Messages:</div>
       <pre id="log"></pre>
     </div>
diff --git a/components/user_education/webui/help_bubble_webui.h b/components/user_education/webui/help_bubble_webui.h
index d5e04da..3850c272 100644
--- a/components/user_education/webui/help_bubble_webui.h
+++ b/components/user_education/webui/help_bubble_webui.h
@@ -40,7 +40,7 @@
   // HelpBubble:
   void CloseBubbleImpl() override;
 
-  const base::raw_ptr<HelpBubbleHandlerBase> handler_;
+  const base::raw_ptr<HelpBubbleHandlerBase, DanglingUntriaged> handler_;
   const ui::ElementIdentifier anchor_id_;
 };
 
diff --git a/components/webapps/browser/android/android_webapps_strings.grd b/components/webapps/browser/android/android_webapps_strings.grd
index 3f38483..f2abab3 100644
--- a/components/webapps/browser/android/android_webapps_strings.grd
+++ b/components/webapps/browser/android/android_webapps_strings.grd
@@ -185,7 +185,7 @@
       <message name="IDS_MENU_ADD_TO_HOMESCREEN" desc="Menu item for adding a shortcut to the Home screen (default title). [CHAR_LIMIT=27]">
         Add to Home screen
       </message>
-      <message name="IDS_MENU_ADD_TO_HOMESCREEN_INSTALL" desc="Menu item for adding a shortcut to the Home screen. [CHAR_LIMIT=27]">
+      <message name="IDS_MENU_INSTALL_WEBAPP" desc="Menu item for adding a shortcut to the Home screen. [CHAR_LIMIT=27]">
         Install app
       </message>
       <message name="IDS_ADDED_TO_HOMESCREEN" desc="Text in a toast indicating that the website with the specified name was added to the user's Home screen.">
diff --git a/components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_ADD_TO_HOMESCREEN_INSTALL.png.sha1 b/components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_INSTALL_WEBAPP.png.sha1
similarity index 97%
rename from components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_ADD_TO_HOMESCREEN_INSTALL.png.sha1
rename to components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_INSTALL_WEBAPP.png.sha1
index 6351f70..3059504 100644
--- a/components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_ADD_TO_HOMESCREEN_INSTALL.png.sha1
+++ b/components/webapps/browser/android/android_webapps_strings_grd/IDS_MENU_INSTALL_WEBAPP.png.sha1
@@ -1 +1 @@
-87c4d2d4657eb321220e86c45542c29e64fcd91d
\ No newline at end of file
+87c4d2d4657eb321220e86c45542c29e64fcd91d
diff --git a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenDialogViewTest.java b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenDialogViewTest.java
index 008b432..7f0e0747 100644
--- a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenDialogViewTest.java
+++ b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AddToHomescreenDialogViewTest.java
@@ -78,8 +78,8 @@
         AppBannerManager.InstallStringPair installPair = showAddToHomeScreen
                 ? new AppBannerManager.InstallStringPair(
                         R.string.menu_add_to_homescreen, R.string.add)
-                : new AppBannerManager.InstallStringPair(R.string.menu_add_to_homescreen_install,
-                        R.string.menu_add_to_homescreen_install);
+                : new AppBannerManager.InstallStringPair(
+                        R.string.menu_install_webapp, R.string.menu_install_webapp);
         mAddToHomescreenDialogView = new AddToHomescreenDialogView(
                 activity, mModalDialogManager, installPair, new AddToHomescreenViewDelegate() {
                     @Override
diff --git a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AppBannerManager.java b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AppBannerManager.java
index f777658..2d03c9f 100644
--- a/components/webapps/browser/android/java/src/org/chromium/components/webapps/AppBannerManager.java
+++ b/components/webapps/browser/android/java/src/org/chromium/components/webapps/AppBannerManager.java
@@ -40,8 +40,8 @@
         }
     }
 
-    public static final InstallStringPair PWA_PAIR = new InstallStringPair(
-            R.string.menu_add_to_homescreen_install, R.string.app_banner_install);
+    public static final InstallStringPair PWA_PAIR =
+            new InstallStringPair(R.string.menu_install_webapp, R.string.app_banner_install);
     public static final InstallStringPair NON_PWA_PAIR =
             new InstallStringPair(R.string.menu_add_to_homescreen, R.string.add);
 
diff --git a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
index 1f0026d..3d97bc7 100644
--- a/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
+++ b/components/webauthn/android/java/src/org/chromium/components/webauthn/Fido2CredentialRequest.java
@@ -141,7 +141,10 @@
         // discouraged here if the payment extension is present.
         //
         // See https://crbug.com/1393662
-        if (options.isPaymentCredentialCreation) {
+        if (options.isPaymentCredentialCreation
+                && !PaymentFeatureList.isEnabled(
+                        PaymentFeatureList
+                                .ALLOW_DISCOVERABLE_CREDENTIALS_FOR_SECURE_PAYMENT_CONFIRMATION)) {
             // Earlier code should reject an attempt by a developer to use residentKey=required or
             // discouraged on Android - only preferred should have made it this far.
             assert options.authenticatorSelection.residentKey == ResidentKeyRequirement.PREFERRED;
diff --git a/content/browser/direct_sockets/direct_sockets_unittest.cc b/content/browser/direct_sockets/direct_sockets_unittest.cc
deleted file mode 100644
index a7ed2490..0000000
--- a/content/browser/direct_sockets/direct_sockets_unittest.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright 2020 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include <memory>
-
-#include "base/test/scoped_feature_list.h"
-#include "build/build_config.h"
-#include "content/browser/direct_sockets/direct_sockets_service_impl.h"
-#include "content/browser/renderer_host/frame_tree_node.h"
-#include "content/browser/renderer_host/render_frame_host_impl.h"
-#include "content/public/common/content_features.h"
-#include "content/public/common/content_switches.h"
-#include "content/public/test/test_renderer_host.h"
-#include "net/base/ip_address.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "third_party/blink/public/mojom/direct_sockets/direct_sockets.mojom.h"
-
-namespace content {
-
-class DirectSocketsUnitTest : public RenderViewHostTestHarness {
- public:
-  ~DirectSocketsUnitTest() override = default;
-
-  void SetUp() override {
-    RenderViewHostTestHarness::SetUp();
-    SimulateUserActivation();
-  }
-
-  absl::optional<net::IPEndPoint> GetLocalAddr(
-      const blink::mojom::DirectSocketOptions& options) {
-    if (net::IPAddress address;
-        options.local_hostname &&
-        address.AssignFromIPLiteral(*options.local_hostname)) {
-      return net::IPEndPoint{std::move(address), options.local_port};
-    }
-    return {};
-  }
-
- private:
-  void SimulateUserActivation() {
-    static_cast<RenderFrameHostImpl*>(main_rfh())
-        ->UpdateUserActivationState(
-            blink::mojom::UserActivationUpdateType::kNotifyActivation,
-            blink::mojom::UserActivationNotificationType::kTest);
-  }
-
-  base::test::ScopedFeatureList feature_list_;
-};
-
-TEST_F(DirectSocketsUnitTest, PopulateLocalAddr) {
-  blink::mojom::DirectSocketOptions options;
-
-  // Test for default condition.
-  absl::optional<net::IPEndPoint> local_addr = GetLocalAddr(options);
-  EXPECT_EQ(local_addr, absl::nullopt);
-
-  // Test with IPv4 address and default port(0) provided.
-  options.local_hostname = "12.34.56.78";
-  local_addr = GetLocalAddr(options);
-  const uint8_t ipv4[net::IPAddress::kIPv4AddressSize] = {12, 34, 56, 78};
-  EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv4), 0));
-
-  // Test with IPv6 address and default port(0) provided.
-  options.local_hostname = "fedc:ba98:7654:3210:fedc:ba98:7654:3210";
-  local_addr = GetLocalAddr(options);
-  const uint8_t ipv6[net::IPAddress::kIPv6AddressSize] = {
-      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10,
-      0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10};
-  EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv6), 0));
-
-  // Test with IPv6 address and port(12345) provided.
-  options.local_port = 12345;
-  local_addr = GetLocalAddr(options);
-  EXPECT_EQ(local_addr, net::IPEndPoint(net::IPAddress(ipv6), 12345));
-}
-
-}  // namespace content
diff --git a/content/browser/interest_group/ad_auction_service_impl.cc b/content/browser/interest_group/ad_auction_service_impl.cc
index e798fb0..ab254aa 100644
--- a/content/browser/interest_group/ad_auction_service_impl.cc
+++ b/content/browser/interest_group/ad_auction_service_impl.cc
@@ -139,6 +139,7 @@
 // `client_security_state` and  `trusted_url_loader_factory` are used for
 // event-level reports only.
 void SendSuccessfulAuctionReportsAndUpdateInterestGroups(
+    bool* has_sent_reports,
     PrivateAggregationManager* private_aggregation_manager,
     InterestGroupManagerImpl* interest_group_manager,
     const url::Origin& main_frame_origin,
@@ -146,7 +147,7 @@
     const blink::InterestGroupKey& winning_group_key,
     const std::string& winning_group_ad_metadata,
     std::map<url::Origin,
-             std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>>
+             std::vector<auction_worklet::mojom::PrivateAggregationRequestPtr>>*
         private_aggregation_requests,
     const std::vector<GURL>& report_urls,
     const std::vector<GURL>& debug_loss_report_urls,
@@ -156,8 +157,12 @@
     const network::mojom::ClientSecurityStatePtr& client_security_state,
     scoped_refptr<network::WrapperSharedURLLoaderFactory>
         trusted_url_loader_factory) {
+  DCHECK(has_sent_reports);
   DCHECK(interest_group_manager);
   DCHECK(client_security_state);
+  if (*has_sent_reports)
+    return;
+  *has_sent_reports = true;
 
   interest_group_manager->RecordInterestGroupBids(interest_groups_that_bid);
   interest_group_manager->RecordInterestGroupWin(winning_group_key,
@@ -166,10 +171,16 @@
       std::move(k_anon_keys_to_join));
 
   SendPrivateAggregationRequests(private_aggregation_manager, main_frame_origin,
-                                 std::move(private_aggregation_requests));
+                                 std::move(*private_aggregation_requests));
   interest_group_manager->EnqueueReports(
-      report_urls, debug_win_report_urls, debug_loss_report_urls, frame_origin,
-      client_security_state.Clone(), std::move(trusted_url_loader_factory));
+      InterestGroupManagerImpl::ReportType::kSendReportTo, report_urls,
+      frame_origin, *client_security_state, trusted_url_loader_factory);
+  interest_group_manager->EnqueueReports(
+      InterestGroupManagerImpl::ReportType::kDebugWin, debug_win_report_urls,
+      frame_origin, *client_security_state, trusted_url_loader_factory);
+  interest_group_manager->EnqueueReports(
+      InterestGroupManagerImpl::ReportType::kDebugLoss, debug_loss_report_urls,
+      frame_origin, *client_security_state, trusted_url_loader_factory);
 }
 
 }  // namespace
@@ -664,8 +675,8 @@
           AdAuctionResultMetrics::AuctionResult::kFailed);
     }
     GetInterestGroupManager().EnqueueReports(
-        std::vector<GURL>(), std::vector<GURL>(), debug_loss_report_urls,
-        origin(), GetClientSecurityState(),
+        InterestGroupManagerImpl::ReportType::kDebugLoss,
+        debug_loss_report_urls, origin(), *GetClientSecurityState(),
         GetRefCountedTrustedURLLoaderFactory());
     return;
   }
@@ -679,38 +690,12 @@
   DCHECK(urn_uuid.is_valid());
   DCHECK(!interest_groups_that_bid.empty());
 
-  content::AdAuctionData ad_auction_data{winning_group_key->owner,
-                                         winning_group_key->name};
-  FencedFrameURLMapping& fenced_frame_urls_map =
-      GetFrame()->GetPage().fenced_frame_urls_map();
-
-  // Set up reporting for any fenced frame that's navigated to the winning bid's
-  // URL. Use a URLLoaderFactory that will automatically reconnect on network
-  // process crashes, and can outlive the frame.
-  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
-      render_frame_host()
-          .GetStoragePartition()
-          ->GetURLLoaderFactoryForBrowserProcess();
-  scoped_refptr<FencedFrameReporter> fenced_frame_reporter =
-      FencedFrameReporter::CreateForFledge(url_loader_factory);
-
-  blink::FencedFrame::RedactedFencedFrameConfig config =
-      fenced_frame_urls_map.AssignFencedFrameURLAndInterestGroupInfo(
-          urn_uuid, *render_url, std::move(ad_auction_data),
-          reporter->OnNavigateToWinningAdCallback(), ad_component_urls,
-          fenced_frame_reporter);
-  std::move(callback).Run(/*manually_aborted=*/false, std::move(config));
-
-  // Start the InterestGroupAuctionReporter. It will run reporting scripts, but
-  // nothing will be reported (nor the reporter deleted) until a fenced frame
-  // navigates to the winning ad, which will be signalled by invoking the
-  // callback returned by the InterestGroupAuctionReporter's
-  // OnNavitationToWinningAdCallback() method (invoked just above).
   reporters_.emplace_front(std::move(reporter));
   reporters_.front()->Start(base::BindOnce(
       &AdAuctionServiceImpl::OnReporterComplete, base::Unretained(this),
-      reporters_.begin(), std::move(urn_uuid), std::move(*winning_group_key),
-      std::move(winning_group_ad_metadata), std::move(fenced_frame_reporter),
+      reporters_.begin(), std::move(callback), std::move(urn_uuid),
+      std::move(*winning_group_key), std::move(*render_url),
+      std::move(ad_component_urls), std::move(winning_group_ad_metadata),
       std::move(debug_loss_report_urls), std::move(debug_win_report_urls),
       std::move(interest_groups_that_bid), std::move(k_anon_keys_to_join)));
   if (auction_result_metrics) {
@@ -721,10 +706,12 @@
 
 void AdAuctionServiceImpl::OnReporterComplete(
     ReporterList::iterator reporter_it,
+    RunAdAuctionCallback callback,
     GURL urn_uuid,
     blink::InterestGroupKey winning_group_key,
+    GURL render_url,
+    std::vector<GURL> ad_component_urls,
     std::string winning_group_ad_metadata,
-    scoped_refptr<FencedFrameReporter> fenced_frame_reporter,
     std::vector<GURL> debug_loss_report_urls,
     std::vector<GURL> debug_win_report_urls,
     blink::InterestGroupSet interest_groups_that_bid,
@@ -748,22 +735,54 @@
 
   reporters_.erase(reporter_it);
 
-  // TODO(mmenke): Move all reporting logic to the InterestGroupAuctionReporter.
-  // Interest group update logic could remain here or go there as well, but
-  // should be performed as soon as the fenced frame on navigate callback is
-  // invoked, instead of only after reporting - it should also be performed if
-  // the current frame is deleted (e.g., if an iframe runs an auction, passes
-  // the URN to the parent frame, which then deletes the iframe and then
-  // navigates a fenced frame, interest groups should still be updated. We
-  // should run the InterestGroupAuctionReporter as well, but that's potentially
-  // another issue).
-  SendSuccessfulAuctionReportsAndUpdateInterestGroups(
-      private_aggregation_manager_, &GetInterestGroupManager(),
-      main_frame_origin_, origin(), winning_group_key,
-      winning_group_ad_metadata, std::move(private_aggregation_requests),
-      report_urls, debug_win_report_urls, debug_loss_report_urls,
-      interest_groups_that_bid, std::move(k_anon_keys_to_join),
-      GetClientSecurityState(), GetRefCountedTrustedURLLoaderFactory());
+  FencedFrameURLMapping& fenced_frame_urls_map =
+      GetFrame()->GetPage().fenced_frame_urls_map();
+
+  // Need to send reports when the navigation code replaces a winning ad's URN
+  // with its URL, but should only do so once for the results from a given
+  // auction. FencedFrameURLMapping takes a RepeatingCallback, as it can map the
+  // same URN to a URL multiple times. To avoid multiple invocations, pass in a
+  // base::Owned bool, which is set to true by first invocation.
+  //
+  // The callback can also potentially be invoked after the AdAuctionServiceImpl
+  // is destroyed, in a number of cases, such as running an auction in an
+  // iframe, closing the iframe, and then navigating another frame to the URN.
+  // To handle this, the must not dereference `this`, so have to pass everything
+  // the callback needs directly.
+  content::AdAuctionData ad_auction_data{winning_group_key.owner,
+                                         winning_group_key.name};
+
+  // Set up reporting for the fenced frame. Use a URLLoaderFactory that will
+  // automatically reconnect on network process crashes, and can outlive the
+  // frame.
+  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory =
+      render_frame_host()
+          .GetStoragePartition()
+          ->GetURLLoaderFactoryForBrowserProcess();
+  scoped_refptr<FencedFrameReporter> fenced_frame_reporter =
+      FencedFrameReporter::CreateForFledge(url_loader_factory);
+
+  blink::FencedFrame::RedactedFencedFrameConfig config =
+      fenced_frame_urls_map.AssignFencedFrameURLAndInterestGroupInfo(
+          urn_uuid, render_url, std::move(ad_auction_data),
+          base::BindRepeating(
+              &SendSuccessfulAuctionReportsAndUpdateInterestGroups,
+              /*has_sent_reports=*/base::Owned(std::make_unique<bool>(false)),
+              private_aggregation_manager_, &GetInterestGroupManager(),
+              main_frame_origin_, origin(), std::move(winning_group_key),
+              std::move(winning_group_ad_metadata),
+              base::Owned(
+                  std::make_unique<
+                      std::map<url::Origin,
+                               std::vector<auction_worklet::mojom::
+                                               PrivateAggregationRequestPtr>>>(
+                      std::move(private_aggregation_requests))),
+              std::move(report_urls), std::move(debug_win_report_urls),
+              std::move(debug_loss_report_urls),
+              std::move(interest_groups_that_bid),
+              std::move(k_anon_keys_to_join), GetClientSecurityState(),
+              GetRefCountedTrustedURLLoaderFactory()),
+          ad_component_urls, fenced_frame_reporter);
 
   // Pass reporting map to the FencedFrameReporter.
   // TODO(mmenke): move this into InterestGroupReporter.
@@ -774,6 +793,8 @@
     fenced_frame_reporter->OnUrlMappingReady(
         destination, std::move(ad_beacon_map.metadata[destination]));
   }
+
+  std::move(callback).Run(/*manually_aborted=*/false, std::move(config));
 }
 
 void AdAuctionServiceImpl::MaybeLogPrivateAggregationFeature(
diff --git a/content/browser/interest_group/ad_auction_service_impl.h b/content/browser/interest_group/ad_auction_service_impl.h
index 0fe07cfb..17fe893 100644
--- a/content/browser/interest_group/ad_auction_service_impl.h
+++ b/content/browser/interest_group/ad_auction_service_impl.h
@@ -12,8 +12,6 @@
 
 #include "base/containers/unique_ptr_adapters.h"
 #include "base/memory/raw_ptr.h"
-#include "base/memory/ref_counted.h"
-#include "content/browser/fenced_frame/fenced_frame_reporter.h"
 #include "content/browser/fenced_frame/fenced_frame_url_mapping.h"
 #include "content/browser/interest_group/auction_runner.h"
 #include "content/browser/interest_group/auction_worklet_manager.h"
@@ -139,16 +137,17 @@
       std::vector<std::string> errors,
       std::unique_ptr<InterestGroupAuctionReporter> reporter);
 
-  void OnReporterComplete(
-      ReporterList::iterator reporter_it,
-      GURL urn_uuid,
-      blink::InterestGroupKey winning_group_key,
-      std::string winning_group_ad_metadata,
-      scoped_refptr<FencedFrameReporter> fenced_frame_reporter,
-      std::vector<GURL> debug_loss_report_urls,
-      std::vector<GURL> debug_win_report_urls,
-      blink::InterestGroupSet interest_groups_that_bid,
-      base::flat_set<std::string> k_anon_keys_to_join);
+  void OnReporterComplete(ReporterList::iterator reporter_it,
+                          RunAdAuctionCallback callback,
+                          GURL urn_uuid,
+                          blink::InterestGroupKey winning_group_key,
+                          GURL render_url,
+                          std::vector<GURL> ad_component_urls,
+                          std::string winning_group_ad_metadata,
+                          std::vector<GURL> debug_loss_report_urls,
+                          std::vector<GURL> debug_win_report_urls,
+                          blink::InterestGroupSet interest_groups_that_bid,
+                          base::flat_set<std::string> k_anon_keys_to_join);
 
   // Calls LogWebFeatureForCurrentPage() for the frame to inform it of FLEDGE
   // private aggregation API usage, if `private_aggregation_requests` is
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
index fb00722..0ef3326 100644
--- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc
+++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -210,47 +210,35 @@
     report_map_[url_path] = response;
   }
 
-  // Registers a URL to use a "deferred" script response. For a deferred
+  // Registers a URL to use a "deferred" update response. For a deferred
   // response, the request handler returns true without a write, and writes are
-  // performed later in DoDeferred[Script|Update]Write() using a "stolen" Mojo
-  // pipe to the URLLoaderClient.
+  // performed later in DoDeferredWrite() using a "stolen" Mojo pipe to the
+  // URLLoaderClient.
   //
   // It is valid to have a "deferred" response that never completes before the
   // test exits.
-  void RegisterDeferredScriptResponse(const std::string& url_path) {
-    RegisterDeferredResponse(url_path, /*is_update=*/false);
-  }
-
-  // Just like RegisterDeferredResponse(), but for deferred update responses.
   void RegisterDeferredUpdateResponse(const std::string& url_path) {
-    RegisterDeferredResponse(url_path, /*is_update=*/true);
-  }
-
-  // Checks if there's a deferred response (of any type) for `url_path`.
-  bool HasPendingResponse(const std::string& url_path) const {
     base::AutoLock auto_lock(lock_);
-    auto it = deferred_responses_map_.find(url_path);
-    CHECK(it != deferred_responses_map_.end());
-    return it->second.url_loader_client.is_bound() &&
-           it->second.url_loader_client.is_connected();
+    CHECK(
+        deferred_update_responses_map_
+            .emplace(url_path, mojo::Remote<network::mojom::URLLoaderClient>())
+            .second);
   }
 
-  // Perform the deferred response for `url_path`, using response headers
-  // associated with scripts -- the test fails if the client isn't waiting on
-  // `url_path` registered with RegisterDeferredResponse().
-  void DoDeferredScriptResponse(const std::string& url_path,
-                                const std::string& response) {
-    DoDeferredResponse(url_path, response, kFledgeScriptHeaders,
-                       /*expected_is_update=*/false);
-  }
-
-  // Perform the deferred response for `url_path`, using response headers
-  // associated with updates -- the test fails if the client isn't waiting on
-  // `url_path` registered with RegisterDeferredResponse().
+  // Perform the deferred response for `url_path` -- the test fails if the
+  // client isn't waiting on `url_path` registered with
+  // RegisterDeferredUpdateResponse().
   void DoDeferredUpdateResponse(const std::string& url_path,
                                 const std::string& response) {
-    DoDeferredResponse(url_path, response, kFledgeScriptHeaders,
-                       /*expected_is_update=*/true);
+    base::AutoLock auto_lock(lock_);
+    auto it = deferred_update_responses_map_.find(url_path);
+    CHECK(it != deferred_update_responses_map_.end());
+    mojo::Remote<network::mojom::URLLoaderClient>& url_loader_client =
+        it->second;
+    CHECK(url_loader_client.is_bound());
+    URLLoaderInterceptor::WriteResponse(kFledgeUpdateHeaders, response,
+                                        url_loader_client.get());
+    deferred_update_responses_map_.erase(it);
   }
 
   // Registers a URL that, when seen, will have its URLLoaderClient stored in
@@ -337,18 +325,6 @@
   bool RequestHandler(URLLoaderInterceptor::RequestParams* params) {
     base::AutoLock auto_lock(lock_);
 
-    // Check deferred responses map first.
-    const auto deferred_it =
-        deferred_responses_map_.find(params->url_request.url.path());
-    if (deferred_it != deferred_responses_map_.end()) {
-      CHECK(!deferred_it->second.url_loader_client);
-      deferred_it->second.url_loader_client = std::move(params->client);
-      if (deferred_it->second.is_update) {
-        OnUpdateRequestReceived(params);
-      }
-      return true;
-    }
-
     // Cross-origin iframe handling is covered by integration tests, for cases
     // that request .well-known URLs.
     if (params->url_request.url.path_piece() ==
@@ -393,7 +369,11 @@
 
     // Not a non-update error, script request, or report request, so consider
     // this an update request.
-    OnUpdateRequestReceived(params);
+    update_count_++;
+    EXPECT_TRUE(params->url_request.trusted_params);
+    EXPECT_TRUE(params->url_request.trusted_params->isolation_info
+                    .network_isolation_key()
+                    .IsTransient());
     const auto update_it =
         json_update_map_.find(params->url_request.url.path());
     if (update_it != json_update_map_.end()) {
@@ -402,6 +382,14 @@
       return true;
     }
 
+    const auto deferred_update_it =
+        deferred_update_responses_map_.find(params->url_request.url.path());
+    if (deferred_update_it != deferred_update_responses_map_.end()) {
+      CHECK(!deferred_update_it->second);
+      deferred_update_it->second = std::move(params->client);
+      return true;
+    }
+
     if (params->url_request.url.path() == update_error_path_) {
       CHECK(update_error_ != net::OK);
       params->client->OnComplete(
@@ -425,41 +413,6 @@
       std::move(quit_report_wait_loop_callback_).Run();
   }
 
-  void OnUpdateRequestReceived(URLLoaderInterceptor::RequestParams* params)
-      EXCLUSIVE_LOCKS_REQUIRED(lock_) {
-    update_count_++;
-    EXPECT_TRUE(params->url_request.trusted_params);
-    EXPECT_TRUE(params->url_request.trusted_params->isolation_info
-                    .network_isolation_key()
-                    .IsTransient());
-  }
-
-  void RegisterDeferredResponse(const std::string& url_path, bool is_update) {
-    base::AutoLock auto_lock(lock_);
-    CHECK(deferred_responses_map_
-              .emplace(url_path,
-                       DeferredResponseInfo{
-                           mojo::Remote<network::mojom::URLLoaderClient>(),
-                           is_update})
-              .second);
-  }
-
-  void DoDeferredResponse(const std::string& url_path,
-                          const std::string& response,
-                          const std::string headers,
-                          bool expected_is_update) {
-    base::AutoLock auto_lock(lock_);
-    auto it = deferred_responses_map_.find(url_path);
-    CHECK(it != deferred_responses_map_.end());
-    EXPECT_EQ(expected_is_update, it->second.is_update);
-    mojo::Remote<network::mojom::URLLoaderClient>& url_loader_client =
-        it->second.url_loader_client;
-    CHECK(url_loader_client.is_bound());
-    URLLoaderInterceptor::WriteResponse(headers, response,
-                                        url_loader_client.get());
-    deferred_responses_map_.erase(it);
-  }
-
   // Handles network requests for interest group updates and scripts.
   URLLoaderInterceptor network_interceptor_{
       base::BindRepeating(&NetworkResponder::RequestHandler,
@@ -482,14 +435,9 @@
   // Only saves reporting requests that auctually received responses.
   std::vector<std::string> sent_reports_ GUARDED_BY(lock_);
 
-  struct DeferredResponseInfo {
-    mojo::Remote<network::mojom::URLLoaderClient> url_loader_client;
-    bool is_update = false;
-  };
-
-  // Stores the set of URL paths that will receive a deferred response.
+  // Stores the set of URL paths that will receive deferred updates.
   //
-  // First, a URL path is registered to defer the response, but the mapped value
+  // First, a URL path is registered to receive an update, but the mapped value
   // will not be bound.
   //
   // Next, once a request is made for that URL path, the
@@ -501,8 +449,8 @@
   //
   // It is valid to have a "deferred" response that never completes before the
   // test exits.
-  base::flat_map<std::string, DeferredResponseInfo> deferred_responses_map_
-      GUARDED_BY(lock_);
+  base::flat_map<std::string, mojo::Remote<network::mojom::URLLoaderClient>>
+      deferred_update_responses_map_ GUARDED_BY(lock_);
 
   // Stores the last URL path that was registered with
   // RegisterStoreUrlLoaderClient().
@@ -4781,6 +4729,54 @@
   EXPECT_EQ(base::Seconds(15), base::Time::Now() - start_time);
 }
 
+// Check that reports are sent (And there's no UAF when invoking the URN
+// callback) if the AdAuctionService is deleted before a URN is navigated to.
+//
+// This isn't a common case, but can happen if an auction runs in an iframe,
+// which is then closed, and then the URN is loaded in a fenced frame.
+//
+// It can also potentially happen when navigating away from a page that run an
+// auction is racing against loading a URN in a frame within the page.
+//
+// It can also happen if a compromised renderer closes the Mojo pipe to its
+// AdAuctionService.
+TEST_F(AdAuctionServiceImplTest, ReportsSentAfterServiceDestruction) {
+  network_responder_->RegisterScriptResponse(kBiddingUrlPath,
+                                             BasicBiddingReportScript());
+  network_responder_->RegisterScriptResponse(kDecisionUrlPath,
+                                             BasicSellerReportScript());
+  network_responder_->RegisterReportResponse("/report_bidder", /*response=*/"");
+  network_responder_->RegisterReportResponse("/report_seller", /*response=*/"");
+
+  blink::InterestGroup interest_group = CreateInterestGroup();
+  interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
+  interest_group.ads.emplace();
+  blink::InterestGroup::Ad ad(
+      /*render_url=*/GURL("https://example.com/render"),
+      /*metadata=*/absl::nullopt);
+  interest_group.ads->emplace_back(std::move(ad));
+  JoinInterestGroupAndFlush(interest_group);
+  EXPECT_EQ(1, GetJoinCount(kOriginA, kInterestGroupName));
+
+  blink::AuctionConfig auction_config;
+  auction_config.seller = kOriginA;
+  auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
+  auction_config.non_shared_params.interest_group_buyers = {kOriginA};
+  absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
+  ASSERT_NE(auction_result, absl::nullopt);
+
+  // Destroy the auction service Mojo pipe, and wait for the underlying service
+  // to be destroyed.
+  DestroyAdAuctionService();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_EQ(network_responder_->ReportCount(), 0u);
+
+  // Invoking the callback should not crash and should result in two reports
+  // being sent.
+  InvokeCallbackForURN(*auction_result);
+  network_responder_->WaitForNumReports(2);
+}
+
 // Similar to SendReports() above, but with one report request failed instead of
 // timed out. Following report requests should still be send after previous ones
 // failed.
@@ -4898,10 +4894,6 @@
     absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
     ASSERT_NE(auction_result, absl::nullopt);
     InvokeCallbackForURN(*auction_result);
-    // Wait for the reporting scripts to complete and reporting URLs to be
-    // requested. Need to do this for each auction to make sure reporting
-    // scripts complete and requests are made in a consistent order.
-    task_environment()->RunUntilIdle();
   }
 
   // There should be one report sent already, since there's no delay for the
@@ -4954,9 +4946,6 @@
   absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
   ASSERT_NE(auction_result, absl::nullopt);
   InvokeCallbackForURN(*auction_result);
-  // Wait for the reporting scripts to complete and all reporting URLs to be
-  // requested.
-  task_environment()->RunUntilIdle();
 
   // Wait for the seller report to be sent.
   network_responder_->WaitForNumReports(1);
@@ -4971,9 +4960,6 @@
   auction_result = RunAdAuctionAndFlush(auction_config2);
   ASSERT_NE(auction_result, absl::nullopt);
   InvokeCallbackForURN(*auction_result);
-  // Wait for the reporting scripts to complete and all reporting URLs to be
-  // requested.
-  task_environment()->RunUntilIdle();
   // Two more reports are enqueued.
   EXPECT_EQ(manager_->report_queue_length_for_testing(), 3u);
 
@@ -4997,91 +4983,12 @@
   auction_result = RunAdAuctionAndFlush(auction_config3);
   ASSERT_NE(auction_result, absl::nullopt);
   InvokeCallbackForURN(*auction_result);
-  // Wait for the reporting scripts to complete and all reporting URLs to be
-  // requested.
-  task_environment()->RunUntilIdle();
 
   task_environment()->FastForwardBy(base::Seconds(20));
   // Two more reports from the third auction are sent.
   EXPECT_EQ(network_responder_->ReportCount(), 3u);
 }
 
-// Check that running reporting worklets doesn't block auction completion. To do
-// this, the bidding script is set to be deferred. The auction is started, and
-// the bid script is supplied. Then the auction completes. This should trigger
-// reloading the bidding script to call reportWin(). The second time, a bidding
-// script is not supplied. The fact that the auction completes despite the
-// second stalled load verifies that running reporting scripts does not block
-// completion of an auction. The AdAuctionServiceImpl is destroyed before
-// the bidding URL is downloaded the second time, which provides some test
-// coverage of that as well.
-TEST_F(AdAuctionServiceImplTest, ReportingWorkletsDoNotBlockCompletion) {
-  network_responder_->RegisterDeferredScriptResponse(kBiddingUrlPath);
-  network_responder_->RegisterScriptResponse(kDecisionUrlPath,
-                                             BasicSellerReportScript());
-  network_responder_->RegisterReportResponse("/report_bidder", /*response=*/"");
-  network_responder_->RegisterReportResponse("/report_seller", /*response=*/"");
-
-  blink::InterestGroup interest_group = CreateInterestGroup();
-  interest_group.bidding_url = kUrlA.Resolve(kBiddingUrlPath);
-  interest_group.ads.emplace();
-  blink::InterestGroup::Ad ad(
-      /*render_url=*/GURL("https://example.com/render"),
-      /*metadata=*/absl::nullopt);
-  interest_group.ads->emplace_back(std::move(ad));
-
-  JoinInterestGroupAndFlush(interest_group);
-  EXPECT_EQ(1, GetJoinCount(kOriginA, kInterestGroupName));
-
-  blink::AuctionConfig auction_config;
-  auction_config.seller = kOriginA;
-  auction_config.decision_logic_url = kUrlA.Resolve(kDecisionUrlPath);
-  auction_config.non_shared_params.interest_group_buyers = {kOriginA};
-
-  AdAuctionServiceImpl::CreateMojoService(
-      main_rfh(), ad_auction_service_.BindNewPipeAndPassReceiver());
-
-  // Start the auction.
-  base::RunLoop run_loop;
-  absl::optional<blink::FencedFrame::RedactedFencedFrameConfig> maybe_config;
-  ad_auction_service_->RunAdAuction(
-      auction_config, mojo::NullReceiver(),
-      base::BindLambdaForTesting(
-          [&run_loop, &maybe_config](
-              bool manually_aborted,
-              const absl::optional<
-                  blink::FencedFrame::RedactedFencedFrameConfig>& config) {
-            EXPECT_FALSE(manually_aborted);
-            maybe_config = config;
-            run_loop.Quit();
-          }));
-
-  // Wait for the NetworkResponder to see the request for the bidding URL, and
-  // response with the bidding script.
-  task_environment()->RunUntilIdle();
-  EXPECT_FALSE(run_loop.AnyQuitCalled());
-  network_responder_->DoDeferredScriptResponse(kBiddingUrlPath,
-                                               BasicBiddingReportScript());
-  // Register another deferred response for when the bidding URL is requested
-  // again to run the reporting script.
-  network_responder_->RegisterDeferredScriptResponse(kBiddingUrlPath);
-
-  // Complete the auction. It should have a winning ad.
-  run_loop.Run();
-  ASSERT_TRUE(maybe_config);
-  EXPECT_TRUE(maybe_config->urn_uuid().has_value());
-
-  // Running until idle should result in the NetworkResponder receiving a
-  // request for the bidding URL, to run the reporting script.
-  task_environment()->RunUntilIdle();
-  EXPECT_TRUE(network_responder_->HasPendingResponse(kBiddingUrlPath));
-
-  // Destroy the auction service Mojo pipe, and wait for the underlying service
-  // to be destroyed, which should not cause a crash.
-  DestroyAdAuctionService();
-  base::RunLoop().RunUntilIdle();
-}
-
 // Run several auctions, some of which have a winner, and some of which do
 // not. Verify that the auction result UMA is recorded correctly.
 TEST_F(AdAuctionServiceImplTest,
@@ -6098,9 +6005,6 @@
     absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
     ASSERT_NE(auction_result, absl::nullopt);
     InvokeCallbackForURN(*auction_result);
-    // Wait for the reporting scripts to complete and reporting URLs to be
-    // requested, to ensure requests are made in a consistent order.
-    task_environment()->RunUntilIdle();
   }
 
   task_environment()->FastForwardBy(base::Seconds(3));
@@ -6458,9 +6362,6 @@
   absl::optional<GURL> auction_result = RunAdAuctionAndFlush(auction_config);
   ASSERT_NE(auction_result, absl::nullopt);
   InvokeCallbackForURN(*auction_result);
-  // Wait for reporting to complete - aggregate API usage is only logged if
-  // aggregation reports are sent.
-  task_environment()->RunUntilIdle();
 }
 
 // TODO(crbug.com/1356654): Update when use counter coverage is improved.
diff --git a/content/browser/interest_group/auction_runner_unittest.cc b/content/browser/interest_group/auction_runner_unittest.cc
index e8cc5a3..7a1a3a1 100644
--- a/content/browser/interest_group/auction_runner_unittest.cc
+++ b/content/browser/interest_group/auction_runner_unittest.cc
@@ -2045,8 +2045,6 @@
 
     reporter_->Start(base::BindOnce(&AuctionRunnerTest::OnReportingComplete,
                                     base::Unretained(this)));
-    // Invoke callback immediately, so as not to block reporter completion.
-    reporter_->OnNavigateToWinningAdCallback().Run();
   }
 
   void OnReportingComplete() {
diff --git a/content/browser/interest_group/interest_group_auction_reporter.cc b/content/browser/interest_group/interest_group_auction_reporter.cc
index bd9d29d..3214096 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.cc
+++ b/content/browser/interest_group/interest_group_auction_reporter.cc
@@ -91,13 +91,6 @@
                        /*top_seller_signals=*/absl::nullopt);
 }
 
-base::RepeatingClosure
-InterestGroupAuctionReporter::OnNavigateToWinningAdCallback() {
-  return base::BindRepeating(
-      &InterestGroupAuctionReporter::OnNavigateToWinningAd,
-      weak_ptr_factory_.GetWeakPtr());
-}
-
 void InterestGroupAuctionReporter::RequestSellerWorklet(
     const SellerWinningBidInfo* seller_info,
     const absl::optional<std::string>& top_seller_signals) {
@@ -447,23 +440,7 @@
   TRACE_EVENT_NESTABLE_ASYNC_END0("fledge", "auction",
                                   top_level_seller_winning_bid_info_.trace_id);
   errors_.insert(errors_.end(), errors.begin(), errors.end());
-  reporting_complete_ = true;
-  MaybeInvokeCallback();
-}
-
-void InterestGroupAuctionReporter::OnNavigateToWinningAd() {
-  if (navigated_to_winning_ad_) {
-    return;
-  }
-  navigated_to_winning_ad_ = true;
-  MaybeInvokeCallback();
-}
-
-void InterestGroupAuctionReporter::MaybeInvokeCallback() {
-  DCHECK(callback_);
-  if (reporting_complete_ && navigated_to_winning_ad_) {
-    std::move(callback_).Run();
-  }
+  std::move(callback_).Run();
 }
 
 const InterestGroupAuctionReporter::SellerWinningBidInfo&
diff --git a/content/browser/interest_group/interest_group_auction_reporter.h b/content/browser/interest_group/interest_group_auction_reporter.h
index 485192a2..4a80112 100644
--- a/content/browser/interest_group/interest_group_auction_reporter.h
+++ b/content/browser/interest_group/interest_group_auction_reporter.h
@@ -125,18 +125,8 @@
   InterestGroupAuctionReporter& operator=(const InterestGroupAuctionReporter&) =
       delete;
 
-  // Starts running reporting scripts. `callback` will be invoked once all
-  // reporting scripts have completed, and the callback returned by
-  // OnNavigateToWinningAdCallback() has been invoked, at which point reports
-  // should be sent, and the reporter can be destroyed.
   void Start(base::OnceClosure callback);
 
-  // Returns a callback that should be invoked once a fenced frame has been
-  // navigated to the winning ad. May be invoked multiple times, safe to invoke
-  // after destruction. `this` will not invoke the callback passed to Start()
-  // until the callback this method returns has been invoked at least once.
-  base::RepeatingClosure OnNavigateToWinningAdCallback();
-
   // Accessors so the owner can pass along the results of the auction.
   //
   // TODO(mmenke): Remove these, and make the reporter use them itself (or maybe
@@ -209,19 +199,10 @@
       PrivateAggregationRequests pa_requests,
       const std::vector<std::string>& errors);
 
-  // Sets `reporting_complete_` to true an invokes MaybeCompleteCallback().
+  // Invokes `callback_`.
   void OnReportingComplete(
       const std::vector<std::string>& errors = std::vector<std::string>());
 
-  // Invoked when the winning ad has been navigated to. If
-  // `navigated_to_winning_ad_` is false, sets it to true and invokes
-  // MaybeInvokeCallback(). Otherwise, does nothing.
-  void OnNavigateToWinningAd();
-
-  // Invokes callback passed in to Start() if both OnReportingComplete() and
-  // OnNavigateToWinningAd() have been invoked.
-  void MaybeInvokeCallback();
-
   // Retrieves the SellerWinningBidInfo of the auction the bidder was
   // participating in - i.e., for the component auction, if the bidder was in a
   // component auction, and for the top level auction, otherwise.
@@ -265,9 +246,6 @@
 
   std::vector<GURL> report_urls_;
 
-  bool reporting_complete_ = false;
-  bool navigated_to_winning_ad_ = false;
-
   base::WeakPtrFactory<InterestGroupAuctionReporter> weak_ptr_factory_{this};
 };
 
diff --git a/content/browser/interest_group/interest_group_browsertest.cc b/content/browser/interest_group/interest_group_browsertest.cc
index bcee1de..bed9247 100644
--- a/content/browser/interest_group/interest_group_browsertest.cc
+++ b/content/browser/interest_group/interest_group_browsertest.cc
@@ -444,37 +444,29 @@
       InterestGroupManagerImpl::InterestGroupObserverInterface::AccessType,
       std::string,
       std::string>;
-
   void OnInterestGroupAccessed(
       const base::Time& access_time,
       InterestGroupManagerImpl::InterestGroupObserverInterface::AccessType type,
       const std::string& owner_origin,
       const std::string& name) override {
-    accesses_.emplace_back(type, owner_origin, name);
+    accesses.emplace_back(Entry{type, owner_origin, name});
 
-    if (run_loop_ && accesses_.size() >= expected_.size()) {
-      run_loop_->Quit();
+    if (run_loop_.running() && accesses.size() >= expected_.size()) {
+      run_loop_.Quit();
     }
   }
-
   void WaitForAccesses(const std::vector<Entry>& expected) {
-    DCHECK(!run_loop_);
-    if (accesses_.size() < expected.size()) {
-      run_loop_ = std::make_unique<base::RunLoop>();
+    if (accesses.size() < expected.size()) {
       expected_ = expected;
-      run_loop_->Run();
-      run_loop_.reset();
+      run_loop_.Run();
     }
-    EXPECT_EQ(expected, accesses_);
-
-    // Clear accesses so can be reused.
-    accesses_.clear();
+    EXPECT_EQ(expected, accesses);
   }
+  std::vector<Entry> accesses;
 
  private:
-  std::vector<Entry> accesses_;
   std::vector<Entry> expected_;
-  std::unique_ptr<base::RunLoop> run_loop_;
+  base::RunLoop run_loop_;
 };
 
 class InterestGroupBrowserTest : public ContentBrowserTest {
@@ -5023,7 +5015,7 @@
 
   AttachInterestGroupObserver();
   GURL ad_url = https_server_->GetURL(
-      "b.test", "/set-header?Supports-Loading-Mode: fenced-frame");
+      "a.test", "/fenced_frames/ad_that_leaves_interest_group.html");
   EXPECT_EQ(
       kSuccess,
       JoinInterestGroupAndVerify(
@@ -5044,7 +5036,7 @@
           rfh1));
 
   GURL ad_url2 = https_server_->GetURL(
-      "a.test", "/set-header?Supports-Loading-Mode: fenced-frame");
+      "b.test", "/fenced_frames/ad_that_leaves_interest_group.html");
   EXPECT_EQ(
       kSuccess,
       JoinInterestGroupAndVerify(
@@ -5075,23 +5067,10 @@
           https_server_->GetURL("a.test", "/interest_group/decision_logic.js")),
       rfh1));
 
-  // InterestGroupAccessObserver should see the join and auction.
-  WaitForAccessObserved({
-      {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"},
-      {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "trucks"},
-      {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"},
-      {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"},
-      {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"},
-      {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"},
-      {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"},
-  });
-
-  // Try to leave the winning interest group, which should fail, since the ad is
-  // on b.test, but the IG owner is a.test. Do the failed leave case first so
-  // that subsequent WaitForAccessObserved() calls would likely catch an
-  // unexpected leave event.
-  EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh1),
-                            "navigator.leaveAdInterestGroup()"));
+  // Wait for leave to be committed to the database.
+  while (GetJoinCount(test_origin, "cars") > 0) {
+    base::RunLoop().RunUntilIdle();
+  }
 
   ASSERT_NO_FATAL_FAILURE(RunAuctionAndNavigateFencedFrame(
       ad_url2,
@@ -5108,32 +5087,30 @@
           https_server_->GetURL("a.test", "/interest_group/decision_logic.js")),
       rfh2));
 
-  // For the second auction, InterestGroupAccessObserver should see the two
-  // groups loaded, but just the truck group win. Do this before the leave
-  // attempt, as updating the data is potentially racy with the navigation
-  // committing, so the leave event could appear out of order.
+  // InterestGroupAccessObserver should see the join, auction, and implicit
+  // leave. Note that the implicit leave for "trucks" does not succeed because
+  // leaveAdInterestGroup is not called from the Interest Group owner's frame.
   WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"},
+      {{InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kJoin, test_origin.Serialize(), "trucks"},
+       {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"},
        {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"},
+       {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "trucks"},
        {InterestGroupTestObserver::kBid, test_origin.Serialize(), "trucks"},
        {InterestGroupTestObserver::kWin, test_origin.Serialize(), "trucks"}});
 
-  // Try to leave the winning interest group, which should succeed this time. Do
-  // it by calling Javascript directly instead of loading a page that does this
-  // to avoid races with logging kBin or kWin.
-  EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(rfh2),
-                            "navigator.leaveAdInterestGroup()"));
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLeave, test_origin.Serialize(), "trucks"}});
-
-  // Only the "truck" interest group should have been left.
+  // The ad should have left the "cars" interest group when the page was shown.
   auto groups = GetAllInterestGroups();
   ASSERT_EQ(1u, groups.size());
-  EXPECT_EQ("cars", groups[0].name);
+  EXPECT_EQ("trucks", groups[0].name);
 }
 
 // Runs ad auction with fenced frames enabled. The auction should succeed and
-// be loaded in a fenced frame. The displayed ad leaves the interest group
+// be loaded in a fenced frames. The displayed ad leaves the interest group
 // from a nested iframe.
 //
 // TODO(crbug.com/1320438): Re-enable the test.
@@ -5148,7 +5125,7 @@
 
   AttachInterestGroupObserver();
   GURL inner_url = https_server_->GetURL(
-      "a.test", "/set-header?Supports-Loading-Mode: fenced-frame");
+      "a.test", "/fenced_frames/ad_that_leaves_interest_group.html");
   GURL ad_url = https_server_->GetURL(
       "b.test", "/fenced_frames/outer_inner_frame_as_param.html");
   GURL::Replacements rep;
@@ -5185,22 +5162,14 @@
                   https_server_->GetURL("a.test",
                                         "/interest_group/decision_logic.js"))));
 
-  // InterestGroupAccessObserver should see the join and auction.
+  // InterestGroupAccessObserver should see the join, auction, and implicit
+  // leave.
   WaitForAccessObserved(
       {{InterestGroupTestObserver::kJoin, test_origin.Serialize(), "cars"},
        {InterestGroupTestObserver::kLoaded, test_origin.Serialize(), "cars"},
        {InterestGroupTestObserver::kBid, test_origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"}});
-
-  // Leave the interest group and wait to observe the event. Do this after the
-  // above WaitForAccessObserved() call, as leaving is racy with recording the
-  // result of an auction.
-  EXPECT_EQ(nullptr, EvalJs(GetFencedFrameRenderFrameHost(web_contents())
-                                ->child_at(0)
-                                ->current_frame_host(),
-                            "navigator.leaveAdInterestGroup()"));
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"}});
+       {InterestGroupTestObserver::kWin, test_origin.Serialize(), "cars"},
+       {InterestGroupTestObserver::kLeave, test_origin.Serialize(), "cars"}});
 
   // The ad should have left the interest group when the page was shown.
   EXPECT_EQ(0u, GetAllInterestGroups().size());
@@ -6020,9 +5989,6 @@
   EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count,
             0);
 
-  // Start observer after joins.
-  AttachInterestGroupObserver();
-
   std::string auction_config = JsReplace(
       R"({
     seller: $1,
@@ -6034,22 +6000,10 @@
       origin);
   // Run an ad auction. Interest group cars of owner `test_url` wins.
   RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad1_url);
-  // Wait for interest groups to be updated. Interest groups are updated
-  // during/after commit, so this test is potentially racy without this.
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
-       {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kBid, origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"},
-       {InterestGroupTestObserver::kWin, origin.Serialize(), "cars"}});
 
   // `prev_wins` of `test_url`'s interest group cars is updated in storage.
   storage_interest_groups = GetInterestGroupsForOwner(origin);
   storage_interest_groups2 = GetInterestGroupsForOwner(origin2);
-  // Remove the above two loads from the observer.
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}});
   EXPECT_EQ(
       storage_interest_groups.front().bidding_browser_signals->prev_wins.size(),
       1u);
@@ -6068,22 +6022,14 @@
   EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count,
             1);
 
+  // Start observer in the middle.
+  AttachInterestGroupObserver();
+
   // Run auction again. Interest group shoes of owner `test_url2` wins.
   RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url);
-  // Need to wait again.
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
-       {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"},
-       {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"}});
-
   // `test_url2`'s interest group shoes has one `prev_wins` in storage.
   storage_interest_groups = GetInterestGroupsForOwner(origin);
   storage_interest_groups2 = GetInterestGroupsForOwner(origin2);
-  // Remove the above two loads from the observer.
-  WaitForAccessObserved(
-      {{InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
-       {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"}});
   EXPECT_EQ(
       storage_interest_groups.front().bidding_browser_signals->prev_wins.size(),
       1u);
@@ -6110,13 +6056,6 @@
       origin2,
       https_server_->GetURL("b.test", "/interest_group/decision_logic.js"));
   RunAuctionAndWaitForURLAndNavigateIframe(auction_config, ad2_url);
-  // Need to wait again.
-  WaitForAccessObserved({
-      {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
-      {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"},
-      {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"},
-  });
-
   // `test_url2`'s interest group shoes has two `prev_wins` in storage.
   storage_interest_groups = GetInterestGroupsForOwner(origin);
   storage_interest_groups2 = GetInterestGroupsForOwner(origin2);
@@ -6135,6 +6074,20 @@
             1);
   EXPECT_EQ(storage_interest_groups2.front().bidding_browser_signals->bid_count,
             3);
+  // Observer was not active for joins and first auction.
+  WaitForAccessObserved({
+      {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
+      {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
+      {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kBid, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kWin, origin2.Serialize(), "shoes"},
+      {InterestGroupTestObserver::kLoaded, origin.Serialize(), "cars"},
+      {InterestGroupTestObserver::kLoaded, origin2.Serialize(), "shoes"},
+  });
 }
 
 IN_PROC_BROWSER_TEST_F(InterestGroupBrowserTest, ReportingMultipleAuctions) {
diff --git a/content/browser/interest_group/interest_group_manager_impl.cc b/content/browser/interest_group/interest_group_manager_impl.cc
index d4d8002..bd0493b 100644
--- a/content/browser/interest_group/interest_group_manager_impl.cc
+++ b/content/browser/interest_group/interest_group_manager_impl.cc
@@ -304,12 +304,15 @@
 }
 
 void InterestGroupManagerImpl::EnqueueReports(
+    ReportType report_type,
     const std::vector<GURL>& report_urls,
-    const std::vector<GURL>& debug_win_report_urls,
-    const std::vector<GURL>& debug_loss_report_urls,
     const url::Origin& frame_origin,
-    network::mojom::ClientSecurityStatePtr client_security_state,
+    network::mojom::ClientSecurityState& client_security_state,
     scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
+  if (report_urls.empty()) {
+    return;
+  }
+
   // For memory usage reasons, purge the queue if it has at least
   // `max_report_queue_length_` entries at the time we're about to add new
   // entries.
@@ -318,14 +321,28 @@
     report_requests_.clear();
   }
 
-  EnqueueReportsInternal(report_urls, frame_origin, client_security_state,
-                         "SendReportToReport", url_loader_factory);
-  EnqueueReportsInternal(debug_loss_report_urls, frame_origin,
-                         client_security_state, "DebugLossReport",
-                         url_loader_factory);
-  EnqueueReportsInternal(debug_win_report_urls, frame_origin,
-                         client_security_state, "DebugWinReport",
-                         url_loader_factory);
+  const char* report_type_name;
+  switch (report_type) {
+    case ReportType::kSendReportTo:
+      report_type_name = "SendReportToReport";
+      break;
+    case ReportType::kDebugWin:
+      report_type_name = "DebugWinReport";
+      break;
+    case ReportType::kDebugLoss:
+      report_type_name = "DebugLossReport";
+      break;
+  }
+
+  for (const GURL& report_url : report_urls) {
+    auto report_request = std::make_unique<ReportRequest>();
+    report_request->simple_url_loader = BuildSimpleUrlLoader(
+        report_url, frame_origin, client_security_state.Clone());
+    report_request->name = report_type_name;
+    report_request->url_loader_factory = url_loader_factory;
+    report_request->request_url_size_bytes = report_url.spec().size();
+    report_requests_.emplace_back(std::move(report_request));
+  }
 
   while (!report_requests_.empty() &&
          num_active_ < max_active_report_requests_) {
@@ -465,23 +482,6 @@
   }
 }
 
-void InterestGroupManagerImpl::EnqueueReportsInternal(
-    const std::vector<GURL>& report_urls,
-    const url::Origin& frame_origin,
-    const network::mojom::ClientSecurityStatePtr& client_security_state,
-    const char* name,
-    scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) {
-  for (const GURL& report_url : report_urls) {
-    auto report_request = std::make_unique<ReportRequest>();
-    report_request->simple_url_loader = BuildSimpleUrlLoader(
-        report_url, frame_origin, client_security_state.Clone());
-    report_request->name = name;
-    report_request->url_loader_factory = url_loader_factory;
-    report_request->request_url_size_bytes = report_url.spec().size();
-    report_requests_.emplace_back(std::move(report_request));
-  }
-}
-
 void InterestGroupManagerImpl::TrySendingOneReport() {
   DCHECK_GT(num_active_, 0);
 
diff --git a/content/browser/interest_group/interest_group_manager_impl.h b/content/browser/interest_group/interest_group_manager_impl.h
index de87f9a..797c0aa 100644
--- a/content/browser/interest_group/interest_group_manager_impl.h
+++ b/content/browser/interest_group/interest_group_manager_impl.h
@@ -60,6 +60,15 @@
   // re-use regular renderers following the normal site isolation policy.
   enum class ProcessMode { kDedicated, kInRenderer };
 
+  // Types of even-level reports, for use with EnqueueReports(). Currently only
+  // used for histograms. Raw values are not logged directly in histograms, so
+  // values do not need to be consistent across versions.
+  enum class ReportType {
+    kSendReportTo,
+    kDebugWin,
+    kDebugLoss,
+  };
+
   // Creates an interest group manager using the provided directory path for
   // persistent storage. If `in_memory` is true the path is ignored and only
   // in-memory storage is used.
@@ -187,40 +196,46 @@
   void GetInterestGroup(
       const blink::InterestGroupKey& group_key,
       base::OnceCallback<void(absl::optional<StorageInterestGroup>)> callback);
+
   // Gets a single interest group.
   void GetInterestGroup(
       const url::Origin& owner,
       const std::string& name,
       base::OnceCallback<void(absl::optional<StorageInterestGroup>)> callback);
+
   // Gets a list of all interest group owners. Each owner will only appear
   // once.
   void GetAllInterestGroupOwners(
       base::OnceCallback<void(std::vector<url::Origin>)> callback);
+
   // Gets a list of all interest groups with their bidding information
   // associated with the provided owner.
   void GetInterestGroupsForOwner(
       const url::Origin& owner,
       base::OnceCallback<void(std::vector<StorageInterestGroup>)> callback);
+
   // Clear out storage for the matching owning storage key. If the matcher is
   // empty then apply to all storage keys.
   void DeleteInterestGroupData(
       StoragePartition::StorageKeyMatcherFunction storage_key_matcher,
       base::OnceClosure completion_callback);
+
   // Completely delete all interest group data, including k-anonymity data that
   // is not cleared by DeleteInterestGroupData.
   void DeleteAllInterestGroupData(base::OnceClosure completion_callback);
+
   // Get the last maintenance time from the underlying InterestGroupStorage.
   void GetLastMaintenanceTimeForTesting(
       base::RepeatingCallback<void(base::Time)> callback) const;
-  // Enqueues report requests. Using `client_security_state` when fetching
-  // report URLs from the network.
+
+  // Enqueues reports for the specified URLs.
   void EnqueueReports(
+      ReportType report_type,
       const std::vector<GURL>& report_urls,
-      const std::vector<GURL>& debug_win_report_urls,
-      const std::vector<GURL>& debug_loss_report_urls,
       const url::Origin& frame_origin,
-      network::mojom::ClientSecurityStatePtr client_security_state,
+      network::mojom::ClientSecurityState& client_security_state,
       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
+
   // Update the interest group priority.
   void SetInterestGroupPriority(const blink::InterestGroupKey& group,
                                 double priority);
@@ -387,14 +402,6 @@
       base::OnceCallback<void(std::vector<StorageInterestGroup>)> callback,
       std::vector<StorageInterestGroup> groups);
 
-  // Enqueues each of `report_urls` to the `report_requests_` queue.
-  void EnqueueReportsInternal(
-      const std::vector<GURL>& report_urls,
-      const url::Origin& frame_origin,
-      const network::mojom::ClientSecurityStatePtr& client_security_state,
-      const char* name,
-      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
-
   // Dequeues and sends the first report request in `report_requests_` queue,
   // if the queue is not empty.
   void TrySendingOneReport();
diff --git a/content/browser/renderer_host/cross_origin_opener_policy_status.cc b/content/browser/renderer_host/cross_origin_opener_policy_status.cc
index d008b76..b12b51a5 100644
--- a/content/browser/renderer_host/cross_origin_opener_policy_status.cc
+++ b/content/browser/renderer_host/cross_origin_opener_policy_status.cc
@@ -48,9 +48,13 @@
     case CrossOriginOpenerPolicyValue::kRestrictPropertiesPlusCoep:
       switch (destination_coop) {
         case CrossOriginOpenerPolicyValue::kUnsafeNone:
+          return CoopSwapResult::kSwapWithReference;
         case CrossOriginOpenerPolicyValue::kRestrictProperties:
         case CrossOriginOpenerPolicyValue::kRestrictPropertiesPlusCoep:
-          return CoopSwapResult::kSwapWithReference;
+          return (initiator_coop == destination_coop &&
+                  initiator_origin.IsSameOriginWith(destination_origin))
+                     ? CoopSwapResult::kNoSwap
+                     : CoopSwapResult::kSwapWithReference;
         case CrossOriginOpenerPolicyValue::kSameOriginAllowPopups:
         case CrossOriginOpenerPolicyValue::kSameOrigin:
         case CrossOriginOpenerPolicyValue::kSameOriginPlusCoep:
diff --git a/content/browser/renderer_host/cross_origin_opener_policy_status_unittest.cc b/content/browser/renderer_host/cross_origin_opener_policy_status_unittest.cc
index 64dabcf7..41849157 100644
--- a/content/browser/renderer_host/cross_origin_opener_policy_status_unittest.cc
+++ b/content/browser/renderer_host/cross_origin_opener_policy_status_unittest.cc
@@ -91,9 +91,8 @@
        Result::kSwap, Result::kSwap},
       {COOP::kRestrictProperties, COOP::kSameOriginAllowPopups, Result::kSwap,
        Result::kSwap, Result::kSwap},
-      {COOP::kRestrictProperties, COOP::kRestrictProperties,
-       Result::kSwapWithReference, Result::kSwapWithReference,
-       Result::kSwapWithReference},
+      {COOP::kRestrictProperties, COOP::kRestrictProperties, Result::kNoSwap,
+       Result::kSwapWithReference, Result::kSwapWithReference},
       {COOP::kRestrictProperties, COOP::kRestrictPropertiesPlusCoep,
        Result::kSwapWithReference, Result::kSwapWithReference,
        Result::kSwapWithReference},
@@ -112,8 +111,7 @@
        Result::kSwapWithReference, Result::kSwapWithReference,
        Result::kSwapWithReference},
       {COOP::kRestrictPropertiesPlusCoep, COOP::kRestrictPropertiesPlusCoep,
-       Result::kSwapWithReference, Result::kSwapWithReference,
-       Result::kSwapWithReference},
+       Result::kNoSwap, Result::kSwapWithReference, Result::kSwapWithReference},
   };
   for (const auto& test : cases) {
     url::Origin A = url::Origin::Create(GURL("https://www.a.com"));
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 21f335f30..337aab0 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -314,11 +314,6 @@
 #endif
 );
 
-// Feature to ignore OpenURL from inactive RFH.
-BASE_FEATURE(kIgnoreOpenURLFromInactiveRFH,
-             "IgnoreOpenURLFromInactiveRFH",
-             base::FEATURE_ENABLED_BY_DEFAULT);
-
 }  // namespace features
 
 namespace content {
@@ -7327,12 +7322,7 @@
   // Also, see a similar check in RenderFrameHostImpl::BeginNavigation at
   // https://source.chromium.org/chromium/chromium/src/+/main:content/browser/renderer_host/render_frame_host_impl.cc;l=7761-7769;drc=6dc39d60fea45c003424272efdb4c366119a9d7f
   if (!owner) {
-    if (base::FeatureList::IsEnabled(features::kIgnoreOpenURLFromInactiveRFH)) {
-      return;
-    } else {
-      // TODO(mshin): Remove after 2023/Jan/21.
-      owner = frame_tree_node_;
-    }
+    return;
   }
   owner->GetCurrentNavigator().RequestOpenURL(
       this, validated_url, base::OptionalToPtr(params->initiator_frame_token),
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn
index 81cfae1..3d3a84f 100644
--- a/content/test/BUILD.gn
+++ b/content/test/BUILD.gn
@@ -3048,7 +3048,6 @@
     # Non-Android.
     sources += [
       "../browser/devtools/protocol/webauthn_handler_unittest.cc",
-      "../browser/direct_sockets/direct_sockets_unittest.cc",
       "../browser/host_zoom_map_impl_unittest.cc",
       "../browser/serial/serial_unittest.cc",
       "../browser/speech/endpointer/endpointer_unittest.cc",
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
index 5ac00bd..d4cae0a 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.cc
@@ -18,9 +18,6 @@
 
 namespace extensions {
 
-VirtualKeyboardRestrictFeaturesFunction::
-    VirtualKeyboardRestrictFeaturesFunction() {}
-
 void VirtualKeyboardRestrictFeaturesFunction::OnRestrictFeatures(
     api::virtual_keyboard::FeatureRestrictions update) {
   Respond(OneArgument(base::Value(update.ToValue())));
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
index a0403cfb..a9310416 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_api.h
@@ -12,7 +12,7 @@
 
 class VirtualKeyboardRestrictFeaturesFunction : public ExtensionFunction {
  public:
-  VirtualKeyboardRestrictFeaturesFunction();
+  VirtualKeyboardRestrictFeaturesFunction() = default;
 
   VirtualKeyboardRestrictFeaturesFunction(
       const VirtualKeyboardRestrictFeaturesFunction&) = delete;
diff --git a/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc b/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
index df596955..47a8422 100644
--- a/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
+++ b/extensions/browser/api/virtual_keyboard/virtual_keyboard_apitest.cc
@@ -5,24 +5,17 @@
 #include <memory>
 
 #include "base/auto_reset.h"
-#include "base/values.h"
-#include "content/public/browser/notification_observer.h"
-#include "content/public/browser/notification_registrar.h"
-#include "content/public/browser/notification_service.h"
-#include "content/public/browser/notification_source.h"
-#include "extensions/browser/api/test/test_api.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h"
-#include "extensions/browser/notification_types.h"
 #include "extensions/common/features/feature_session_type.h"
-#include "extensions/common/mojom/feature_session_type.mojom.h"
+#include "extensions/common/mojom/feature_session_type.mojom-shared.h"
 #include "extensions/shell/test/shell_apitest.h"
 
 namespace extensions {
 
 class VirtualKeyboardApiTest : public ShellApiTest {
  public:
-  VirtualKeyboardApiTest() {}
+  VirtualKeyboardApiTest() = default;
 
   VirtualKeyboardApiTest(const VirtualKeyboardApiTest&) = delete;
   VirtualKeyboardApiTest& operator=(const VirtualKeyboardApiTest&) = delete;
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
index f7519c46..b16a86f 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h
@@ -10,7 +10,6 @@
 
 #include "base/functional/callback.h"
 #include "base/values.h"
-#include "content/public/browser/browser_thread.h"
 #include "extensions/common/api/virtual_keyboard.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
@@ -20,7 +19,7 @@
 
 class VirtualKeyboardDelegate {
  public:
-  virtual ~VirtualKeyboardDelegate() {}
+  virtual ~VirtualKeyboardDelegate() = default;
 
   using OnKeyboardSettingsCallback =
       base::OnceCallback<void(absl::optional<base::Value::Dict> settings)>;
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
index 4b6fe0b..7c9f647 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.cc
@@ -13,10 +13,8 @@
 #include "base/strings/utf_string_conversions.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/virtual_keyboard_private/virtual_keyboard_delegate.h"
-#include "extensions/browser/extension_function_registry.h"
 #include "extensions/common/api/virtual_keyboard_private.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
-#include "ui/events/event.h"
 
 namespace extensions {
 
@@ -59,8 +57,6 @@
   return true;
 }
 
-VirtualKeyboardPrivateFunction::~VirtualKeyboardPrivateFunction() {}
-
 ExtensionFunction::ResponseAction
 VirtualKeyboardPrivateInsertTextFunction::Run() {
   EXTENSION_FUNCTION_VALIDATE(args().size() >= 1);
@@ -311,8 +307,7 @@
       ExtensionsAPIClient::Get()->CreateVirtualKeyboardDelegate(context);
 }
 
-VirtualKeyboardAPI::~VirtualKeyboardAPI() {
-}
+VirtualKeyboardAPI::~VirtualKeyboardAPI() = default;
 
 static base::LazyInstance<BrowserContextKeyedAPIFactory<VirtualKeyboardAPI>>::
     DestructorAtExit g_factory = LAZY_INSTANCE_INITIALIZER;
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
index c1cf5d6..333c58c 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api.h
@@ -5,7 +5,6 @@
 #ifndef EXTENSIONS_BROWSER_API_VIRTUAL_KEYBOARD_PRIVATE_VIRTUAL_KEYBOARD_PRIVATE_API_H_
 #define EXTENSIONS_BROWSER_API_VIRTUAL_KEYBOARD_PRIVATE_VIRTUAL_KEYBOARD_PRIVATE_API_H_
 
-#include "base/compiler_specific.h"
 #include "base/memory/raw_ptr.h"
 #include "base/values.h"
 #include "extensions/browser/browser_context_keyed_api_factory.h"
@@ -26,7 +25,7 @@
 
  protected:
   VirtualKeyboardDelegate* delegate() { return delegate_; }
-  ~VirtualKeyboardPrivateFunction() override;
+  ~VirtualKeyboardPrivateFunction() override = default;
 
  private:
   raw_ptr<VirtualKeyboardDelegate> delegate_ = nullptr;
@@ -39,7 +38,7 @@
                              VIRTUALKEYBOARDPRIVATE_INSERTTEXT)
 
  protected:
-  ~VirtualKeyboardPrivateInsertTextFunction() override {}
+  ~VirtualKeyboardPrivateInsertTextFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -52,7 +51,7 @@
                              VIRTUALKEYBOARDPRIVATE_SENDKEYEVENT)
 
  protected:
-  ~VirtualKeyboardPrivateSendKeyEventFunction() override {}
+  ~VirtualKeyboardPrivateSendKeyEventFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -65,7 +64,7 @@
                              VIRTUALKEYBOARDPRIVATE_HIDEKEYBOARD)
 
  protected:
-  ~VirtualKeyboardPrivateHideKeyboardFunction() override {}
+  ~VirtualKeyboardPrivateHideKeyboardFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -78,7 +77,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETHOTRODKEYBOARD)
 
  protected:
-  ~VirtualKeyboardPrivateSetHotrodKeyboardFunction() override {}
+  ~VirtualKeyboardPrivateSetHotrodKeyboardFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -91,7 +90,7 @@
                              VIRTUALKEYBOARDPRIVATE_LOCKKEYBOARD)
 
  protected:
-  ~VirtualKeyboardPrivateLockKeyboardFunction() override {}
+  ~VirtualKeyboardPrivateLockKeyboardFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -104,7 +103,7 @@
                              VIRTUALKEYBOARDPRIVATE_KEYBOARDLOADED)
 
  protected:
-  ~VirtualKeyboardPrivateKeyboardLoadedFunction() override {}
+  ~VirtualKeyboardPrivateKeyboardLoadedFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -117,7 +116,7 @@
                              VIRTUALKEYBOARDPRIVATE_GETKEYBOARDCONFIG)
 
  protected:
-  ~VirtualKeyboardPrivateGetKeyboardConfigFunction() override {}
+  ~VirtualKeyboardPrivateGetKeyboardConfigFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -133,7 +132,7 @@
                              VIRTUALKEYBOARDPRIVATE_OPENSETTINGS)
 
  protected:
-  ~VirtualKeyboardPrivateOpenSettingsFunction() override {}
+  ~VirtualKeyboardPrivateOpenSettingsFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -175,7 +174,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETDRAGGABLEAREA)
 
  protected:
-  ~VirtualKeyboardPrivateSetDraggableAreaFunction() override {}
+  ~VirtualKeyboardPrivateSetDraggableAreaFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -188,7 +187,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETKEYBOARDSTATE)
 
  protected:
-  ~VirtualKeyboardPrivateSetKeyboardStateFunction() override {}
+  ~VirtualKeyboardPrivateSetKeyboardStateFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -201,7 +200,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETOCCLUDEDBOUNDS)
 
  protected:
-  ~VirtualKeyboardPrivateSetOccludedBoundsFunction() override {}
+  ~VirtualKeyboardPrivateSetOccludedBoundsFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -214,7 +213,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETHITTESTBOUNDS)
 
  protected:
-  ~VirtualKeyboardPrivateSetHitTestBoundsFunction() override {}
+  ~VirtualKeyboardPrivateSetHitTestBoundsFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
@@ -227,7 +226,7 @@
                              VIRTUALKEYBOARDPRIVATE_SETAREATOREMAINONSCREEN)
 
  protected:
-  ~VirtualKeyboardPrivateSetAreaToRemainOnScreenFunction() override {}
+  ~VirtualKeyboardPrivateSetAreaToRemainOnScreenFunction() override = default;
 
   // ExtensionFunction:
   ResponseAction Run() override;
diff --git a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
index a15efde..1d00688 100644
--- a/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
+++ b/extensions/browser/api/virtual_keyboard_private/virtual_keyboard_private_api_unittest.cc
@@ -16,7 +16,7 @@
 
 class MockVirtualKeyboardDelegate : public VirtualKeyboardDelegate {
  public:
-  MockVirtualKeyboardDelegate() {}
+  MockVirtualKeyboardDelegate() = default;
 
   MockVirtualKeyboardDelegate(const MockVirtualKeyboardDelegate&) = delete;
   MockVirtualKeyboardDelegate& operator=(const MockVirtualKeyboardDelegate&) =
@@ -105,14 +105,14 @@
 
 class TestVirtualKeyboardExtensionsAPIClient : public ExtensionsAPIClient {
  public:
-  TestVirtualKeyboardExtensionsAPIClient() {}
+  TestVirtualKeyboardExtensionsAPIClient() = default;
 
   TestVirtualKeyboardExtensionsAPIClient(
       const TestVirtualKeyboardExtensionsAPIClient&) = delete;
   TestVirtualKeyboardExtensionsAPIClient& operator=(
       const TestVirtualKeyboardExtensionsAPIClient&) = delete;
 
-  ~TestVirtualKeyboardExtensionsAPIClient() override {}
+  ~TestVirtualKeyboardExtensionsAPIClient() override = default;
 
   // ExtensionsAPIClient implementation.
   std::unique_ptr<VirtualKeyboardDelegate> CreateVirtualKeyboardDelegate(
@@ -138,8 +138,8 @@
 
 class VirtualKeyboardPrivateApiUnittest : public ApiUnitTest {
  public:
-  VirtualKeyboardPrivateApiUnittest() {}
-  ~VirtualKeyboardPrivateApiUnittest() override {}
+  VirtualKeyboardPrivateApiUnittest() = default;
+  ~VirtualKeyboardPrivateApiUnittest() override = default;
 
   const TestVirtualKeyboardExtensionsAPIClient& client() const {
     return extensions_api_client_;
diff --git a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
index 9bbca13..5298fe8 100644
--- a/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
+++ b/extensions/shell/browser/shell_virtual_keyboard_delegate.cc
@@ -12,8 +12,6 @@
 
 namespace extensions {
 
-ShellVirtualKeyboardDelegate::ShellVirtualKeyboardDelegate() {}
-
 void ShellVirtualKeyboardDelegate::GetKeyboardConfig(
     OnKeyboardSettingsCallback on_settings_callback) {
   base::Value::Dict settings;
diff --git a/extensions/shell/browser/shell_virtual_keyboard_delegate.h b/extensions/shell/browser/shell_virtual_keyboard_delegate.h
index 3162b44..c0f3e882 100644
--- a/extensions/shell/browser/shell_virtual_keyboard_delegate.h
+++ b/extensions/shell/browser/shell_virtual_keyboard_delegate.h
@@ -14,7 +14,7 @@
 
 class ShellVirtualKeyboardDelegate : public VirtualKeyboardDelegate {
  public:
-  ShellVirtualKeyboardDelegate();
+  ShellVirtualKeyboardDelegate() = default;
 
   ShellVirtualKeyboardDelegate(const ShellVirtualKeyboardDelegate&) = delete;
   ShellVirtualKeyboardDelegate& operator=(const ShellVirtualKeyboardDelegate&) =
diff --git a/gin/per_context_data.h b/gin/per_context_data.h
index 9b606eca..6c6b8dcd 100644
--- a/gin/per_context_data.h
+++ b/gin/per_context_data.h
@@ -39,7 +39,7 @@
   ContextHolder* context_holder() { return context_holder_; }
 
  private:
-  raw_ptr<ContextHolder> context_holder_;
+  raw_ptr<ContextHolder, DanglingUntriaged> context_holder_;
   raw_ptr<Runner> runner_;
 };
 
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
index 00a8279..4c94d04 100644
--- a/gpu/command_buffer/service/raster_decoder.cc
+++ b/gpu/command_buffer/service/raster_decoder.cc
@@ -1013,6 +1013,12 @@
 }
 
 RasterDecoderImpl::~RasterDecoderImpl() {
+  // Client can call BeginRasterChromium and then channel can be closed and
+  // decoder destroyed. Finish raster first.
+  if (sk_surface_ || scoped_shared_image_raster_write_) {
+    DoEndRasterCHROMIUM();
+  }
+
   shared_context_state_->RemoveContextLostObserver(this);
 }
 
@@ -2487,19 +2493,18 @@
 
   auto sk_image =
       source_scoped_access->CreateSkImage(shared_context_state_->gr_context());
-  if (!sk_image) {
+  if (sk_image) {
+    bool success =
+        sk_image->readPixels(dst_info, pixel_address, row_bytes, src_x, src_y);
+    if (!success) {
+      LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadbackImagePixels",
+                         "Failed to read pixels from SkImage");
+    } else {
+      *result = 1;
+    }
+  } else {
     LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadbackImagePixels",
                        "Couldn't create SkImage for reading.");
-    return;
-  }
-
-  bool success =
-      sk_image->readPixels(dst_info, pixel_address, row_bytes, src_x, src_y);
-  if (!success) {
-    LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadbackImagePixels",
-                       "Failed to read pixels from SkImage");
-  } else {
-    *result = 1;
   }
 
   if (auto end_state = source_scoped_access->TakeEndState()) {
diff --git a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
index ca08d31..0575232 100644
--- a/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
+++ b/gpu/command_buffer/service/shared_image/d3d_image_backing.cc
@@ -1003,13 +1003,8 @@
     SharedImageManager* manager,
     MemoryTypeTracker* tracker) {
   TRACE_EVENT0("gpu", "D3DImageBacking::ProduceOverlay");
-  D3D11_TEXTURE2D_DESC desc;
-  d3d11_texture_->GetDesc(&desc);
-  if (swap_chain_ || desc.Format == DXGI_FORMAT_NV12) {
-    return std::make_unique<OverlayD3DImageRepresentation>(manager, this,
-                                                           tracker);
-  }
-  return nullptr;
+  return std::make_unique<OverlayD3DImageRepresentation>(manager, this,
+                                                         tracker);
 }
 
 absl::optional<gl::DCLayerOverlayImage>
diff --git a/gpu/ipc/service/gpu_channel_test_common.cc b/gpu/ipc/service/gpu_channel_test_common.cc
index b09be34..6f97d2b4 100644
--- a/gpu/ipc/service/gpu_channel_test_common.cc
+++ b/gpu/ipc/service/gpu_channel_test_common.cc
@@ -91,7 +91,12 @@
           new TestGpuChannelManagerDelegate(scheduler_.get())) {
   // We need GL bindings to actually initialize command buffers.
   if (use_stub_bindings) {
-    display_ = gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
+    if (features::UsePassthroughCommandDecoder()) {
+      display_ =
+          gl::GLSurfaceTestSupport::InitializeOneOffWithNullAngleBindings();
+    } else {
+      display_ = gl::GLSurfaceTestSupport::InitializeOneOffWithStubBindings();
+    }
   } else {
     display_ = gl::GLSurfaceTestSupport::InitializeOneOff();
   }
diff --git a/infra/config/generated/builders/ci/mac-arm64-on-arm64-rel-reclient/properties.json b/infra/config/generated/builders/ci/mac-arm64-on-arm64-rel-reclient/properties.json
deleted file mode 100644
index 284cb98..0000000
--- a/infra/config/generated/builders/ci/mac-arm64-on-arm64-rel-reclient/properties.json
+++ /dev/null
@@ -1,57 +0,0 @@
-{
-  "$build/chromium_tests_builder_config": {
-    "builder_config": {
-      "builder_db": {
-        "entries": [
-          {
-            "builder_id": {
-              "bucket": "ci",
-              "builder": "mac-arm64-on-arm64-rel-reclient",
-              "project": "chromium"
-            },
-            "builder_spec": {
-              "build_gs_bucket": "chromium-fyi-archive",
-              "builder_group": "chromium.fyi",
-              "execution_mode": "COMPILE_AND_TEST",
-              "legacy_chromium_config": {
-                "apply_configs": [
-                  "mb"
-                ],
-                "build_config": "Release",
-                "config": "chromium",
-                "target_arch": "arm",
-                "target_bits": 64
-              },
-              "legacy_gclient_config": {
-                "apply_configs": [
-                  "reclient_test"
-                ],
-                "config": "chromium"
-              }
-            }
-          }
-        ]
-      },
-      "builder_ids": [
-        {
-          "bucket": "ci",
-          "builder": "mac-arm64-on-arm64-rel-reclient",
-          "project": "chromium"
-        }
-      ]
-    }
-  },
-  "$build/reclient": {
-    "instance": "rbe-chromium-trusted",
-    "metrics_project": "chromium-reclient-metrics"
-  },
-  "$recipe_engine/resultdb/test_presentation": {
-    "column_keys": [],
-    "grouping_keys": [
-      "status",
-      "v.test_suite"
-    ]
-  },
-  "builder_group": "chromium.fyi",
-  "recipe": "chromium"
-}
\ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg
index 138ae38..d71233d1 100644
--- a/infra/config/generated/luci/cr-buildbucket.cfg
+++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -42800,93 +42800,6 @@
       }
     }
     builders {
-      name: "mac-arm64-on-arm64-rel-reclient"
-      swarming_host: "chromium-swarm.appspot.com"
-      dimensions: "builder:mac-arm64-on-arm64-rel-reclient"
-      dimensions: "cpu:arm64"
-      dimensions: "os:Mac-12"
-      dimensions: "pool:luci.chromium.ci"
-      exe {
-        cipd_package: "infra/chromium/bootstrapper/${platform}"
-        cipd_version: "latest"
-        cmd: "bootstrapper"
-      }
-      properties:
-        '{'
-        '  "$bootstrap/exe": {'
-        '    "exe": {'
-        '      "cipd_package": "infra/recipe_bundles/chromium.googlesource.com/chromium/tools/build",'
-        '      "cipd_version": "refs/heads/main",'
-        '      "cmd": ['
-        '        "luciexe"'
-        '      ]'
-        '    }'
-        '  },'
-        '  "$bootstrap/properties": {'
-        '    "properties_file": "infra/config/generated/builders/ci/mac-arm64-on-arm64-rel-reclient/properties.json",'
-        '    "top_level_project": {'
-        '      "ref": "refs/heads/main",'
-        '      "repo": {'
-        '        "host": "chromium.googlesource.com",'
-        '        "project": "chromium/src"'
-        '      }'
-        '    }'
-        '  },'
-        '  "builder_group": "chromium.fyi",'
-        '  "led_builder_is_bootstrapped": true,'
-        '  "recipe": "chromium"'
-        '}'
-      priority: 35
-      execution_timeout_secs: 36000
-      build_numbers: YES
-      service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
-      experiments {
-        key: "chromium_swarming.expose_merge_script_failures"
-        value: 100
-      }
-      experiments {
-        key: "luci.buildbucket.omit_python2"
-        value: 100
-      }
-      experiments {
-        key: "luci.recipes.use_python3"
-        value: 100
-      }
-      resultdb {
-        enable: true
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "ci_test_results"
-          test_results {}
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "gpu_ci_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "ninja://chrome/test:telemetry_gpu_integration_test[^/]*/.+"
-            }
-          }
-        }
-        bq_exports {
-          project: "chrome-luci-data"
-          dataset: "chromium"
-          table: "blink_web_tests_ci_test_results"
-          test_results {
-            predicate {
-              test_id_regexp: "(ninja://[^/]*blink_web_tests/.+)|(ninja://[^/]*blink_wpt_tests/.+)"
-            }
-          }
-        }
-        history_options {
-          use_invocation_timestamp: true
-        }
-      }
-      description_html: "experiment reclient on mac-arm. should be removed after the migration. crbug.com/1252626"
-    }
-    builders {
       name: "mac-arm64-rel"
       swarming_host: "chromium-swarm.appspot.com"
       dimensions: "builder:mac-arm64-rel"
diff --git a/infra/config/generated/luci/luci-milo.cfg b/infra/config/generated/luci/luci-milo.cfg
index 13fdde6..a3d584d51 100644
--- a/infra/config/generated/luci/luci-milo.cfg
+++ b/infra/config/generated/luci/luci-milo.cfg
@@ -8897,11 +8897,6 @@
     short_name: "re"
   }
   builders {
-    name: "buildbucket/luci.chromium.ci/mac-arm64-on-arm64-rel-reclient"
-    category: "mac"
-    short_name: "re"
-  }
-  builders {
     name: "buildbucket/luci.chromium.ci/Comparison Mac (reclient)(CQ)"
     category: "mac|cq"
     short_name: "cmp"
diff --git a/infra/config/generated/luci/luci-scheduler.cfg b/infra/config/generated/luci/luci-scheduler.cfg
index 14a892a..b101f6a 100644
--- a/infra/config/generated/luci/luci-scheduler.cfg
+++ b/infra/config/generated/luci/luci-scheduler.cfg
@@ -5270,15 +5270,6 @@
   }
 }
 job {
-  id: "mac-arm64-on-arm64-rel-reclient"
-  realm: "ci"
-  buildbucket {
-    server: "cr-buildbucket.appspot.com"
-    bucket: "ci"
-    builder: "mac-arm64-on-arm64-rel-reclient"
-  }
-}
-job {
   id: "mac-arm64-rel"
   realm: "ci"
   buildbucket {
@@ -6409,7 +6400,6 @@
   triggers: "mac-arm64-archive-dbg"
   triggers: "mac-arm64-archive-rel"
   triggers: "mac-arm64-on-arm64-rel"
-  triggers: "mac-arm64-on-arm64-rel-reclient"
   triggers: "mac-arm64-rel"
   triggers: "mac-backuprefptr-x64-fyi-rel"
   triggers: "mac-code-coverage"
diff --git a/infra/config/subprojects/chromium/ci/chromium.fyi.star b/infra/config/subprojects/chromium/ci/chromium.fyi.star
index 1ba856c..2751ff7 100644
--- a/infra/config/subprojects/chromium/ci/chromium.fyi.star
+++ b/infra/config/subprojects/chromium/ci/chromium.fyi.star
@@ -1888,35 +1888,6 @@
 )
 
 fyi_mac_builder(
-    name = "mac-arm64-on-arm64-rel-reclient",
-    description_html = "experiment reclient on mac-arm. should be removed after the migration. crbug.com/1252626",
-    builder_spec = builder_config.builder_spec(
-        gclient_config = builder_config.gclient_config(
-            config = "chromium",
-            apply_configs = ["reclient_test"],
-        ),
-        chromium_config = builder_config.chromium_config(
-            config = "chromium",
-            apply_configs = ["mb"],
-            build_config = builder_config.build_config.RELEASE,
-            target_arch = builder_config.target_arch.ARM,
-            target_bits = 64,
-        ),
-        build_gs_bucket = "chromium-fyi-archive",
-    ),
-
-    # same with mac-arm64-on-arm64-rel
-    cores = None,  # crbug.com/1245114
-    os = os.MAC_12,
-    cpu = cpu.ARM64,
-    console_view_entry = consoles.console_view_entry(
-        category = "mac",
-        short_name = "re",
-    ),
-    reclient_jobs = None,
-)
-
-fyi_mac_builder(
     name = "mac10.15-wpt-content-shell-fyi-rel",
     builder_spec = builder_config.builder_spec(
         gclient_config = builder_config.gclient_config(
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd
index 802f895..3d77431 100644
--- a/ios/chrome/app/strings/ios_strings.grd
+++ b/ios/chrome/app/strings/ios_strings.grd
@@ -1026,9 +1026,6 @@
       <message name="IDS_IOS_FIRST_RUN_SIGNIN_SIGN_IN_ACTION" desc="In Title Case: Button on the very first screen of Chrome for users to sign in when there is no Google Account on the device. [iOS only]">
         Sign In…
       </message>
-      <message name="IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT_WITH_LINK_TO_SETTINGS" desc="Content string on the sync screen presented to the user on First Run [iOS only]">
-        You can always choose what to sync in <ph name="BEGIN_LINK">BEGIN_LINK</ph>settings<ph name="END_LINK">END_LINK</ph>. Google may use your history to personalize Search and other Google services.
-      </message>
       <message name="IDS_IOS_FIRST_RUN_SYNC_SCREEN_PRIMARY_ACTION" desc="The primary action string on the sync screen presented to the user on First Run [iOS only]">
         Turn on Sync
       </message>
@@ -2429,9 +2426,6 @@
       <message name="IDS_IOS_ENTERPRISE_MANAGED_INFO" desc="Text displayed to inform the user that the browser is managed by one or more Enterprise policies. [iOS only]">
         Managed by your organization. Some features may be unavailable. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn more<ph name="END_LINK">END_LINK</ph>
       </message>
-      <message name="IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_DETAILS" desc="Text displayed to inform the user that their Sign In/Sync is managed by their administrator. [iOS only]">
-          Your browser is managed. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Details<ph name="END_LINK">END_LINK</ph>
-      </message>
       <message name="IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_LEARN_MORE" desc="Text displayed to inform the user that their Sign In/Sync is managed by their administrator. [iOS only]">
           Your browser is managed. <ph name="BEGIN_LINK">BEGIN_LINK</ph>Learn More<ph name="END_LINK">END_LINK</ph>
       </message>
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_DETAILS.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_DETAILS.png.sha1
deleted file mode 100644
index 7fa5dce..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_DETAILS.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-8834605065beece9c13f66fe4d1b04a62e3f13cc
\ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT_WITH_LINK_TO_SETTINGS.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT_WITH_LINK_TO_SETTINGS.png.sha1
deleted file mode 100644
index fd881c7..0000000
--- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT_WITH_LINK_TO_SETTINGS.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-441d167623c5b3cbe921bb7a14d6832bffd2c1e4
\ No newline at end of file
diff --git a/ios/chrome/browser/first_run/first_run_metrics.h b/ios/chrome/browser/first_run/first_run_metrics.h
index 30d8fdb..b5ada24c 100644
--- a/ios/chrome/browser/first_run/first_run_metrics.h
+++ b/ios/chrome/browser/first_run/first_run_metrics.h
@@ -84,14 +84,13 @@
   // The first run experience has completed.
   kComplete = 1,
   // Sync screen is shown.
-  kSyncScreenStart = 2,
+  // kSyncScreenStart_DEPRECATED = 2,
   // Sync screen is closed with sync.
-  kSyncScreenCompletionWithSync = 3,
+  // kSyncScreenCompletionWithSync_DEPRECATED = 3,
   // Sync screen is closed without sync.
-  kSyncScreenCompletionWithoutSync = 4,
+  // kSyncScreenCompletionWithoutSync_DEPRECATED = 4,
   // Sync screen is closed when user taps on advance sync settings button.
-  // Deprecated. This is not used anymore.
-  kSyncScreenCompletionWithSyncSettings = 5,
+  // kSyncScreenCompletionWithSyncSettings_DEPRECATED = 5,
   // SignIn screen is shown.
   kSignInScreenStart = 6,
   // SignIn screen is closed with sign in.
@@ -145,12 +144,6 @@
   // detected, but with no footer shown at the bottom. Displayed when MICe is
   // enabled with the welcome screen (3-steps MICe FRE).
   kSignInScreenWithoutFooterOrIdentityPicker,
-  // The screen that asks the user to turn on sync while no account picker is
-  // present. Displayed when MICe is enabled or when no account is detected.
-  kSyncScreenWithoutIdentityPicker,
-  // The screen that asks the user to turn on sync while showing an account
-  // picker. Displayed when MICe is disabled and an account is detected.
-  kSyncScreenWithIdentityPicker,
   // Welcome screen without UMA checkbox. Displayed when MICe is enabled.
   kWelcomeScreenWithoutUMACheckbox,
   // Welcome screen with UMA checkbox. Displayed when MICe is disabled.
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm
index ac06760..bf9a2863 100644
--- a/ios/chrome/browser/flags/about_flags.mm
+++ b/ios/chrome/browser/flags/about_flags.mm
@@ -732,6 +732,11 @@
      flag_descriptions::kUpdateHistoryEntryPointsInIncognitoDescription,
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(kUpdateHistoryEntryPointsInIncognito)},
+    {"sync-trusted-vault-passphrase-promo",
+     flag_descriptions::kSyncTrustedVaultPassphrasePromoName,
+     flag_descriptions::kSyncTrustedVaultPassphrasePromoDescription,
+     flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(::syncer::kSyncTrustedVaultPassphrasePromo)},
     {"wait-threshold-seconds-for-capabilities-api",
      flag_descriptions::kWaitThresholdMillisecondsForCapabilitiesApiName,
      flag_descriptions::kWaitThresholdMillisecondsForCapabilitiesApiDescription,
@@ -1200,10 +1205,6 @@
      flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(
          autofill::features::kAutofillOfferToSaveCardWithSameLastFour)},
-    {"enable-new-bookmarks-implementation",
-     flag_descriptions::kEnableNewBookmarksImplementationName,
-     flag_descriptions::kEnableNewBookmarksImplementationDescription,
-     flags_ui::kOsIos, FEATURE_VALUE_TYPE(kEnableNewBookmarksImplementation)},
     {"omnibox-multiline-search-suggest",
      flag_descriptions::kOmniboxMultilineSearchSuggestName,
      flag_descriptions::kOmniboxMultilineSearchSuggestDescription,
@@ -1241,6 +1242,9 @@
     {"shopping-list", commerce::flag_descriptions::kShoppingListName,
      commerce::flag_descriptions::kShoppingListDescription, flags_ui::kOsIos,
      FEATURE_VALUE_TYPE(commerce::kShoppingList)},
+    {"ios-tabstrip-context-menu", flag_descriptions::kTabStripContextMenuName,
+     flag_descriptions::kTabStripContextMenuDescription, flags_ui::kOsIos,
+     FEATURE_VALUE_TYPE(kTabStripContextMenu)},
 };
 
 bool SkipConditionalFeatureEntry(const flags_ui::FeatureEntry& entry) {
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
index 11079bd..04e0f26 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -316,11 +316,6 @@
 const char kEnableFullscreenAPIDescription[] =
     "Enable the Fullscreen API for web content (iOS 16.0+).";
 
-const char kEnableNewBookmarksImplementationName[] =
-    "Enable New Bookmarks Implementation";
-const char kEnableNewBookmarksImplementationDescription[] =
-    "Enable the new bookmarks implementation with coordinators";
-
 const char kPasswordsGroupingName[] =
     "Enable password grouping for the Password Manager";
 const char kPasswordsGroupingDescription[] =
@@ -786,6 +781,12 @@
 const char kSyncEnableHistoryDataTypeDescription[] =
     "Enables the History sync data type instead of TypedURLs";
 
+const char kSyncTrustedVaultPassphrasePromoName[] =
+    "Enable promos for sync trusted vault passphrase.";
+const char kSyncTrustedVaultPassphrasePromoDescription[] =
+    "Enables promos for an experimental sync passphrase type, referred to as "
+    "trusted vault.";
+
 const char kSyncInvalidationsName[] = "Use Sync standalone invalidations";
 const char kSyncInvalidationsDescription[] =
     "If enabled, Sync will use standalone invalidations instead of topic based "
@@ -871,6 +872,10 @@
 const char kTabGridRecencySortDescription[] =
     "When enabled, the tabs in the Tab Grid are sorted differently.";
 
+const char kTabStripContextMenuName[] = "Tab Strip Context Menu";
+const char kTabStripContextMenuDescription[] =
+    "Add context menu to tab strip items.";
+
 const char kUseLoadSimulatedRequestForOfflinePageName[] =
     "Use loadSimulatedRequest:responseHTMLString: when displaying offline "
     "pages";
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
index 3af9e55..d687c6a 100644
--- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
+++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -284,10 +284,6 @@
 extern const char kEnableFullscreenAPIName[];
 extern const char kEnableFullscreenAPIDescription[];
 
-// Title and description for the new bookmarks implementation.
-extern const char kEnableNewBookmarksImplementationName[];
-extern const char kEnableNewBookmarksImplementationDescription[];
-
 // Title and description for the flag to enable password grouping for the
 // Password Manager.
 extern const char kPasswordsGroupingName[];
@@ -703,6 +699,11 @@
 extern const char kSyncEnableHistoryDataTypeName[];
 extern const char kSyncEnableHistoryDataTypeDescription[];
 
+// Title and description for the flag to control if Chrome Sync should support
+// trusted vault passphrase promos.
+extern const char kSyncTrustedVaultPassphrasePromoName[];
+extern const char kSyncTrustedVaultPassphrasePromoDescription[];
+
 // Title and description for the flag to enable Sync standalone invalidations.
 extern const char kSyncInvalidationsName[];
 extern const char kSyncInvalidationsDescription[];
@@ -764,6 +765,10 @@
 extern const char kTabGridRecencySortName[];
 extern const char kTabGridRecencySortDescription[];
 
+// Title and description for the flag that enable tab strip context menu.
+extern const char kTabStripContextMenuName[];
+extern const char kTabStripContextMenuDescription[];
+
 // Title and description for the flag to enable using the
 // loadSimulatedRequest:responseHTMLString: API for displaying error pages in
 // CRWWKNavigationHandler.
diff --git a/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h b/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h
index 4ce9dc7..ed80e49 100644
--- a/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h
+++ b/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h
@@ -9,29 +9,11 @@
 
 #include "ios/chrome/browser/sync/sync_setup_service.h"
 
-class AuthenticationService;
 class PrefService;
 namespace syncer {
 class SyncService;
 }
 
-// List of Enterprise restriction options.
-typedef NS_OPTIONS(NSUInteger, EnterpriseSignInRestrictions) {
-  // No enterprise restriction.
-  kNoEnterpriseRestriction = 0,
-  // Sign-in is forced.
-  kEnterpriseForceSignIn = 1 << 0,
-  // Sign-in is disabled, please consider using
-  // AuthenticationService::GetServiceStatus() to get all disable reasons.
-  kEnterpriseSignInDisabled = 1 << 1,
-  // Account restrictions are set.
-  kEnterpriseRestrictAccounts = 1 << 2,
-  // Sync is disabled.
-  kEnterpriseSyncDisabled = 1 << 3,
-  // If any data type is managed by policies (i.e. is not syncable).
-  kEnterpriseSyncTypesListDisabled = 1 << 4,
-};
-
 // Returns YES if some account restrictions are set.
 bool IsRestrictAccountsToPatternsEnabled();
 
@@ -42,12 +24,6 @@
 // Returns true if any data type is managed by policies (i.e. is not syncable).
 bool HasManagedSyncDataType(PrefService* pref_service);
 
-// Returns current EnterpriseSignInRestrictions.
-EnterpriseSignInRestrictions GetEnterpriseSignInRestrictions(
-    AuthenticationService* authentication_service,
-    PrefService* pref_service,
-    syncer::SyncService* sync_service);
-
 // true if sync is disabled.
 bool IsSyncDisabledByPolicy(syncer::SyncService* sync_service);
 
diff --git a/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.mm b/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.mm
index c1d7028..dbb89f2 100644
--- a/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.mm
+++ b/ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.mm
@@ -13,7 +13,6 @@
 #import "ios/chrome/browser/application_context/application_context.h"
 #import "ios/chrome/browser/policy/policy_util.h"
 #import "ios/chrome/browser/prefs/pref_names.h"
-#import "ios/chrome/browser/signin/authentication_service.h"
 #import "ios/chrome/browser/sync/sync_service_factory.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
@@ -60,32 +59,6 @@
   return false;
 }
 
-EnterpriseSignInRestrictions GetEnterpriseSignInRestrictions(
-    AuthenticationService* authentication_service,
-    PrefService* pref_service,
-    syncer::SyncService* sync_service) {
-  EnterpriseSignInRestrictions restrictions = kNoEnterpriseRestriction;
-  switch (authentication_service->GetServiceStatus()) {
-    case AuthenticationService::ServiceStatus::SigninForcedByPolicy:
-      restrictions |= kEnterpriseForceSignIn;
-      break;
-    case AuthenticationService::ServiceStatus::SigninDisabledByPolicy:
-      restrictions |= kEnterpriseSignInDisabled;
-      break;
-    case AuthenticationService::ServiceStatus::SigninAllowed:
-    case AuthenticationService::ServiceStatus::SigninDisabledByUser:
-    case AuthenticationService::ServiceStatus::SigninDisabledByInternal:
-      break;
-  }
-  if (IsRestrictAccountsToPatternsEnabled())
-    restrictions |= kEnterpriseRestrictAccounts;
-  if (IsSyncDisabledByPolicy(sync_service))
-    restrictions |= kEnterpriseSyncDisabled;
-  if (HasManagedSyncDataType(pref_service))
-    restrictions |= kEnterpriseSyncTypesListDisabled;
-  return restrictions;
-}
-
 bool IsSyncDisabledByPolicy(syncer::SyncService* sync_service) {
   return sync_service->GetDisableReasons().Has(
       syncer::SyncService::DISABLE_REASON_ENTERPRISE_POLICY);
diff --git a/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm b/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
index f924e10..aa69777 100644
--- a/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
+++ b/ios/chrome/browser/ui/authentication/signin/forced_signin/forced_signin_coordinator.mm
@@ -115,7 +115,6 @@
                                    browser:self.browser
                             showFREConsent:NO
                                   delegate:self];
-    case kSignInAndSync_DEPRECATED:
     case kTangibleSync:
     case kWelcomeAndConsent_DEPRECATED:
     case kDefaultBrowserPromo:
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/BUILD.gn b/ios/chrome/browser/ui/authentication/signin_sync/BUILD.gn
deleted file mode 100644
index 7256e7a..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/BUILD.gn
+++ /dev/null
@@ -1,111 +0,0 @@
-# Copyright 2021 The Chromium Authors
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-import("//build/config/chrome_build.gni")
-
-source_set("signin_sync") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "signin_sync_coordinator.h",
-    "signin_sync_coordinator.mm",
-    "signin_sync_mediator.h",
-    "signin_sync_mediator.mm",
-    "signin_sync_mediator_delegate.h",
-  ]
-  deps = [
-    ":signin_sync_ui",
-    "//base",
-    "//components/consent_auditor",
-    "//components/prefs",
-    "//components/unified_consent",
-    "//ios/chrome/app/application_delegate:app_state_header",
-    "//ios/chrome/app/strings",
-    "//ios/chrome/browser/consent_auditor",
-    "//ios/chrome/browser/first_run",
-    "//ios/chrome/browser/main:public",
-    "//ios/chrome/browser/policy",
-    "//ios/chrome/browser/policy:policy_util",
-    "//ios/chrome/browser/signin",
-    "//ios/chrome/browser/signin:system_identity",
-    "//ios/chrome/browser/sync",
-    "//ios/chrome/browser/ui/authentication",
-    "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils",
-    "//ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt",
-    "//ios/chrome/browser/ui/authentication/signin:signin_headers",
-    "//ios/chrome/browser/ui/authentication/signin/user_signin/logging",
-    "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser",
-    "//ios/chrome/browser/ui/commands",
-    "//ios/chrome/browser/ui/first_run:interruptible_chrome_coordinator",
-    "//ios/chrome/browser/ui/first_run:screen_delegate",
-    "//ios/chrome/browser/ui/first_run:utils",
-    "//ios/chrome/browser/ui/first_run/resources:sync_screen_banner",
-    "//ios/chrome/browser/ui/main:scene_state_header",
-    "//ios/chrome/browser/unified_consent",
-    "//ios/chrome/browser/url_loading",
-  ]
-}
-
-source_set("signin_sync_ui") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  sources = [
-    "signin_sync_consumer.h",
-    "signin_sync_view_controller.h",
-    "signin_sync_view_controller.mm",
-    "signin_sync_view_controller_delegate.h",
-  ]
-  deps = [
-    "//ios/chrome/app/strings",
-    "//ios/chrome/browser/ui/authentication",
-    "//ios/chrome/browser/ui/authentication:authentication_constants",
-    "//ios/chrome/browser/ui/authentication/enterprise:enterprise_utils",
-    "//ios/chrome/browser/ui/authentication/views",
-    "//ios/chrome/browser/ui/elements:elements_internal",
-    "//ios/chrome/browser/ui/settings/elements:constants",
-    "//ios/chrome/browser/ui/settings/elements:enterprise_info_popover_view_controller",
-    "//ios/chrome/common:string_util",
-    "//ios/chrome/common/ui/colors",
-    "//ios/chrome/common/ui/elements:popover_label_view_controller",
-    "//ios/chrome/common/ui/promo_style",
-    "//ios/chrome/common/ui/util",
-    "//net",
-    "//ui/base",
-    "//url",
-  ]
-}
-
-source_set("unit_tests") {
-  configs += [ "//build/config/compiler:enable_arc" ]
-  testonly = true
-  sources = [ "signin_sync_mediator_unittest.mm" ]
-  deps = [
-    ":signin_sync",
-    ":signin_sync_ui",
-    "//base",
-    "//base/test:test_support",
-    "//components/consent_auditor",
-    "//components/consent_auditor:test_support",
-    "//components/prefs",
-    "//components/signin/public/identity_manager",
-    "//components/sync:test_support",
-    "//components/sync/driver",
-    "//components/unified_consent",
-    "//ios/chrome/browser/application_context",
-    "//ios/chrome/browser/browser_state:test_support",
-    "//ios/chrome/browser/consent_auditor",
-    "//ios/chrome/browser/consent_auditor:test_support",
-    "//ios/chrome/browser/main:test_support",
-    "//ios/chrome/browser/signin",
-    "//ios/chrome/browser/signin:fake_system_identity",
-    "//ios/chrome/browser/signin:fake_system_identity_manager",
-    "//ios/chrome/browser/signin:test_support",
-    "//ios/chrome/browser/sync",
-    "//ios/chrome/browser/sync:test_support",
-    "//ios/chrome/browser/ui/authentication",
-    "//ios/chrome/browser/unified_consent",
-    "//ios/chrome/browser/web_state_list",
-    "//ios/chrome/test:test_support",
-    "//ios/web/public/test",
-    "//third_party/ocmock",
-  ]
-}
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h
deleted file mode 100644
index bffd98bc..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_CONSUMER_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_CONSUMER_H_
-
-#import <UIKit/UIKit.h>
-
-// Handles sign-in screen UI updates.
-@protocol SigninSyncConsumer <NSObject>
-
-// Sets the `userName`, `email`, `givenName` and `avatar` of the selected
-// identity. The `userName` and `givenName` can be nil. Notifies the UI that an
-// identity is available.
-- (void)setSelectedIdentityUserName:(NSString*)userName
-                              email:(NSString*)email
-                          givenName:(NSString*)givenName
-                             avatar:(UIImage*)avatar;
-
-// Notifies the consumer that no identity is available and that the UI should be
-// updated accordingly.
-- (void)noIdentityAvailable;
-
-// Sets the UI as interactable or not.
-- (void)setUIEnabled:(BOOL)UIEnabled;
-
-// Sets the value of the sign-in or sign out action to done (YES).
-- (void)setActionToDone;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_CONSUMER_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.h
deleted file mode 100644
index 845b63e..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.h
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_COORDINATOR_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_COORDINATOR_H_
-
-#import "ios/chrome/browser/ui/first_run/interruptible_chrome_coordinator.h"
-
-@protocol FirstRunScreenDelegate;
-
-// Coordinator for the screen allowing the user to Sign-in and Sync.
-@interface SigninSyncCoordinator : InterruptibleChromeCoordinator
-
-// Initiates a SigninSyncCoordinator with `navigationController`,
-// `browser` and `delegate`.
-// The `delegate` parameter is for handling the transfer between screens.
-- (instancetype)initWithBaseNavigationController:
-                    (UINavigationController*)navigationController
-                                         browser:(Browser*)browser
-                                        delegate:
-                                            (id<FirstRunScreenDelegate>)delegate
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)initWithBaseViewController:(UIViewController*)viewController
-                                   browser:(Browser*)browser NS_UNAVAILABLE;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm
deleted file mode 100644
index 6538a5b..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.mm
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.h"
-
-#import "base/metrics/histogram_functions.h"
-#import "components/sync/driver/sync_service.h"
-#import "ios/chrome/app/application_delegate/app_state.h"
-#import "ios/chrome/app/application_delegate/app_state_observer.h"
-#import "ios/chrome/browser/browser_state/chrome_browser_state.h"
-#import "ios/chrome/browser/consent_auditor/consent_auditor_factory.h"
-#import "ios/chrome/browser/first_run/first_run_metrics.h"
-#import "ios/chrome/browser/main/browser.h"
-#import "ios/chrome/browser/policy/policy_watcher_browser_agent.h"
-#import "ios/chrome/browser/policy/policy_watcher_browser_agent_observer_bridge.h"
-#import "ios/chrome/browser/signin/authentication_service.h"
-#import "ios/chrome/browser/signin/authentication_service_factory.h"
-#import "ios/chrome/browser/signin/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/chrome_account_manager_service_factory.h"
-#import "ios/chrome/browser/signin/constants.h"
-#import "ios/chrome/browser/signin/identity_manager_factory.h"
-#import "ios/chrome/browser/sync/sync_service_factory.h"
-#import "ios/chrome/browser/sync/sync_setup_service.h"
-#import "ios/chrome/browser/sync/sync_setup_service_factory.h"
-#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
-#import "ios/chrome/browser/ui/authentication/enterprise/enterprise_prompt/enterprise_prompt_coordinator.h"
-#import "ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h"
-#import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
-#import "ios/chrome/browser/ui/authentication/signin/signin_coordinator.h"
-#import "ios/chrome/browser/ui/authentication/signin/signin_utils.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h"
-#import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_coordinator.h"
-#import "ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_coordinator_delegate.h"
-#import "ios/chrome/browser/ui/commands/browsing_data_commands.h"
-#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
-#import "ios/chrome/browser/ui/first_run/first_run_screen_delegate.h"
-#import "ios/chrome/browser/ui/first_run/first_run_util.h"
-#import "ios/chrome/browser/ui/main/scene_state.h"
-#import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
-#import "ios/chrome/browser/unified_consent/unified_consent_service_factory.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface SigninSyncCoordinator () <EnterprisePromptCoordinatorDelegate,
-                                     IdentityChooserCoordinatorDelegate,
-                                     PolicyWatcherBrowserAgentObserving,
-                                     SigninSyncMediatorDelegate,
-                                     SigninSyncViewControllerDelegate> {
-  // Observer for the sign-out policy changes.
-  std::unique_ptr<PolicyWatcherBrowserAgentObserverBridge>
-      _policyWatcherObserverBridge;
-}
-
-// First run screen delegate.
-@property(nonatomic, weak) id<FirstRunScreenDelegate> delegate;
-// The view controller.
-@property(nonatomic, strong) SigninSyncViewController* viewController;
-// The mediator.
-@property(nonatomic, strong) SigninSyncMediator* mediator;
-// Coordinator handling choosing the account to sign in with.
-@property(nonatomic, strong)
-    IdentityChooserCoordinator* identityChooserCoordinator;
-// Coordinator handling adding a user account.
-@property(nonatomic, strong) SigninCoordinator* addAccountSigninCoordinator;
-// Whether the user attempted to sign in (the attempt can be successful, failed
-// or canceled).
-@property(nonatomic, assign) first_run::SignInAttemptStatus attemptStatus;
-// Whether there was existing accounts when the screen was presented.
-@property(nonatomic, assign) BOOL hadIdentitiesAtStartup;
-// The coordinator that manages enterprise prompts.
-@property(nonatomic, strong)
-    EnterprisePromptCoordinator* enterprisePromptCoordinator;
-// Account manager service to retrieve Chrome identities.
-@property(nonatomic, assign) ChromeAccountManagerService* accountManagerService;
-// YES if this coordinator is currently used in First Run. When set to NO, it
-// is assumed that the coordinator is used outside of First Run (i.e., used
-// from Settings).
-@property(nonatomic, readonly) BOOL firstRun;
-// The consent string ids that were pushed that are related to the text for
-// sync.
-@property(nonatomic, strong, readonly) NSMutableArray* consentStringIDs;
-// Coordinator for showing advanced settings on top of the screen.
-@property(nonatomic, strong)
-    SigninCoordinator* advancedSettingsSigninCoordinator;
-// Browser sign-in state to revert to in case sync is canceled.
-@property(nonatomic, assign) IdentitySigninState signinStateOnStart;
-// Sign-in identity when the coordiantor starts. This is used as the identity to
-// revert to in case sync is canceled.
-@property(nonatomic, strong) id<SystemIdentity> signinIdentityOnStart;
-
-@end
-
-@implementation SigninSyncCoordinator
-
-@synthesize baseNavigationController = _baseNavigationController;
-
-- (instancetype)initWithBaseNavigationController:
-                    (UINavigationController*)navigationController
-                                         browser:(Browser*)browser
-                                        delegate:(id<FirstRunScreenDelegate>)
-                                                     delegate {
-  self = [super initWithBaseViewController:navigationController
-                                   browser:browser];
-  if (self) {
-    DCHECK(!browser->GetBrowserState()->IsOffTheRecord());
-    _baseNavigationController = navigationController;
-    _delegate = delegate;
-    _policyWatcherObserverBridge =
-        std::make_unique<PolicyWatcherBrowserAgentObserverBridge>(self);
-
-    // Determine if the sign-in screen is used in First Run.
-    SceneState* sceneState =
-        SceneStateBrowserAgent::FromBrowser(self.browser)->GetSceneState();
-    AppState* appState = sceneState.appState;
-    _firstRun = appState.initStage == InitStageFirstRun;
-    _consentStringIDs = [NSMutableArray array];
-    // Make sure that the coordinator is only used for the FRE which is the
-    // only context that is supported at the moment. The coordinator may be
-    // used outside of the FRE but this case isn't supported yet.
-    DCHECK(_firstRun);
-  }
-  return self;
-}
-
-- (void)start {
-  ChromeBrowserState* browserState = self.browser->GetBrowserState();
-
-  AuthenticationService* authenticationService =
-      AuthenticationServiceFactory::GetForBrowserState(browserState);
-  self.signinIdentityOnStart =
-      authenticationService->GetPrimaryIdentity(signin::ConsentLevel::kSignin);
-
-  switch (authenticationService->GetServiceStatus()) {
-    case AuthenticationService::ServiceStatus::SigninForcedByPolicy:
-    case AuthenticationService::ServiceStatus::SigninAllowed:
-      break;
-    case AuthenticationService::ServiceStatus::SigninDisabledByUser:
-      // This case is rare. This can happen if sign-in is disabled by user,
-      // and FRE is forced by the flag for test reason.
-      self.attemptStatus = first_run::SignInAttemptStatus::NOT_ATTEMPTED;
-      [self finishPresentingAndSkipRemainingScreens:NO];
-      return;
-    case AuthenticationService::ServiceStatus::SigninDisabledByPolicy:
-      self.attemptStatus = first_run::SignInAttemptStatus::SKIPPED_BY_POLICY;
-      [self finishPresentingAndSkipRemainingScreens:NO];
-      return;
-    case AuthenticationService::ServiceStatus::SigninDisabledByInternal:
-      self.attemptStatus = first_run::SignInAttemptStatus::NOT_SUPPORTED;
-      [self finishPresentingAndSkipRemainingScreens:NO];
-      return;
-  }
-  syncer::SyncService* syncService =
-      SyncServiceFactory::GetForBrowserState(browserState);
-  if (IsSyncDisabledByPolicy(syncService)) {
-    // Skip the screen if sync is disabled by policy.
-    self.attemptStatus = first_run::SignInAttemptStatus::SKIPPED_BY_POLICY;
-    [self finishPresentingAndSkipRemainingScreens:NO];
-    return;
-  }
-
-  SyncSetupService* syncSetupService =
-      SyncSetupServiceFactory::GetForBrowserState(browserState);
-  if (syncSetupService->IsFirstSetupComplete()) {
-    // Skip the screen if sync is already enabled. Sync might be already
-    // enabled if the coordinator is used outside of the FRE OR when tests are
-    // performed with irregular states. We expect sync to be disabled when the
-    // FRE is displayed in a regular situation (i.e., first launch after
-    // install).
-    [self.delegate screenWillFinishPresenting];
-    return;
-  }
-
-  self.signinStateOnStart =
-      signin::GetPrimaryIdentitySigninState(self.browser->GetBrowserState());
-
-  PolicyWatcherBrowserAgent::FromBrowser(self.browser)
-      ->AddObserver(_policyWatcherObserverBridge.get());
-
-  self.viewController = [[SigninSyncViewController alloc] init];
-  self.viewController.delegate = self;
-  PrefService* prefService = browserState->GetPrefs();
-  self.viewController.enterpriseSignInRestrictions =
-      GetEnterpriseSignInRestrictions(authenticationService, prefService,
-                                      syncService);
-
-  self.accountManagerService =
-      ChromeAccountManagerServiceFactory::GetForBrowserState(browserState);
-
-  self.mediator = [[SigninSyncMediator alloc]
-      initWithAuthenticationService:authenticationService
-                    identityManager:IdentityManagerFactory::GetForBrowserState(
-                                        browserState)
-              accountManagerService:self.accountManagerService
-                     consentAuditor:ConsentAuditorFactory::GetForBrowserState(
-                                        browserState)
-                   syncSetupService:syncSetupService
-              unifiedConsentService:UnifiedConsentServiceFactory::
-                                        GetForBrowserState(browserState)
-                        syncService:syncService];
-  self.mediator.delegate = self;
-  self.mediator.selectedIdentity =
-      self.accountManagerService->GetDefaultIdentity();
-  self.hadIdentitiesAtStartup = self.accountManagerService->HasIdentities();
-
-  self.mediator.consumer = self.viewController;
-  BOOL animated = self.baseNavigationController.topViewController != nil;
-  [self.baseNavigationController setViewControllers:@[ self.viewController ]
-                                           animated:animated];
-  self.viewController.modalInPresentation = YES;
-
-  if (self.firstRun) {
-    base::UmaHistogramEnumeration("FirstRun.Stage",
-                                  first_run::kSyncScreenStart);
-  }
-}
-
-- (void)stop {
-  PolicyWatcherBrowserAgent::FromBrowser(self.browser)
-      ->RemoveObserver(_policyWatcherObserverBridge.get());
-
-  self.delegate = nil;
-  self.viewController = nil;
-  [self.mediator disconnect];
-  self.mediator = nil;
-  [self.identityChooserCoordinator stop];
-  self.identityChooserCoordinator = nil;
-
-  // If `_addAccountSigninCoordinator` or `_advancedSettingsSigninCoordinator`
-  // weren't stopped yet (which can happen when closing the scene), try to
-  // call -interruptWithAction: to properly tear down the coordinators.
-  SigninCoordinator* signinCoordinator = self.addAccountSigninCoordinator;
-  [self.addAccountSigninCoordinator
-      interruptWithAction:SigninCoordinatorInterruptActionNoDismiss
-               completion:^() {
-                 [signinCoordinator stop];
-               }];
-  self.addAccountSigninCoordinator = nil;
-  signinCoordinator = self.advancedSettingsSigninCoordinator;
-  [self.advancedSettingsSigninCoordinator
-      interruptWithAction:SigninCoordinatorInterruptActionNoDismiss
-               completion:^() {
-                 [signinCoordinator stop];
-               }];
-  self.advancedSettingsSigninCoordinator = nil;
-
-  [self.enterprisePromptCoordinator stop];
-  self.enterprisePromptCoordinator = nil;
-}
-
-#pragma mark - SigninSyncViewControllerDelegate
-
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-      showAccountPickerFromPoint:(CGPoint)point {
-  self.identityChooserCoordinator = [[IdentityChooserCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                         browser:self.browser];
-  self.identityChooserCoordinator.delegate = self;
-  self.identityChooserCoordinator.origin = point;
-  [self.identityChooserCoordinator start];
-  self.identityChooserCoordinator.selectedIdentity =
-      self.mediator.selectedIdentity;
-}
-
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-              addConsentStringID:(const int)stringID {
-  [self.consentStringIDs addObject:[NSNumber numberWithInt:stringID]];
-}
-
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-          logScrollButtonVisible:(BOOL)scrollButtonVisible
-        withAccountPickerVisible:(BOOL)accountButtonVisible {
-  first_run::FirstRunScreenType screenType =
-      accountButtonVisible
-          ? first_run::FirstRunScreenType::kSyncScreenWithIdentityPicker
-          : first_run::FirstRunScreenType::kSyncScreenWithoutIdentityPicker;
-  RecordFirstRunScrollButtonVisibilityMetrics(screenType, scrollButtonVisible);
-}
-
-#pragma mark - PromoStyleViewControllerDelegate
-
-- (void)didTapPrimaryActionButton {
-  if (self.mediator.selectedIdentity) {
-    [self startSync];
-  } else {
-    [self triggerAddAccount];
-  }
-}
-
-- (void)didTapSecondaryActionButton {
-  // Cancel sync and sign out the user if needed.
-  [self.mediator cancelSyncAndRestoreSigninState:self.signinStateOnStart
-                           signinIdentityOnStart:self.signinIdentityOnStart];
-}
-
-- (void)didTapURLInDisclaimer:(NSURL*)URL {
-  // Currently there is only one link to show sync settings in the disclaimer.
-  DCHECK(self.mediator.selectedIdentity);
-
-  AuthenticationFlow* authenticationFlow =
-      [[AuthenticationFlow alloc] initWithBrowser:self.browser
-                                         identity:self.mediator.selectedIdentity
-                                 postSignInAction:POST_SIGNIN_ACTION_NONE
-                         presentingViewController:self.viewController];
-  authenticationFlow.dispatcher = HandlerForProtocol(
-      self.browser->GetCommandDispatcher(), BrowsingDataCommands);
-
-  [self.mediator
-      prepareAdvancedSettingsWithAuthenticationFlow:authenticationFlow];
-}
-
-#pragma mark - IdentityChooserCoordinatorDelegate
-
-- (void)identityChooserCoordinatorDidClose:
-    (IdentityChooserCoordinator*)coordinator {
-  CHECK_EQ(self.identityChooserCoordinator, coordinator);
-  [self.identityChooserCoordinator stop];
-  self.identityChooserCoordinator = nil;
-}
-
-- (void)identityChooserCoordinatorDidTapOnAddAccount:
-    (IdentityChooserCoordinator*)coordinator {
-  CHECK_EQ(self.identityChooserCoordinator, coordinator);
-  DCHECK(!self.addAccountSigninCoordinator);
-
-  [self triggerAddAccount];
-}
-
-- (void)identityChooserCoordinator:(IdentityChooserCoordinator*)coordinator
-                 didSelectIdentity:(id<SystemIdentity>)identity {
-  CHECK_EQ(self.identityChooserCoordinator, coordinator);
-  self.mediator.selectedIdentity = identity;
-}
-
-#pragma mark - PolicyWatcherBrowserAgentObserving
-
-- (void)policyWatcherBrowserAgentNotifySignInDisabled:
-    (PolicyWatcherBrowserAgent*)policyWatcher {
-  if (self.addAccountSigninCoordinator) {
-    __weak __typeof(self) weakSelf = self;
-    [self.addAccountSigninCoordinator
-        interruptWithAction:SigninCoordinatorInterruptActionDismissWithAnimation
-                 completion:^{
-                   [weakSelf showSignedOutModal];
-                 }];
-  } else {
-    [self showSignedOutModal];
-  }
-}
-
-#pragma mark - EnterprisePromptCoordinatorDelegate
-
-- (void)hideEnterprisePrompForLearnMore:(BOOL)learnMore {
-  [self dismissSignedOutModalAndSkipScreens:learnMore];
-}
-
-#pragma mark - SigninSyncMediatorDelegate
-
-- (void)signinSyncMediatorDidSuccessfulyFinishSignin:
-    (SigninSyncMediator*)mediator {
-  if (self.firstRun) {
-    base::UmaHistogramEnumeration("FirstRun.Stage",
-                                  first_run::kSyncScreenCompletionWithSync);
-  }
-  [self finishPresentingAndSkipRemainingScreens:NO];
-}
-
-- (void)signinSyncMediatorDidSuccessfulyFinishSigninForAdvancedSettings:
-    (SigninSyncMediator*)mediator {
-  [self showAdvancedSettings];
-}
-
-- (void)signinSyncMediatorDidSuccessfulyFinishSignout:
-    (SigninSyncMediator*)mediator {
-  [self finishPresentingAndSkipRemainingScreens:NO];
-  if (self.firstRun) {
-    base::UmaHistogramEnumeration("FirstRun.Stage",
-                                  first_run::kSyncScreenCompletionWithoutSync);
-  }
-}
-
-#pragma mark - Private
-
-// Dismisses the Signed Out modal if it is still present and `skipScreens`.
-- (void)dismissSignedOutModalAndSkipScreens:(BOOL)skipScreens {
-  [self.enterprisePromptCoordinator stop];
-  self.enterprisePromptCoordinator = nil;
-  [self finishPresentingAndSkipRemainingScreens:skipScreens];
-}
-
-// Shows the modal letting the user know that they have been signed out.
-- (void)showSignedOutModal {
-  self.attemptStatus = first_run::SignInAttemptStatus::SKIPPED_BY_POLICY;
-  self.enterprisePromptCoordinator = [[EnterprisePromptCoordinator alloc]
-      initWithBaseViewController:self.viewController
-                         browser:self.browser
-                      promptType:EnterprisePromptTypeForceSignOut];
-  self.enterprisePromptCoordinator.delegate = self;
-  [self.enterprisePromptCoordinator start];
-}
-
-// Completes the presentation of the screen, recording the metrics and notifying
-// the delegate to skip the rest of the FRE if `skipRemainingScreens` is YES, or
-// to continue the FRE.
-- (void)finishPresentingAndSkipRemainingScreens:(BOOL)skipRemainingScreens {
-  signin::IdentityManager* identityManager =
-      IdentityManagerFactory::GetForBrowserState(
-          self.browser->GetBrowserState());
-  if (self.firstRun) {
-    RecordFirstRunSignInMetrics(identityManager, self.attemptStatus,
-                                self.hadIdentitiesAtStartup);
-  }
-
-  if (skipRemainingScreens) {
-    [self.delegate skipAllScreens];
-  } else {
-    [self.delegate screenWillFinishPresenting];
-  }
-}
-
-// Starts the coordinator to present the Add Account module.
-- (void)triggerAddAccount {
-  self.attemptStatus = first_run::SignInAttemptStatus::ATTEMPTED;
-
-  self.addAccountSigninCoordinator = [SigninCoordinator
-      addAccountCoordinatorWithBaseViewController:self.viewController
-                                          browser:self.browser
-                                      accessPoint:signin_metrics::AccessPoint::
-                                                      ACCESS_POINT_START_PAGE];
-
-  __weak __typeof(self) weakSelf = self;
-  self.addAccountSigninCoordinator.signinCompletion =
-      ^(SigninCoordinatorResult signinResult,
-        SigninCompletionInfo* signinCompletionInfo) {
-        [weakSelf addAccountSigninCompleteWithResult:signinResult
-                                      completionInfo:signinCompletionInfo];
-      };
-  [self.addAccountSigninCoordinator start];
-}
-
-// Callback handling the completion of the AddAccount action.
-- (void)addAccountSigninCompleteWithResult:(SigninCoordinatorResult)signinResult
-                            completionInfo:
-                                (SigninCompletionInfo*)signinCompletionInfo {
-  [self.addAccountSigninCoordinator stop];
-  self.addAccountSigninCoordinator = nil;
-  if (signinResult == SigninCoordinatorResultSuccess &&
-      self.accountManagerService->IsValidIdentity(
-          signinCompletionInfo.identity)) {
-    self.mediator.selectedIdentity = signinCompletionInfo.identity;
-    self.mediator.addedAccount = YES;
-  }
-}
-
-// Shows the advanced sync settings on top of the screen.
-- (void)showAdvancedSettings {
-  DCHECK(!self.advancedSettingsSigninCoordinator);
-
-  self.advancedSettingsSigninCoordinator = [SigninCoordinator
-      advancedSettingsSigninCoordinatorWithBaseViewController:
-          self.viewController
-                                                      browser:self.browser
-                                                  signinState:
-                                                      self.signinStateOnStart];
-  __weak __typeof(self) weakSelf = self;
-  self.advancedSettingsSigninCoordinator.signinCompletion =
-      ^(SigninCoordinatorResult advancedSigninResult,
-        SigninCompletionInfo* signinCompletionInfo) {
-        [weakSelf onAdvancedSettingsFinished];
-      };
-  [self.advancedSettingsSigninCoordinator start];
-}
-
-// Starts syncing.
-- (void)startSync {
-  DCHECK(self.mediator.selectedIdentity);
-
-  AuthenticationFlow* authenticationFlow =
-      [[AuthenticationFlow alloc] initWithBrowser:self.browser
-                                         identity:self.mediator.selectedIdentity
-                                 postSignInAction:POST_SIGNIN_ACTION_COMMIT_SYNC
-                         presentingViewController:self.viewController];
-  authenticationFlow.dispatcher = HandlerForProtocol(
-      self.browser->GetCommandDispatcher(), BrowsingDataCommands);
-
-  [self.mediator
-      startSyncWithConfirmationID:[self.viewController activateSyncButtonID]
-                       consentIDs:self.consentStringIDs
-               authenticationFlow:authenticationFlow];
-}
-
-// Called when advanced settings are dismissed/finished.
-- (void)onAdvancedSettingsFinished {
-  DCHECK(self.advancedSettingsSigninCoordinator);
-
-  [self.advancedSettingsSigninCoordinator stop];
-  self.advancedSettingsSigninCoordinator = nil;
-}
-
-@end
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h
deleted file mode 100644
index 5b3efe4..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h
+++ /dev/null
@@ -1,94 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_H_
-
-#import <Foundation/Foundation.h>
-
-#import "base/ios/block_types.h"
-#import "ios/chrome/browser/ui/authentication/signin/signin_constants.h"
-
-namespace consent_auditor {
-class ConsentAuditor;
-}
-
-namespace signin {
-class IdentityManager;
-}
-
-namespace unified_consent {
-class UnifiedConsentService;
-}
-
-namespace syncer {
-class SyncService;
-}
-
-@class AuthenticationFlow;
-class AuthenticationService;
-class ChromeAccountManagerService;
-@protocol SigninSyncConsumer;
-@protocol SigninSyncMediatorDelegate;
-class SyncSetupService;
-@protocol SystemIdentity;
-
-@interface SigninSyncMediator : NSObject
-
-// The designated initializer.
-- (instancetype)
-    initWithAuthenticationService:(AuthenticationService*)authenticationService
-                  identityManager:(signin::IdentityManager*)identityManager
-            accountManagerService:
-                (ChromeAccountManagerService*)accountManagerService
-                   consentAuditor:
-                       (consent_auditor::ConsentAuditor*)consentAuditor
-                 syncSetupService:(SyncSetupService*)syncSetupService
-            unifiedConsentService:
-                (unified_consent::UnifiedConsentService*)unifiedConsentService
-                      syncService:(syncer::SyncService*)syncService
-    NS_DESIGNATED_INITIALIZER;
-
-- (instancetype)init NS_UNAVAILABLE;
-
-// Consumer for this mediator.
-@property(nonatomic, weak) id<SigninSyncConsumer> consumer;
-
-// The identity currently selected.
-@property(nonatomic, strong) id<SystemIdentity> selectedIdentity;
-
-// Whether an account has been added. Must be set externally.
-@property(nonatomic, assign) BOOL addedAccount;
-
-// Delegate.
-@property(nonatomic, weak) id<SigninSyncMediatorDelegate> delegate;
-
-// Disconnect the mediator.
-- (void)disconnect;
-
-// Reverts the sign-in and sync operation if needed.
-// @param signinStateOnStart: Browser sign-in state when the coordinator starts.
-// @param signinIdentityOnStart: Sign-in identity when the coordinator starts.
-- (void)cancelSyncAndRestoreSigninState:(IdentitySigninState)signinStateOnStart
-                  signinIdentityOnStart:
-                      (id<SystemIdentity>)signinIdentityOnStart;
-
-// Starts the sync engine.
-// @param confirmationID: The confirmation string ID of sync.
-// @param consentIDs: The consent string IDs of sync screen.
-// @param authenticationFlow: the object used to manage the authentication flow.
-// @param advancedSyncSettingsLinkWasTapped: YES if the link to show the
-//   advance settings was used to start the sync.
-- (void)startSyncWithConfirmationID:(const int)confirmationID
-                         consentIDs:(NSArray<NSNumber*>*)consentIDs
-                 authenticationFlow:(AuthenticationFlow*)authenticationFlow;
-
-// Prepare for advanced settings before showing them.
-// @param authenticationFlow: the object used to manage the authentication flow.
-- (void)prepareAdvancedSettingsWithAuthenticationFlow:
-    (AuthenticationFlow*)authenticationFlow;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.mm
deleted file mode 100644
index c06c8ac..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.mm
+++ /dev/null
@@ -1,333 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h"
-
-#import "base/strings/sys_string_conversions.h"
-#import "components/consent_auditor/consent_auditor.h"
-#import "components/sync/driver/sync_service.h"
-#import "components/unified_consent/unified_consent_service.h"
-#import "ios/chrome/browser/signin/authentication_service.h"
-#import "ios/chrome/browser/signin/chrome_account_manager_service_observer_bridge.h"
-#import "ios/chrome/browser/signin/identity_manager_factory.h"
-#import "ios/chrome/browser/signin/system_identity.h"
-#import "ios/chrome/browser/sync/sync_setup_service.h"
-#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
-#import "ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h"
-#import "ios/chrome/browser/ui/authentication/signin/user_signin/logging/first_run_signin_logger.h"
-#import "ios/chrome/browser/ui/authentication/signin/user_signin/logging/user_signin_logger.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h"
-#import "ios/chrome/grit/ios_strings.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-@interface SigninSyncMediator () <ChromeAccountManagerServiceObserver> {
-  std::unique_ptr<ChromeAccountManagerServiceObserverBridge>
-      _accountManagerServiceObserver;
-}
-
-// Logger used to record sign in metrics.
-@property(nonatomic, strong) UserSigninLogger* logger;
-// Account manager service to retrieve Chrome identities.
-@property(nonatomic, assign) ChromeAccountManagerService* accountManagerService;
-// Authentication service for sign in.
-@property(nonatomic, assign) AuthenticationService* authenticationService;
-// Manager for user's Google identities.
-@property(nonatomic, assign) signin::IdentityManager* identityManager;
-// Auditor for user consent.
-@property(nonatomic, assign) consent_auditor::ConsentAuditor* consentAuditor;
-// Service to configure sync.
-@property(nonatomic, assign) SyncSetupService* syncSetupService;
-// Manager for user consent.
-@property(nonatomic, assign)
-    unified_consent::UnifiedConsentService* unifiedConsentService;
-// Manager for the authentication flow.
-@property(nonatomic, strong) AuthenticationFlow* authenticationFlow;
-// Sync service.
-@property(nonatomic, assign) syncer::SyncService* syncService;
-// Whether the setting screen was presented.
-@property(nonatomic, assign) BOOL settingsScreenShown;
-
-@end
-
-@implementation SigninSyncMediator
-
-- (instancetype)
-    initWithAuthenticationService:(AuthenticationService*)authenticationService
-                  identityManager:(signin::IdentityManager*)identityManager
-            accountManagerService:
-                (ChromeAccountManagerService*)accountManagerService
-                   consentAuditor:
-                       (consent_auditor::ConsentAuditor*)consentAuditor
-                 syncSetupService:(SyncSetupService*)syncSetupService
-            unifiedConsentService:
-                (unified_consent::UnifiedConsentService*)unifiedConsentService
-                      syncService:(syncer::SyncService*)syncService {
-  self = [super init];
-  if (self) {
-    DCHECK(accountManagerService);
-    DCHECK(authenticationService);
-
-    _authenticationService = authenticationService;
-    _identityManager = identityManager;
-    _accountManagerService = accountManagerService;
-    _consentAuditor = consentAuditor;
-    _syncSetupService = syncSetupService;
-    _unifiedConsentService = unifiedConsentService;
-    _syncService = syncService;
-
-    _accountManagerServiceObserver =
-        std::make_unique<ChromeAccountManagerServiceObserverBridge>(
-            self, _accountManagerService);
-
-    _logger = [[FirstRunSigninLogger alloc]
-          initWithPromoAction:signin_metrics::PromoAction::
-                                  PROMO_ACTION_NO_SIGNIN_PROMO
-        accountManagerService:accountManagerService];
-
-    [_logger logSigninStarted];
-  }
-  return self;
-}
-
-- (void)dealloc {
-  DCHECK(!self.accountManagerService);
-}
-
-- (void)disconnect {
-  [self.logger disconnect];
-  self.accountManagerService = nullptr;
-  _accountManagerServiceObserver.reset();
-}
-
-- (void)cancelSyncAndRestoreSigninState:(IdentitySigninState)signinStateOnStart
-                  signinIdentityOnStart:
-                      (id<SystemIdentity>)signinIdentityOnStart {
-  [self.consumer setUIEnabled:NO];
-  [self.authenticationFlow cancelAndDismissAnimated:NO];
-
-  self.syncService->GetUserSettings()->SetSyncRequested(false);
-  switch (signinStateOnStart) {
-    case IdentitySigninStateSignedOut: {
-      __weak __typeof(self) weakSelf = self;
-      self.authenticationService->SignOut(
-          signin_metrics::ProfileSignout::kAbortSignin,
-          /*force_clear_browsing_data=*/false, ^{
-            [weakSelf onSigninStateRestorationCompleted];
-          });
-      break;
-    }
-    case IdentitySigninStateSignedInWithSyncDisabled: {
-      DCHECK(!self.authenticationService->GetPrimaryIdentity(
-          signin::ConsentLevel::kSync));
-      if ([self.authenticationService->GetPrimaryIdentity(
-              signin::ConsentLevel::kSignin) isEqual:signinIdentityOnStart]) {
-        // Can't be synced in this option because sync has to be disabled.
-        _syncService->StopAndClear();
-        [self onSigninStateRestorationCompleted];
-      } else {
-        __weak __typeof(self) weakSelf = self;
-        self.authenticationService->SignOut(
-            signin_metrics::ProfileSignout::kAbortSignin,
-            /*force_clear_browsing_data=*/false, ^() {
-              [weakSelf
-                  signinWithIdentityOnStartAfterSignout:signinIdentityOnStart];
-            });
-      }
-      break;
-    }
-    case IdentitySigninStateSignedInWithSyncEnabled: {
-      // This view wouldn't be shown if sync is enabled, so this option
-      // shouldn't be reached.
-      NOTREACHED();
-      break;
-    }
-  }
-}
-
-- (void)signinWithIdentityOnStartAfterSignout:(id<SystemIdentity>)identity {
-  // Make sure the identity is still valid (for example, the identity
-  // can be removed by another application).
-  ChromeAccountManagerService* accountManagerService =
-      self.accountManagerService;
-  if (accountManagerService &&
-      accountManagerService->IsValidIdentity(identity)) {
-    AuthenticationService* authenticationService = self.authenticationService;
-    if (authenticationService) {
-      authenticationService->SignIn(identity);
-    }
-  }
-
-  [self onSigninStateRestorationCompleted];
-}
-
-- (void)startSyncWithConfirmationID:(const int)confirmationID
-                         consentIDs:(NSArray<NSNumber*>*)consentIDs
-                 authenticationFlow:(AuthenticationFlow*)authenticationFlow {
-  DCHECK(!self.authenticationFlow);
-
-  [self.consumer setUIEnabled:NO];
-
-  // Local copy to be captured to make sure that the updates don't propagate to
-  // the authentication flow when it is started.
-  NSArray<NSNumber*>* consentIDsCopy = [consentIDs copy];
-
-  self.authenticationFlow = authenticationFlow;
-  __weak __typeof(self) weakSelf = self;
-  [self.authenticationFlow startSignInWithCompletion:^(BOOL success) {
-    [weakSelf signinCompletedWithSuccess:success
-                          confirmationID:confirmationID
-                              consentIDs:consentIDsCopy];
-  }];
-}
-
-- (void)prepareAdvancedSettingsWithAuthenticationFlow:
-    (AuthenticationFlow*)authenticationFlow {
-  DCHECK(!self.authenticationFlow);
-
-  self.settingsScreenShown = YES;
-
-  [self.consumer setUIEnabled:NO];
-
-  self.authenticationFlow = authenticationFlow;
-  __weak __typeof(self) weakSelf = self;
-  [self.authenticationFlow startSignInWithCompletion:^(BOOL success) {
-    [weakSelf signinForAdvancedSettingsCompletedWithSuccess:success];
-  }];
-}
-
-#pragma mark - Properties
-
-- (void)setSelectedIdentity:(id<SystemIdentity>)selectedIdentity {
-  if ([_selectedIdentity isEqual:selectedIdentity])
-    return;
-  // nil is allowed only if there is no other identity.
-  DCHECK(selectedIdentity || !self.accountManagerService->HasIdentities());
-  _selectedIdentity = selectedIdentity;
-
-  [self updateConsumerIdentity];
-}
-
-- (void)setConsumer:(id<SigninSyncConsumer>)consumer {
-  if (consumer == _consumer)
-    return;
-  _consumer = consumer;
-
-  [self updateConsumerIdentity];
-}
-
-#pragma mark - ChromeAccountManagerServiceObserver
-
-- (void)identityListChanged {
-  if (!self.accountManagerService) {
-    return;
-  }
-
-  if (!self.accountManagerService->IsValidIdentity(self.selectedIdentity)) {
-    self.selectedIdentity = self.accountManagerService->GetDefaultIdentity();
-  }
-}
-
-- (void)identityUpdated:(id<SystemIdentity>)identity {
-  if ([self.selectedIdentity isEqual:identity]) {
-    [self updateConsumerIdentity];
-  }
-}
-
-#pragma mark - Private
-
-// Updates the identity displayed by the consumer.
-- (void)updateConsumerIdentity {
-  id<SystemIdentity> selectedIdentity = self.selectedIdentity;
-  if (!selectedIdentity) {
-    [self.consumer noIdentityAvailable];
-  } else {
-    UIImage* avatar = self.accountManagerService->GetIdentityAvatarWithIdentity(
-        selectedIdentity, IdentityAvatarSize::Regular);
-    [self.consumer setSelectedIdentityUserName:selectedIdentity.userFullName
-                                         email:selectedIdentity.userEmail
-                                     givenName:selectedIdentity.userGivenName
-                                        avatar:avatar];
-  }
-}
-
-// Callback used when the sign-in flow is complete, with/without `success`.
-- (void)signinCompletedWithSuccess:(BOOL)success
-                    confirmationID:(const int)confirmationID
-                        consentIDs:(NSArray<NSNumber*>*)consentIDs {
-  self.authenticationFlow = nil;
-  [self.consumer setActionToDone];
-
-  if (!success) {
-    return;
-  }
-
-  // TODO(crbug.com/1254359): Dedupe duplicated code, here and in
-  // user_signin_mediator.
-
-  [self.logger logSigninCompletedWithResult:SigninCoordinatorResultSuccess
-                               addedAccount:self.addedAccount
-                      advancedSettingsShown:self.settingsScreenShown];
-
-  // Set sync consent.
-  sync_pb::UserConsentTypes::SyncConsent syncConsent;
-  syncConsent.set_status(sync_pb::UserConsentTypes::ConsentStatus::
-                             UserConsentTypes_ConsentStatus_GIVEN);
-  DCHECK_NE(confirmationID, 0);
-  syncConsent.set_confirmation_grd_id(confirmationID);
-  DCHECK_NE(consentIDs.count, 0ul);
-  for (NSNumber* consentID in consentIDs) {
-    syncConsent.add_description_grd_ids([consentID intValue]);
-  }
-
-  // Set the account to enable sync for.
-  DCHECK(self.selectedIdentity);
-  id<SystemIdentity> selectedIdentity = self.selectedIdentity;
-  CoreAccountId coreAccountId = self.identityManager->PickAccountIdForAccount(
-      base::SysNSStringToUTF8(selectedIdentity.gaiaID),
-      base::SysNSStringToUTF8(selectedIdentity.userEmail));
-
-  self.consentAuditor->RecordSyncConsent(coreAccountId, syncConsent);
-  self.authenticationService->GrantSyncConsent(selectedIdentity);
-
-  self.unifiedConsentService->SetUrlKeyedAnonymizedDataCollectionEnabled(true);
-
-  // Turn on FirstSetupComplete flag after the authentication service has
-  // granted user consent to start Sync.
-  self.syncSetupService->SetFirstSetupComplete(
-      syncer::SyncFirstSetupCompleteSource::BASIC_FLOW);
-  self.syncSetupService->CommitSyncChanges();
-
-  [self.delegate signinSyncMediatorDidSuccessfulyFinishSignin:self];
-}
-
-// Callback used when the sign-in flow used for advanced settings is complete,
-// with/without `success`.
-- (void)signinForAdvancedSettingsCompletedWithSuccess:(BOOL)success {
-  self.authenticationFlow = nil;
-  [self.consumer setActionToDone];
-
-  if (!success) {
-    return;
-  }
-
-  // Sync has to be set as requested in order to display the preferences
-  // correctly and differentiate the special state where the user is signed
-  // in, but the sync feature can't start yet.
-  _syncService->GetUserSettings()->SetSyncRequested(true);
-
-  [self.delegate
-      signinSyncMediatorDidSuccessfulyFinishSigninForAdvancedSettings:self];
-}
-
-- (void)onSigninStateRestorationCompleted {
-  // Stop the loading overlay and call back to the coordinator.
-  [self.consumer setActionToDone];
-  [self.delegate signinSyncMediatorDidSuccessfulyFinishSignout:self];
-}
-
-@end
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h
deleted file mode 100644
index 800ab924..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_DELEGATE_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_DELEGATE_H_
-
-@class SigninSyncMediator;
-
-// Delegate for SigninSyncMediator.
-@protocol SigninSyncMediatorDelegate <NSObject>
-
-// Called when sign-in did successfully finish.
-- (void)signinSyncMediatorDidSuccessfulyFinishSignin:
-    (SigninSyncMediator*)signinSyncMediator;
-
-// Called when sign-in for advanced settings did successfully finish.
-- (void)signinSyncMediatorDidSuccessfulyFinishSigninForAdvancedSettings:
-    (SigninSyncMediator*)signinSyncMediator;
-
-// Called when revert the sign-in and sync operation if needed did successfully
-// finish.
-- (void)signinSyncMediatorDidSuccessfulyFinishSignout:
-    (SigninSyncMediator*)signinSyncMediator;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_MEDIATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_unittest.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_unittest.mm
deleted file mode 100644
index 5762c67..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_unittest.mm
+++ /dev/null
@@ -1,320 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator.h"
-
-#import "base/functional/callback_helpers.h"
-#import "base/run_loop.h"
-#import "base/test/ios/wait_util.h"
-#import "components/consent_auditor/consent_auditor.h"
-#import "components/consent_auditor/fake_consent_auditor.h"
-#import "components/signin/public/identity_manager/identity_manager.h"
-#import "components/sync/driver/sync_service.h"
-#import "components/sync/test/mock_sync_service.h"
-#import "components/unified_consent/pref_names.h"
-#import "ios/chrome/browser/application_context/application_context.h"
-#import "ios/chrome/browser/browser_state/test_chrome_browser_state.h"
-#import "ios/chrome/browser/consent_auditor/consent_auditor_factory.h"
-#import "ios/chrome/browser/consent_auditor/consent_auditor_test_utils.h"
-#import "ios/chrome/browser/main/test_browser.h"
-#import "ios/chrome/browser/signin/authentication_service.h"
-#import "ios/chrome/browser/signin/authentication_service_factory.h"
-#import "ios/chrome/browser/signin/chrome_account_manager_service.h"
-#import "ios/chrome/browser/signin/chrome_account_manager_service_factory.h"
-#import "ios/chrome/browser/signin/constants.h"
-#import "ios/chrome/browser/signin/fake_authentication_service_delegate.h"
-#import "ios/chrome/browser/signin/fake_system_identity.h"
-#import "ios/chrome/browser/signin/fake_system_identity_manager.h"
-#import "ios/chrome/browser/signin/identity_manager_factory.h"
-#import "ios/chrome/browser/signin/signin_util.h"
-#import "ios/chrome/browser/sync/mock_sync_service_utils.h"
-#import "ios/chrome/browser/sync/sync_service_factory.h"
-#import "ios/chrome/browser/sync/sync_setup_service.h"
-#import "ios/chrome/browser/sync/sync_setup_service_factory.h"
-#import "ios/chrome/browser/sync/sync_setup_service_mock.h"
-#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
-#import "ios/chrome/browser/ui/authentication/authentication_flow_performer.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_mediator_delegate.h"
-#import "ios/chrome/browser/unified_consent/unified_consent_service_factory.h"
-#import "ios/chrome/browser/web_state_list/web_state_list.h"
-#import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h"
-#import "ios/web/public/test/web_task_environment.h"
-#import "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#import "testing/platform_test.h"
-#import "third_party/ocmock/OCMock/OCMock.h"
-#import "third_party/ocmock/gtest_support.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-using base::test::ios::kWaitForActionTimeout;
-using base::test::ios::WaitUntilConditionOrTimeout;
-
-// Fake implementing the consumer protocol.
-@interface FakeSigninSyncConsumer : NSObject <SigninSyncConsumer>
-
-@property(nonatomic, assign) BOOL hidden;
-@property(nonatomic, copy) NSString* userName;
-@property(nonatomic, copy) NSString* email;
-@property(nonatomic, copy) NSString* givenName;
-@property(nonatomic, strong) UIImage* avatar;
-@property(nonatomic, assign) BOOL UIWasEnabled;
-
-@end
-
-@implementation FakeSigninSyncConsumer
-
-- (void)noIdentityAvailable {
-  self.hidden = YES;
-}
-
-- (void)setSelectedIdentityUserName:(NSString*)userName
-                              email:(NSString*)email
-                          givenName:(NSString*)givenName
-                             avatar:(UIImage*)avatar {
-  self.userName = userName;
-  self.email = email;
-  self.givenName = givenName;
-  self.avatar = avatar;
-}
-
-- (void)setUIEnabled:(BOOL)UIEnabled {
-  self.UIWasEnabled = UIEnabled;
-}
-
-- (void)setActionToDone {
-  self.UIWasEnabled = YES;
-}
-
-@end
-
-class SigninSyncMediatorTest : public PlatformTest {
- protected:
-  void SetUp() override {
-    PlatformTest::SetUp();
-    identity_ = [FakeSystemIdentity fakeIdentity1];
-    fake_system_identity_manager()->AddIdentity(identity_);
-    TestChromeBrowserState::Builder builder;
-    builder.AddTestingFactory(
-        AuthenticationServiceFactory::GetInstance(),
-        AuthenticationServiceFactory::GetDefaultFactory());
-    builder.AddTestingFactory(ConsentAuditorFactory::GetInstance(),
-                              base::BindRepeating(&BuildFakeConsentAuditor));
-    builder.AddTestingFactory(SyncServiceFactory::GetInstance(),
-                              base::BindRepeating(&CreateMockSyncService));
-    builder.AddTestingFactory(
-        SyncSetupServiceFactory::GetInstance(),
-        base::BindRepeating(&SyncSetupServiceMock::CreateKeyedService));
-
-    browser_state_ = builder.Build();
-    AuthenticationServiceFactory::CreateAndInitializeForBrowserState(
-        browser_state_.get(),
-        std::make_unique<FakeAuthenticationServiceDelegate>());
-    AuthenticationService* authentication_service =
-        AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
-    signin::IdentityManager* identity_manager =
-        IdentityManagerFactory::GetForBrowserState(browser_state_.get());
-    consent_auditor::ConsentAuditor* consent_auditor =
-        ConsentAuditorFactory::GetForBrowserState(browser_state_.get());
-    SyncSetupService* sync_setup_service =
-        SyncSetupServiceFactory::GetForBrowserState(browser_state_.get());
-    syncer::SyncService* sync_service =
-        SyncServiceFactory::GetForBrowserState(browser_state_.get());
-    ChromeAccountManagerService* account_manager_service =
-        ChromeAccountManagerServiceFactory::GetForBrowserState(
-            browser_state_.get());
-
-    mediator_ = [[SigninSyncMediator alloc]
-        initWithAuthenticationService:authentication_service
-                      identityManager:identity_manager
-                accountManagerService:account_manager_service
-                       consentAuditor:consent_auditor
-                     syncSetupService:sync_setup_service
-                unifiedConsentService:UnifiedConsentServiceFactory::
-                                          GetForBrowserState(
-                                              browser_state_.get())
-                          syncService:(syncer::SyncService*)sync_service];
-
-    consumer_ = [[FakeSigninSyncConsumer alloc] init];
-
-    sync_setup_service_mock_ =
-        static_cast<SyncSetupServiceMock*>(sync_setup_service);
-    sync_service_mock_ = static_cast<syncer::MockSyncService*>(sync_service);
-  }
-
-  void TearDown() override {
-    PlatformTest::TearDown();
-    [mediator_ disconnect];
-    browser_state_.reset();
-    fake_system_identity_manager()->WaitForServiceCallbacksToComplete();
-  }
-
-  FakeSystemIdentityManager* fake_system_identity_manager() {
-    return FakeSystemIdentityManager::FromSystemIdentityManager(
-        GetApplicationContext()->GetSystemIdentityManager());
-  }
-
-  web::WebTaskEnvironment task_environment_;
-  IOSChromeScopedTestingLocalState scoped_testing_local_state_;
-
-  SigninSyncMediator* mediator_;
-  std::unique_ptr<ChromeBrowserState> browser_state_;
-  FakeSigninSyncConsumer* consumer_;
-  id<SystemIdentity> identity_;
-  SyncSetupServiceMock* sync_setup_service_mock_;
-  syncer::MockSyncService* sync_service_mock_;
-};
-
-// Tests that setting the consumer after the selected identity is set is
-// correctly notifying the consumer.
-TEST_F(SigninSyncMediatorTest, TestSettingConsumerWithExistingIdentity) {
-  mediator_.selectedIdentity = identity_;
-  mediator_.consumer = consumer_;
-
-  EXPECT_EQ(identity_.userEmail, consumer_.email);
-  EXPECT_EQ(identity_.userFullName, consumer_.userName);
-  EXPECT_FALSE(consumer_.hidden);
-  UIImage* avatar = consumer_.avatar;
-  EXPECT_NE(nil, avatar);
-  CGSize expected_size =
-      GetSizeForIdentityAvatarSize(IdentityAvatarSize::Regular);
-  EXPECT_TRUE(CGSizeEqualToSize(expected_size, avatar.size));
-}
-
-// Tests that the consumer is correctly updated when the selected identity is
-// updated.
-TEST_F(SigninSyncMediatorTest, TestUpdatingSelectedIdentity) {
-  mediator_.consumer = consumer_;
-
-  EXPECT_EQ(nil, consumer_.email);
-  EXPECT_EQ(nil, consumer_.userName);
-  // True because the selected identity is nil.
-  EXPECT_TRUE(consumer_.hidden);
-  EXPECT_EQ(nil, consumer_.avatar);
-
-  consumer_.hidden = NO;
-  mediator_.selectedIdentity = identity_;
-
-  EXPECT_EQ(identity_.userEmail, consumer_.email);
-  EXPECT_EQ(identity_.userFullName, consumer_.userName);
-  EXPECT_FALSE(consumer_.hidden);
-  UIImage* avatar = consumer_.avatar;
-  EXPECT_NE(nil, avatar);
-  CGSize expected_size =
-      GetSizeForIdentityAvatarSize(IdentityAvatarSize::Regular);
-  EXPECT_TRUE(CGSizeEqualToSize(expected_size, avatar.size));
-}
-
-// Tests IdentityService observations of the identity list.
-TEST_F(SigninSyncMediatorTest, TestIdentityListChanged) {
-  mediator_.consumer = consumer_;
-
-  EXPECT_EQ(nil, consumer_.email);
-  EXPECT_EQ(nil, consumer_.userName);
-  // True because the selected identity is nil.
-  EXPECT_TRUE(consumer_.hidden);
-  EXPECT_EQ(nil, consumer_.avatar);
-
-  consumer_.hidden = NO;
-
-  // Adding an identity is selecting it.
-  fake_system_identity_manager()->AddIdentity(identity_);
-
-  EXPECT_EQ(identity_.userEmail, consumer_.email);
-  EXPECT_EQ(identity_.userFullName, consumer_.userName);
-  EXPECT_FALSE(consumer_.hidden);
-  UIImage* avatar = consumer_.avatar;
-  EXPECT_NE(nil, avatar);
-  CGSize expected_size =
-      GetSizeForIdentityAvatarSize(IdentityAvatarSize::Regular);
-  EXPECT_TRUE(CGSizeEqualToSize(expected_size, avatar.size));
-
-  // Removing all the identity is resetting the selected identity.
-  base::RunLoop run_loop;
-  fake_system_identity_manager()->ForgetIdentity(
-      identity_, base::IgnoreArgs<NSError*>(run_loop.QuitClosure()));
-  run_loop.Run();
-
-  EXPECT_TRUE(consumer_.hidden);
-}
-
-TEST_F(SigninSyncMediatorTest, TestStartSyncService) {
-  mediator_.selectedIdentity = identity_;
-  mediator_.consumer = consumer_;
-
-  NSMutableArray* consentStringIDs = [[NSMutableArray alloc] init];
-  [consentStringIDs addObject:@1];
-  [consentStringIDs addObject:@2];
-  [consentStringIDs addObject:@3];
-
-  AuthenticationService* authentication_service =
-      AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
-  id mock_flow = OCMClassMock([AuthenticationFlow class]);
-  OCMStub([mock_flow startSignInWithCompletion:[OCMArg any]])
-      .andDo(^(NSInvocation* invocation) {
-        __weak signin_ui::CompletionCallback block;
-        [invocation getArgument:&block atIndex:2];
-        authentication_service->SignIn(identity_);
-        block(YES);
-      });
-
-  EXPECT_CALL(
-      *sync_setup_service_mock_,
-      SetFirstSetupComplete(syncer::SyncFirstSetupCompleteSource::BASIC_FLOW));
-  [mediator_ startSyncWithConfirmationID:1
-                              consentIDs:consentStringIDs
-                      authenticationFlow:mock_flow];
-}
-
-// Tests the authentication flow for the mediator.
-TEST_F(SigninSyncMediatorTest, TestAuthenticationFlow) {
-  mediator_.consumer = consumer_;
-  mediator_.selectedIdentity = identity_;
-  consumer_.UIEnabled = YES;
-  // TestBrowser browser;
-
-  id mock_delegate = OCMProtocolMock(@protocol(SigninSyncMediatorDelegate));
-  id mock_flow = OCMClassMock([AuthenticationFlow class]);
-
-  mediator_.delegate = mock_delegate;
-
-  __block signin_ui::CompletionCallback completion = nil;
-
-  OCMStub([mock_flow startSignInWithCompletion:[OCMArg any]])
-      .andDo(^(NSInvocation* invocation) {
-        __weak signin_ui::CompletionCallback block;
-        [invocation getArgument:&block atIndex:2];
-        completion = [block copy];
-      });
-
-  EXPECT_EQ(nil, completion);
-  EXPECT_TRUE(consumer_.UIWasEnabled);
-
-  [mediator_ startSyncWithConfirmationID:1
-                              consentIDs:@[ @(1) ]
-                      authenticationFlow:mock_flow];
-
-  EXPECT_FALSE(consumer_.UIWasEnabled);
-  ASSERT_NE(nil, completion);
-
-  OCMExpect(
-      [mock_delegate signinSyncMediatorDidSuccessfulyFinishSignin:mediator_]);
-
-  EXPECT_FALSE(browser_state_->GetPrefs()->GetBoolean(
-      unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled));
-
-  AuthenticationService* authentication_service =
-      AuthenticationServiceFactory::GetForBrowserState(browser_state_.get());
-  authentication_service->SignIn(identity_);
-  // Simulate the signin completion being successful.
-  completion(YES);
-
-  EXPECT_TRUE(browser_state_->GetPrefs()->GetBoolean(
-      unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled));
-  EXPECT_TRUE(consumer_.UIWasEnabled);
-  EXPECT_OCMOCK_VERIFY(mock_delegate);
-}
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h
deleted file mode 100644
index 3df7e77..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_H_
-
-#import <UIKit/UIKit.h>
-
-#import "ios/chrome/browser/ui/authentication/authentication_flow.h"
-#import "ios/chrome/browser/ui/authentication/enterprise/enterprise_utils.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_consumer.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h"
-#import "ios/chrome/common/ui/promo_style/promo_style_view_controller.h"
-
-@interface SigninSyncViewController
-    : PromoStyleViewController <SigninSyncConsumer>
-
-@property(nonatomic, weak) id<SigninSyncViewControllerDelegate> delegate;
-
-@property(nonatomic, assign)
-    EnterpriseSignInRestrictions enterpriseSignInRestrictions;
-
-// The ID of the main button activating sync.
-@property(nonatomic, readonly) int activateSyncButtonID;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
deleted file mode 100644
index 4efd81d..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.mm
+++ /dev/null
@@ -1,490 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller.h"
-
-#import "base/strings/sys_string_conversions.h"
-#import "ios/chrome/browser/ui/authentication/authentication_constants.h"
-#import "ios/chrome/browser/ui/authentication/views/identity_button_control.h"
-#import "ios/chrome/browser/ui/elements/activity_overlay_view.h"
-#import "ios/chrome/browser/ui/settings/elements/enterprise_info_popover_view_controller.h"
-#import "ios/chrome/common/string_util.h"
-#import "ios/chrome/common/ui/colors/semantic_color_names.h"
-#import "ios/chrome/common/ui/elements/popover_label_view_controller.h"
-#import "ios/chrome/common/ui/util/constraints_ui_util.h"
-#import "ios/chrome/common/ui/util/text_view_util.h"
-#import "ios/chrome/grit/ios_google_chrome_strings.h"
-#import "ios/chrome/grit/ios_strings.h"
-#import "net/base/mac/url_conversions.h"
-#import "ui/base/l10n/l10n_util.h"
-#import "url/gurl.h"
-
-#if !defined(__has_feature) || !__has_feature(objc_arc)
-#error "This file requires ARC support."
-#endif
-
-namespace {
-
-// Width of the identity control.
-constexpr CGFloat kIdentityControlMarginDefault = 16;
-
-// URL for the Settings link.
-const char* const kSettingsSyncURL = "internal://settings-sync";
-
-// URL for the learn more text.
-// Need to set a value so the delegate gets called.
-NSString* const kLearnMoreUrl = @"internal://learn-more";
-
-NSString* const kLearnMoreTextViewAccessibilityIdentifier =
-    @"kLearnMoreTextViewAccessibilityIdentifier";
-
-}  // namespace
-
-@interface SigninSyncViewController ()
-
-// Button controlling the display of the selected identity.
-@property(nonatomic, strong) IdentityButtonControl* identityControl;
-
-// Layout guide determining the area for the identity control.
-@property(nonatomic, strong) UILayoutGuide* identityControlArea;
-
-// Scrim displayed above the view when the UI is disabled.
-@property(nonatomic, strong) ActivityOverlayView* overlay;
-
-// Text view that displays an attributed string with the "Learn More" link that
-// opens a popover.
-@property(nonatomic, strong) UITextView* learnMoreTextView;
-
-// Popover shown when "Details" link is tapped.
-@property(nonatomic, strong)
-    EnterpriseInfoPopoverViewController* bubbleViewController;
-
-// Bottom constraint of the identity control area.
-@property(nonatomic, strong)
-    NSLayoutConstraint* identityControlAreaBottomConstraint;
-
-// YES when the sign-in or sign out action is done.
-@property(nonatomic, assign) BOOL signinSignoutActionDone;
-
-// YES when spinner overlay animation is done.
-@property(nonatomic, assign) BOOL overlayAnimationDone;
-
-@end
-
-@implementation SigninSyncViewController
-@dynamic delegate;
-
-#pragma mark - Public
-
-- (void)viewDidLoad {
-  self.view.accessibilityIdentifier = kSigninSyncScreenAccessibilityIdentifier;
-  self.isTallBanner = NO;
-  self.scrollToEndMandatory = YES;
-  self.readMoreString =
-      l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SCREEN_READ_MORE);
-
-  [self.delegate signinSyncViewController:self
-                       addConsentStringID:[self titleTextID]];
-  self.titleText = l10n_util::GetNSString([self titleTextID]);
-
-  [self.delegate signinSyncViewController:self
-                       addConsentStringID:[self subtitleTextID]];
-  self.subtitleText = l10n_util::GetNSString([self subtitleTextID]);
-
-  if (!self.primaryActionString) {
-    // `primaryActionString` could already be set using the consumer methods.
-    self.primaryActionString =
-        l10n_util::GetNSString(IDS_IOS_FIRST_RUN_SIGNIN_SIGN_IN_ACTION);
-  }
-  // Set the consent ID associated with the primary action string to
-  // `self.activateSyncButtonID` regardless of its current value because this
-  // is the only string that will be used in the button when enabling sync.
-  [self.delegate signinSyncViewController:self
-                       addConsentStringID:self.activateSyncButtonID];
-
-  [self.specificContentView addSubview:self.identityControl];
-  [self.specificContentView addLayoutGuide:self.identityControlArea];
-
-  // Add the Learn More text label if there are enterprise sign-in or sync
-  // restrictions.
-  if (self.enterpriseSignInRestrictions != kNoEnterpriseRestriction) {
-    self.learnMoreTextView.delegate = self;
-    [self.specificContentView addSubview:self.learnMoreTextView];
-
-    [NSLayoutConstraint activateConstraints:@[
-      [self.learnMoreTextView.bottomAnchor
-          constraintEqualToAnchor:self.specificContentView.bottomAnchor],
-      [self.learnMoreTextView.centerXAnchor
-          constraintEqualToAnchor:self.specificContentView.centerXAnchor],
-      [self.learnMoreTextView.widthAnchor
-          constraintLessThanOrEqualToAnchor:self.specificContentView
-                                                .widthAnchor],
-    ]];
-  }
-
-  self.bannerName = @"sync_screen_banner";
-  self.secondaryActionString =
-      l10n_util::GetNSString([self secondaryActionStringID]);
-
-  // Set constraints specific to the identity control button that don't change.
-  NSLayoutConstraint* areaWidthConstraint = [self.identityControl.widthAnchor
-      constraintEqualToAnchor:self.specificContentView.widthAnchor];
-  areaWidthConstraint.priority = UILayoutPriorityDefaultHigh;
-  [NSLayoutConstraint activateConstraints:@[
-    [self.identityControlArea.centerXAnchor
-        constraintEqualToAnchor:self.identityControlArea.owningView
-                                    .centerXAnchor],
-    [self.identityControlArea.widthAnchor
-        constraintLessThanOrEqualToAnchor:self.identityControlArea.owningView
-                                              .widthAnchor],
-    [self.identityControlArea.topAnchor
-        constraintEqualToAnchor:self.identityControl.topAnchor
-                       constant:0],
-    areaWidthConstraint,
-    [self.identityControl.widthAnchor
-        constraintEqualToAnchor:self.identityControlArea.widthAnchor],
-    [self.identityControl.centerXAnchor
-        constraintEqualToAnchor:self.identityControlArea.centerXAnchor],
-    [self.identityControlArea.topAnchor
-        constraintEqualToAnchor:self.specificContentView.topAnchor],
-    [self.identityControlArea.bottomAnchor
-        constraintLessThanOrEqualToAnchor:self.specificContentView
-                                              .bottomAnchor],
-  ]];
-  if (self.enterpriseSignInRestrictions != kNoEnterpriseRestriction) {
-    [self.learnMoreTextView.topAnchor
-        constraintGreaterThanOrEqualToAnchor:self.identityControlArea
-                                                 .bottomAnchor]
-        .active = YES;
-  }
-
-  [self.delegate signinSyncViewController:self
-                       addConsentStringID:[self disclaimerTextID]];
-  if (self.identityControl.hidden) {
-    // Since no one is logged in, the word "settings" should not be linkable;
-    // retrieve raw text from the string with tags.
-    self.disclaimerText =
-        ParseStringWithLinks(l10n_util::GetNSString([self disclaimerTextID]))
-            .string;
-    self.disclaimerURLs = [NSArray array];
-  } else {
-    self.disclaimerText = l10n_util::GetNSString([self disclaimerTextID]);
-    self.disclaimerURLs = @[ net::NSURLWithGURL(GURL(kSettingsSyncURL)) ];
-  }
-
-  [self updateIdentityControlButtonVerticalLayout];
-
-  // Call super after setting up the strings and others, as required per super
-  // class.
-  [super viewDidLoad];
-}
-
-- (void)viewDidAppear:(BOOL)animated {
-  [super viewDidAppear:animated];
-  [self.delegate signinSyncViewController:self
-                   logScrollButtonVisible:!self.didReachBottom
-                 withAccountPickerVisible:!self.identityControl.hidden];
-}
-
-- (void)traitCollectionDidChange:(UITraitCollection*)previousTraitCollection {
-  [super traitCollectionDidChange:previousTraitCollection];
-
-  // Close popover when font size changed for accessibility because it does not
-  // resize properly and the arrow is not aligned.
-  if (self.bubbleViewController) {
-    [self.bubbleViewController dismissViewControllerAnimated:YES
-                                                  completion:nil];
-  }
-}
-
-#pragma mark - Properties
-
-- (void)setOverlayAnimationDone:(BOOL)overlayAnimationDone {
-  _overlayAnimationDone = overlayAnimationDone;
-  if (_overlayAnimationDone) {
-    [self setUIEnabled:YES];
-  }
-}
-
-- (IdentityButtonControl*)identityControl {
-  if (!_identityControl) {
-    _identityControl = [[IdentityButtonControl alloc] initWithFrame:CGRectZero];
-    _identityControl.translatesAutoresizingMaskIntoConstraints = NO;
-    [_identityControl addTarget:self
-                         action:@selector(identityButtonControlTapped:forEvent:)
-               forControlEvents:UIControlEventTouchUpInside];
-
-    // Setting the content hugging priority isn't working, so creating a
-    // low-priority constraint to make sure that the view is as small as
-    // possible.
-    NSLayoutConstraint* heightConstraint =
-        [_identityControl.heightAnchor constraintEqualToConstant:0];
-    heightConstraint.priority = UILayoutPriorityDefaultLow - 1;
-    heightConstraint.active = YES;
-  }
-  return _identityControl;
-}
-
-- (UILayoutGuide*)identityControlArea {
-  if (!_identityControlArea) {
-    _identityControlArea = [[UILayoutGuide alloc] init];
-  }
-  return _identityControlArea;
-}
-
-- (ActivityOverlayView*)overlay {
-  if (!_overlay) {
-    _overlay = [[ActivityOverlayView alloc] init];
-    _overlay.translatesAutoresizingMaskIntoConstraints = NO;
-  }
-  return _overlay;
-}
-
-- (UITextView*)learnMoreTextView {
-  if (!_learnMoreTextView) {
-    _learnMoreTextView = CreateUITextViewWithTextKit1();
-    _learnMoreTextView.backgroundColor = UIColor.clearColor;
-    _learnMoreTextView.scrollEnabled = NO;
-    _learnMoreTextView.editable = NO;
-    _learnMoreTextView.adjustsFontForContentSizeCategory = YES;
-    _learnMoreTextView.textContainerInset = UIEdgeInsetsZero;
-    _learnMoreTextView.textContainer.lineFragmentPadding = 0;
-    _learnMoreTextView.accessibilityIdentifier =
-        kLearnMoreTextViewAccessibilityIdentifier;
-
-    _learnMoreTextView.linkTextAttributes =
-        @{NSForegroundColorAttributeName : [UIColor colorNamed:kBlueColor]};
-    _learnMoreTextView.translatesAutoresizingMaskIntoConstraints = NO;
-
-    NSMutableParagraphStyle* paragraphStyle =
-        [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
-    paragraphStyle.alignment = NSTextAlignmentCenter;
-
-    NSDictionary* textAttributes = @{
-      NSForegroundColorAttributeName : [UIColor colorNamed:kTextSecondaryColor],
-      NSFontAttributeName :
-          [UIFont preferredFontForTextStyle:UIFontTextStyleCaption2],
-      NSParagraphStyleAttributeName : paragraphStyle
-    };
-
-    NSDictionary* linkAttributes =
-        @{NSLinkAttributeName : [NSURL URLWithString:kLearnMoreUrl]};
-
-    NSAttributedString* learnMoreTextAttributedString =
-        AttributedStringFromStringWithLink(
-            l10n_util::GetNSString(IDS_IOS_ENTERPRISE_MANAGED_SIGNIN_DETAILS),
-            textAttributes, linkAttributes);
-
-    _learnMoreTextView.attributedText = learnMoreTextAttributedString;
-  }
-  return _learnMoreTextView;
-}
-
-// Returns the ID of the string of the button that is used to activate sync.
-- (int)activateSyncButtonID {
-  return IDS_IOS_ACCOUNT_UNIFIED_CONSENT_OK_BUTTON;
-}
-
-#pragma mark - SignInSyncConsumer
-
-- (void)setSelectedIdentityUserName:(NSString*)userName
-                              email:(NSString*)email
-                          givenName:(NSString*)givenName
-                             avatar:(UIImage*)avatar {
-  DCHECK(email);
-  DCHECK(avatar);
-  [self updateUIForIdentityAvailable:YES];
-  [self.identityControl setIdentityName:userName email:email];
-  [self.identityControl setIdentityAvatar:avatar];
-}
-
-- (void)noIdentityAvailable {
-  [self updateUIForIdentityAvailable:NO];
-}
-
-- (void)setUIEnabled:(BOOL)UIEnabled {
-  if (UIEnabled) {
-    // Only remove the overlay when both the action and the animation are done.
-    if (self.signinSignoutActionDone && self.overlayAnimationDone) {
-      [self.overlay removeFromSuperview];
-    }
-  } else {
-    // Handling the sign-in or sign out action and start the fade-in effect
-    // along with the spinner animation.
-    self.signinSignoutActionDone = NO;
-    self.overlayAnimationDone = NO;
-
-    self.overlay.indicator.alpha = 0.0;
-    [self.view addSubview:self.overlay];
-    AddSameConstraints(self.view, self.overlay);
-    [self.overlay.indicator startAnimating];
-    [UIView animateWithDuration:0.2
-        animations:^{
-          self.overlay.indicator.alpha = 1.0;
-        }
-        completion:^(BOOL finished) {
-          self.overlayAnimationDone = YES;
-        }];
-  }
-}
-
-- (void)setActionToDone {
-  self.signinSignoutActionDone = YES;
-  [self setUIEnabled:YES];
-}
-
-#pragma mark - Private
-
-// Callback for `identityControl`.
-- (void)identityButtonControlTapped:(id)sender forEvent:(UIEvent*)event {
-  UITouch* touch = event.allTouches.anyObject;
-  [self.delegate signinSyncViewController:self
-               showAccountPickerFromPoint:[touch locationInView:nil]];
-}
-
-// Updates the UI to adapt for `identityAvailable` or not.
-- (void)updateUIForIdentityAvailable:(BOOL)identityAvailable {
-  self.identityControl.hidden = !identityAvailable;
-  [self updateIdentityControlButtonVerticalLayout];
-  if (identityAvailable) {
-    self.primaryActionString =
-        l10n_util::GetNSString(self.activateSyncButtonID);
-    self.disclaimerText = l10n_util::GetNSString([self disclaimerTextID]);
-    self.disclaimerURLs = @[ net::NSURLWithGURL(GURL(kSettingsSyncURL)) ];
-  } else {
-    self.primaryActionString =
-        l10n_util::GetNSString(IDS_IOS_ACCOUNT_UNIFIED_CONSENT_ADD_ACCOUNT);
-    // Since no one is logged in, the word "settings" should not be linkable.
-    self.disclaimerText =
-        ParseStringWithLinks(l10n_util::GetNSString([self disclaimerTextID]))
-            .string;
-    self.disclaimerURLs = [NSArray array];
-  }
-}
-
-// Appends `restrictionString` to `existingString`, adding padding if needed.
-- (void)appendRestrictionString:(NSString*)restrictionString
-                       toString:(NSMutableString*)existingString {
-  NSString* padding = @"\n\n";
-  if ([existingString length])
-    [existingString appendString:padding];
-  [existingString appendString:restrictionString];
-}
-
-// Returns the title string ID.
-- (int)titleTextID {
-  return IDS_IOS_ACCOUNT_UNIFIED_CONSENT_TITLE;
-}
-
-// Returns the subtitle string ID.
-- (int)subtitleTextID {
-  return IDS_IOS_ACCOUNT_UNIFIED_CONSENT_SYNC_TITLE;
-}
-
-// Returns the secondary action string ID.
-- (int)secondaryActionStringID {
-  return IDS_IOS_FIRST_RUN_DEFAULT_BROWSER_SCREEN_SECONDARY_ACTION;
-}
-
-// Returns the disclaimer text string ID.
-- (int)disclaimerTextID {
-  return IDS_IOS_FIRST_RUN_SYNC_SCREEN_CONTENT_WITH_LINK_TO_SETTINGS;
-}
-
-// Updates the vertical layout of the identity control button according to its
-// visibility.
-- (void)updateIdentityControlButtonVerticalLayout {
-  if (!self.viewLoaded) {
-    // Don't update the constraints when the view isn't yet loaded because the
-    // view tree as to be properly set before updating the constraints.
-    return;
-  }
-
-  BOOL hidden = self.identityControl.hidden;
-
-  // Clear constraint from the previous state.
-  self.identityControlAreaBottomConstraint.active = NO;
-
-  // Set the bottom margin between the area and identity control view to match
-  // the state of the UI.
-  int bottomMargin = kIdentityControlMarginDefault;
-  if (!hidden) {
-    if (self.enterpriseSignInRestrictions == kNoEnterpriseRestriction) {
-      // Remove the bottom margin when the identity control is in bottom and
-      // visible.
-      bottomMargin = 0;
-    }
-  }
-
-  // Limit the area to a specific height when the identity control is hidden.
-  NSLayoutAnchor* bottomAnchor = hidden ? self.identityControlArea.topAnchor
-                                        : self.identityControl.bottomAnchor;
-
-  self.identityControlAreaBottomConstraint =
-      [self.identityControlArea.bottomAnchor
-          constraintEqualToAnchor:bottomAnchor
-                         constant:bottomMargin];
-  self.identityControlAreaBottomConstraint.active = YES;
-}
-
-#pragma mark - UITextViewDelegate
-
-- (BOOL)textView:(UITextView*)textView
-    shouldInteractWithURL:(NSURL*)URL
-                  inRange:(NSRange)characterRange
-              interaction:(UITextItemInteraction)interaction {
-  if (textView != self.learnMoreTextView) {
-    // The text view being tapped is not the learnMoreTextView. Defer to the
-    // handler in the superclass.
-    [super textView:textView
-        shouldInteractWithURL:URL
-                      inRange:characterRange
-                  interaction:interaction];
-    return NO;
-  }
-  DCHECK(textView == self.learnMoreTextView);
-
-  NSMutableString* detailsMessage = [[NSMutableString alloc] init];
-  if (self.enterpriseSignInRestrictions & kEnterpriseForceSignIn) {
-    [self appendRestrictionString:l10n_util::GetNSString(
-                                      IDS_IOS_ENTERPRISE_FORCED_SIGNIN_MESSAGE)
-                         toString:detailsMessage];
-  }
-  if (self.enterpriseSignInRestrictions & kEnterpriseRestrictAccounts) {
-    [self appendRestrictionString:
-              l10n_util::GetNSString(
-                  IDS_IOS_ENTERPRISE_RESTRICTED_ACCOUNTS_TO_PATTERNS_MESSAGE)
-                         toString:detailsMessage];
-  }
-  if (self.enterpriseSignInRestrictions & kEnterpriseSyncTypesListDisabled) {
-    [self appendRestrictionString:l10n_util::GetNSString(
-                                      IDS_IOS_ENTERPRISE_MANAGED_SYNC)
-                         toString:detailsMessage];
-  }
-
-  // Open signin popover.
-  self.bubbleViewController = [[EnterpriseInfoPopoverViewController alloc]
-             initWithMessage:detailsMessage
-              enterpriseName:nil  // TODO(crbug.com/1251986): Remove this
-                                  // variable.
-      isPresentingFromButton:NO
-            addLearnMoreLink:NO];
-  [self presentViewController:self.bubbleViewController
-                     animated:YES
-                   completion:nil];
-
-  // Set the anchor and arrow direction of the bubble.
-  self.bubbleViewController.popoverPresentationController.sourceView =
-      self.learnMoreTextView;
-  self.bubbleViewController.popoverPresentationController.sourceRect =
-      TextViewLinkBound(textView, characterRange);
-  self.bubbleViewController.popoverPresentationController
-      .permittedArrowDirections =
-      UIPopoverArrowDirectionUp | UIPopoverArrowDirectionDown;
-
-  // The handler is already handling the tap.
-  return NO;
-}
-
-@end
diff --git a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h b/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h
deleted file mode 100644
index c91ea5c3..0000000
--- a/ios/chrome/browser/ui/authentication/signin_sync/signin_sync_view_controller_delegate.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2021 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_DELEGATE_H_
-#define IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_DELEGATE_H_
-
-#import "ios/chrome/common/ui/promo_style/promo_style_view_controller.h"
-
-@class SigninSyncViewController;
-
-// Delegate of sign-in screen view controller.
-@protocol SigninSyncViewControllerDelegate <PromoStyleViewControllerDelegate>
-
-// Called when the user taps to see the account picker.
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-      showAccountPickerFromPoint:(CGPoint)point;
-
-// Adds consent string ID.
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-              addConsentStringID:(const int)stringID;
-
-// Logs scrollability metric on view appears.
-- (void)signinSyncViewController:
-            (SigninSyncViewController*)signinSyncViewController
-          logScrollButtonVisible:(BOOL)scrollButtonVisible
-        withAccountPickerVisible:(BOOL)accountButtonVisible;
-
-@end
-
-#endif  // IOS_CHROME_BROWSER_UI_AUTHENTICATION_SIGNIN_SYNC_SIGNIN_SYNC_VIEW_CONTROLLER_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
index da0a58f..61ca80f2 100644
--- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
+++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -2041,6 +2041,7 @@
   // TODO(crbug.com/1403957): Move AutofillTabHelper logic inside
   // TabLifecycleMediator.
   if (AutofillTabHelper::FromWebState(webState)) {
+    DCHECK(self.viewController);
     AutofillTabHelper::FromWebState(webState)->SetBaseViewController(
         self.viewController);
   }
@@ -2048,6 +2049,7 @@
   // TODO(crbug.com/1403959): Move PrintTabHelper logic inside
   // TabLifecycleMediator.
   if (PrintTabHelper::FromWebState(webState)) {
+    DCHECK(self.printController);
     PrintTabHelper::FromWebState(webState)->set_printer(self.printController);
   }
 
@@ -2059,6 +2061,7 @@
   // TabLifecycleMediator.
   FollowTabHelper* followTabHelper = FollowTabHelper::FromWebState(webState);
   if (followTabHelper) {
+    DCHECK(self.followIPHCoordinator);
     followTabHelper->set_follow_iph_presenter(self.followIPHCoordinator);
   }
 
@@ -2067,6 +2070,7 @@
   if (CaptivePortalTabHelper::FromWebState(webState)) {
     TabInsertionBrowserAgent* insertionAgent =
         TabInsertionBrowserAgent::FromBrowser(self.browser);
+    DCHECK(insertionAgent);
     CaptivePortalTabHelper::FromWebState(webState)->SetTabInsertionBrowserAgent(
         insertionAgent);
   }
@@ -2080,6 +2084,7 @@
   // TODO(crbug.com/1403967): Move AnnotationsTabHelper logic inside
   // TabLifecycleMediator.
   if (AnnotationsTabHelper::FromWebState(webState)) {
+    DCHECK(self.viewController);
     AnnotationsTabHelper::FromWebState(webState)->SetBaseViewController(
         self.viewController);
   }
@@ -2089,6 +2094,7 @@
   PriceNotificationsTabHelper* priceNotificationsTabHelper =
       PriceNotificationsTabHelper::FromWebState(webState);
   if (priceNotificationsTabHelper) {
+    DCHECK(self.priceNotificationsIPHCoordinator);
     priceNotificationsTabHelper->SetPriceNotificationsIPHPresenter(
         self.priceNotificationsIPHCoordinator);
   }
diff --git a/ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.mm b/ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.mm
index eefa133..ddd73e6 100644
--- a/ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.mm
+++ b/ios/chrome/browser/ui/browser_view/tab_lifecycle_mediator.mm
@@ -89,18 +89,24 @@
   // Only realized webstates should have dependencies installed.
   DCHECK(webState->IsRealized());
 
+  DCHECK(_snapshotGeneratorDelegate);
   SnapshotTabHelper::FromWebState(webState)->SetDelegate(
       _snapshotGeneratorDelegate);
 
   if (PasswordTabHelper* passwordTabHelper =
           PasswordTabHelper::FromWebState(webState)) {
+    DCHECK(_baseViewController);
+    DCHECK(_delegate);
+    DCHECK(_commandDispatcher);
     passwordTabHelper->SetBaseViewController(_baseViewController);
     passwordTabHelper->SetPasswordControllerDelegate(_delegate);
     passwordTabHelper->SetDispatcher(_commandDispatcher);
   }
 
+  DCHECK(_delegate);
   OverscrollActionsTabHelper::FromWebState(webState)->SetDelegate(_delegate);
 
+  DCHECK(_sideSwipeController);
   web_deprecated::SetSwipeRecognizerProvider(webState, _sideSwipeController);
 
   // DownloadManagerTabHelper cannot function without its delegate.
@@ -108,10 +114,12 @@
   DownloadManagerTabHelper::FromWebState(webState)->SetDelegate(
       _downloadManagerCoordinator);
 
+  DCHECK(_tabHelperDelegate);
   NetExportTabHelper::FromWebState(webState)->SetDelegate(_tabHelperDelegate);
 
   id<WebContentCommands> webContentsHandler =
       HandlerForProtocol(_commandDispatcher, WebContentCommands);
+  DCHECK(webContentsHandler);
   ITunesUrlsHandlerTabHelper::FromWebState(webState)->SetWebContentsHandler(
       webContentsHandler);
   PassKitTabHelper::FromWebState(webState)->SetWebContentsHandler(
diff --git a/ios/chrome/browser/ui/first_run/BUILD.gn b/ios/chrome/browser/ui/first_run/BUILD.gn
index e175211..29ecfe4 100644
--- a/ios/chrome/browser/ui/first_run/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/BUILD.gn
@@ -83,7 +83,6 @@
     "//ios/chrome/browser/ui/authentication/signin",
     "//ios/chrome/browser/ui/authentication/signin/add_account_signin",
     "//ios/chrome/browser/ui/authentication/signin/user_signin/logging",
-    "//ios/chrome/browser/ui/authentication/signin_sync",
     "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser",
     "//ios/chrome/browser/ui/authentication/views",
     "//ios/chrome/browser/ui/commands",
diff --git a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
index 5421ee05..a31400fe 100644
--- a/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_coordinator.mm
@@ -12,7 +12,6 @@
 #import "ios/chrome/browser/browser_state/chrome_browser_state.h"
 #import "ios/chrome/browser/first_run/first_run_metrics.h"
 #import "ios/chrome/browser/main/browser.h"
-#import "ios/chrome/browser/ui/authentication/signin_sync/signin_sync_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/default_browser/default_browser_screen_coordinator.h"
 #import "ios/chrome/browser/ui/first_run/first_run_screen_delegate.h"
 #import "ios/chrome/browser/ui/first_run/first_run_util.h"
@@ -144,11 +143,6 @@
           initWithBaseNavigationController:self.navigationController
                                    browser:self.browser
                                   delegate:self];
-    case kSignInAndSync_DEPRECATED:
-      return [[SigninSyncCoordinator alloc]
-          initWithBaseNavigationController:self.navigationController
-                                   browser:self.browser
-                                  delegate:self];
     case kDefaultBrowserPromo:
       return [[DefaultBrowserScreenCoordinator alloc]
           initWithBaseNavigationController:self.navigationController
diff --git a/ios/chrome/browser/ui/first_run/first_run_util.mm b/ios/chrome/browser/ui/first_run/first_run_util.mm
index 28afc414..4c46509 100644
--- a/ios/chrome/browser/ui/first_run/first_run_util.mm
+++ b/ios/chrome/browser/ui/first_run/first_run_util.mm
@@ -117,16 +117,6 @@
                                 "SignInScreenWithoutFooterOrIdentityPicker",
                                 scroll_button_visible);
       break;
-    case first_run::FirstRunScreenType::kSyncScreenWithoutIdentityPicker:
-      base::UmaHistogramBoolean(
-          "IOS.FirstRun.ScrollButtonVisible.SyncScreenWithoutIdentityPicker",
-          scroll_button_visible);
-      break;
-    case first_run::FirstRunScreenType::kSyncScreenWithIdentityPicker:
-      base::UmaHistogramBoolean(
-          "IOS.FirstRun.ScrollButtonVisible.SyncScreenWithIdentityPicker",
-          scroll_button_visible);
-      break;
     case first_run::FirstRunScreenType::kWelcomeScreenWithoutUMACheckbox:
       base::UmaHistogramBoolean(
           "IOS.FirstRun.ScrollButtonVisible.WelcomeScreenWithoutUMACheckbox",
diff --git a/ios/chrome/browser/ui/first_run/resources/BUILD.gn b/ios/chrome/browser/ui/first_run/resources/BUILD.gn
index 3bf8410c..2a78e9a8 100644
--- a/ios/chrome/browser/ui/first_run/resources/BUILD.gn
+++ b/ios/chrome/browser/ui/first_run/resources/BUILD.gn
@@ -24,16 +24,6 @@
   ]
 }
 
-imageset("sync_screen_banner") {
-  sources = [
-    "sync_screen_banner.imageset/Contents.json",
-    "sync_screen_banner.imageset/sync_screen_banner_dark@2x.png",
-    "sync_screen_banner.imageset/sync_screen_banner_dark@3x.png",
-    "sync_screen_banner.imageset/sync_screen_banner_light@2x.png",
-    "sync_screen_banner.imageset/sync_screen_banner_light@3x.png",
-  ]
-}
-
 imageset("read_more_arrow") {
   sources = [
     "read_more_arrow.imageset/Contents.json",
diff --git a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/Contents.json b/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/Contents.json
deleted file mode 100644
index 1cafceb..0000000
--- a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/Contents.json
+++ /dev/null
@@ -1,40 +0,0 @@
-{
-  "images" : [
-    {
-      "filename" : "sync_screen_banner_light@2x.png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "sync_screen_banner_dark@2x.png",
-      "idiom" : "universal",
-      "scale" : "2x"
-    },
-    {
-      "filename" : "sync_screen_banner_light@3x.png",
-      "idiom" : "universal",
-      "scale" : "3x"
-    },
-    {
-      "appearances" : [
-        {
-          "appearance" : "luminosity",
-          "value" : "dark"
-        }
-      ],
-      "filename" : "sync_screen_banner_dark@3x.png",
-      "idiom" : "universal",
-      "scale" : "3x"
-    }
-  ],
-  "info" : {
-    "version" : 1,
-    "author" : "xcode"
-  }
-}
diff --git a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@2x.png b/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@2x.png
deleted file mode 100644
index 489fa07d..0000000
--- a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@2x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@3x.png b/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@3x.png
deleted file mode 100644
index 5d9f667f..0000000
--- a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_dark@3x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@2x.png b/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@2x.png
deleted file mode 100644
index ede8034..0000000
--- a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@2x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@3x.png b/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@3x.png
deleted file mode 100644
index 93665f6..0000000
--- a/ios/chrome/browser/ui/first_run/resources/sync_screen_banner.imageset/sync_screen_banner_light@3x.png
+++ /dev/null
Binary files differ
diff --git a/ios/chrome/browser/ui/screen/screen_type.h b/ios/chrome/browser/ui/screen/screen_type.h
index 1d64f71..236c300 100644
--- a/ios/chrome/browser/ui/screen/screen_type.h
+++ b/ios/chrome/browser/ui/screen/screen_type.h
@@ -16,7 +16,6 @@
   // TODO(crbug.com/1407658) Remove the following entries and their
   // corresponding screens as they are not obsolete.
   kWelcomeAndConsent_DEPRECATED,
-  kSignInAndSync_DEPRECATED,
 
   // It isn't a screen, but a signal that no more screen should be
   // presented.
diff --git a/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm b/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm
index 3c0d71f6..691d20ab 100644
--- a/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm
+++ b/ios/chrome/browser/ui/settings/password/legacy_password_settings_egtest.mm
@@ -433,9 +433,30 @@
   config.features_disabled.push_back(
       password_manager::features::kPasswordsGrouping);
 
+  if ([self isRunningTest:@selector
+            (testNoOndeviceEncryptionSetupWhenSignedOut)]) {
+    config.features_enabled.push_back(syncer::kSyncTrustedVaultPassphrasePromo);
+  }
+  if ([self isRunningTest:@selector(testNoOndeviceEncryptionWithoutFlag)]) {
+    config.features_disabled.push_back(
+        syncer::kSyncTrustedVaultPassphrasePromo);
+  }
+
   return config;
 }
 
+// Verifies that a signed out account has no option related to
+// on device encryption.
+- (void)testNoOndeviceEncryptionWithoutFlag {
+  OpenPasswordSettings();
+
+  // Check that the menus related to on-device encryptions are not displayed.
+  [OptedInTrustedVaultLink() assertWithMatcher:grey_nil()];
+  [OptedInTrustedVaultText() assertWithMatcher:grey_nil()];
+  [OptInTrustedVaultLink() assertWithMatcher:grey_nil()];
+  [SetUpTrustedVaultLink() assertWithMatcher:grey_nil()];
+}
+
 // Check that a user which is not logged in any account do not get
 // offered to use trusted vault.
 - (void)testNoOndeviceEncryptionSetupWhenSignedOut {
diff --git a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
index 04c8b91..db68ec3 100644
--- a/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_manager_egtest.mm
@@ -498,6 +498,14 @@
   }
 
   if ([self isRunningTest:@selector
+            (testNoOndeviceEncryptionSetupWhenSignedOut)]) {
+    config.features_enabled.push_back(syncer::kSyncTrustedVaultPassphrasePromo);
+  }
+  if ([self isRunningTest:@selector(testNoOndeviceEncryptionWithoutFlag)]) {
+    config.features_disabled.push_back(
+        syncer::kSyncTrustedVaultPassphrasePromo);
+  }
+  if ([self isRunningTest:@selector
             (testAccountStorageSwitchHiddenIfSignedInAndFlagDisabled)]) {
     config.features_disabled.push_back(
         password_manager::features::kEnablePasswordsAccountStorage);
@@ -511,6 +519,20 @@
   return config;
 }
 
+// Verifies that a signed out account has no option related to
+// on device encryption.
+- (void)testNoOndeviceEncryptionWithoutFlag {
+  OpenPasswordManager();
+
+  // Check that the menus related to on-device encryptions are not displayed.
+  [OptedInTrustedVaultLink() assertWithMatcher:grey_nil()];
+  [OptedInTrustedVaultText() assertWithMatcher:grey_nil()];
+  [OptInTrustedVaultLink() assertWithMatcher:grey_nil()];
+  [SetUpTrustedVaultLink() assertWithMatcher:grey_nil()];
+  [[EarlGrey selectElementWithMatcher:SettingsDoneButton()]
+      performAction:grey_tap()];
+}
+
 // Check that a user which is not logged in any account do not get
 // offered to use trusted vault.
 - (void)testNoOndeviceEncryptionSetupWhenSignedOut {
diff --git a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm
index c3873dc..985948d 100644
--- a/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm
+++ b/ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator_unittest.mm
@@ -4,6 +4,7 @@
 
 #import "ios/chrome/browser/ui/settings/password/password_settings/password_settings_mediator.h"
 
+#import "base/test/scoped_feature_list.h"
 #import "base/test/task_environment.h"
 #import "components/keyed_service/core/service_access_type.h"
 #import "components/password_manager/core/browser/affiliation/mock_affiliation_service.h"
@@ -102,6 +103,10 @@
 
 TEST_F(PasswordSettingsMediatorTest,
        SyncChangeTriggersChangeOnDeviceEncryption) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(
+      syncer::kSyncTrustedVaultPassphrasePromo);
+
   // This was populated when the consumer was initially set.
   [[consumer_ verify] setOnDeviceEncryptionState:
                           PasswordSettingsOnDeviceEncryptionStateNotShown];
diff --git a/ios/chrome/browser/ui/tab_switcher/BUILD.gn b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
index 0318cc9..f61d5f2f 100644
--- a/ios/chrome/browser/ui/tab_switcher/BUILD.gn
+++ b/ios/chrome/browser/ui/tab_switcher/BUILD.gn
@@ -8,6 +8,8 @@
   sources = [
     "tab_collection_consumer.h",
     "tab_collection_drag_drop_handler.h",
+    "tab_collection_drag_drop_metrics.h",
+    "tab_collection_drag_drop_metrics.mm",
     "tab_switcher_item.h",
     "tab_switcher_item.mm",
   ]
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h b/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h
new file mode 100644
index 0000000..0b9056a7
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h
@@ -0,0 +1,38 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_COLLECTION_DRAG_DROP_METRICS_H_
+#define IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_COLLECTION_DRAG_DROP_METRICS_H_
+
+// Key of UMA DragDrop histograms.
+extern const char kUmaGridViewDragDropTabs[];
+extern const char kUmaPinnedViewDragDropTabs[];
+
+// Key of UMA DragOrigin histograms.
+extern const char kUmaGridViewDragOrigin[];
+extern const char kUmaPinnedViewDragOrigin[];
+
+// Values of UMA DragDrop histograms. These values are persisted to logs.
+// Entries should not be renumbered and numeric values should never be reused.
+enum class DragDropTabs {
+  // A tab is dragged.
+  kDragBegin = 0,
+  // A tab is dropped at the same index position.
+  kDragEndAtSameIndex = 1,
+  // A tab is dropped at a new index position.
+  kDragEndAtNewIndex = 2,
+  kMaxValue = kDragEndAtNewIndex
+};
+
+// Values of UMA DragOrigin histograms. These values are persisted to logs.
+// Entries should not be renumbered and numeric values should never be reused.
+enum class DragItemOrigin {
+  kSameCollection = 0,
+  kSameBrowser = 1,
+  kOtherBrwoser = 2,
+  kOther = 3,
+  kMaxValue = kOther
+};
+
+#endif  // IOS_CHROME_BROWSER_UI_TAB_SWITCHER_TAB_COLLECTION_DRAG_DROP_METRICS_H_
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.mm b/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.mm
new file mode 100644
index 0000000..c70507c
--- /dev/null
+++ b/ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.mm
@@ -0,0 +1,17 @@
+// Copyright 2023 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+extern const char kUmaGridViewDragDropTabs[] = "IOS.TabSwitcher.DragDropTabs";
+extern const char kUmaPinnedViewDragDropTabs[] =
+    "IOS.TabSwitcher.PinnedTabs.DragDropTabs";
+
+extern const char kUmaGridViewDragOrigin[] = "IOS.TabSwitcher.DragOrigin";
+extern const char kUmaPinnedViewDragOrigin[] =
+    "IOS.TabSwitcher.PinnedTabs.DragOrigin";
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
index ca044f3e..86d256b 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.h
@@ -26,22 +26,6 @@
 @protocol ThumbStripCommands;
 @protocol SuggestedActionsDelegate;
 
-// Key of the UMA IOS.TabSwitcher.DragDropTabs histogram.
-extern const char kUmaDragDropTabs[];
-
-// Values of the UMA IOS.TabSwitcher.DragDropTabs histogram. These values are
-// persisted to logs. Entries should not be renumbered and numeric values should
-// never be reused.
-enum class DragDropTabs {
-  // A tab is dragged.
-  kDragBegin = 0,
-  // A tab is dropped at the same index position.
-  kDragEndAtSameIndex = 1,
-  // A tab is dropped at a new index position
-  kDragEndAtNewIndex = 2,
-  kMaxValue = kDragEndAtNewIndex
-};
-
 // Protocol used to relay relevant user interactions from a grid UI.
 @protocol GridViewControllerDelegate
 // Tells the delegate that the item with `itemID` was selected in
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
index e58efe2..b7719fd 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_view_controller.mm
@@ -23,6 +23,7 @@
 #import "ios/chrome/browser/ui/incognito_reauth/incognito_reauth_view.h"
 #import "ios/chrome/browser/ui/menu/menu_histograms.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_handler.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_cell.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_empty_view.h"
@@ -50,8 +51,6 @@
 #error "This file requires ARC support."
 #endif
 
-extern const char kUmaDragDropTabs[] = "IOS.TabSwitcher.DragDropTabs";
-
 namespace {
 
 // Constants used in the spring animation when inserting items in the thumb
@@ -765,7 +764,8 @@
 - (void)collectionView:(UICollectionView*)collectionView
     dragSessionWillBegin:(id<UIDragSession>)session {
   self.dragEndAtNewIndex = NO;
-  base::UmaHistogramEnumeration(kUmaDragDropTabs, DragDropTabs::kDragBegin);
+  base::UmaHistogramEnumeration(kUmaGridViewDragDropTabs,
+                                DragDropTabs::kDragBegin);
 
   [self.delegate gridViewControllerDragSessionWillBegin:self];
 }
@@ -775,7 +775,7 @@
   DragDropTabs dragEvent = self.dragEndAtNewIndex
                                ? DragDropTabs::kDragEndAtNewIndex
                                : DragDropTabs::kDragEndAtSameIndex;
-  base::UmaHistogramEnumeration(kUmaDragDropTabs, dragEvent);
+  base::UmaHistogramEnumeration(kUmaGridViewDragDropTabs, dragEvent);
 
   // Used to let the Taptic Engine return to its idle state.
   // To preserve power, the Taptic Engine remains in a prepared state for only a
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
index fdf4cd4..e5a44b1d 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_mediator.mm
@@ -19,6 +19,7 @@
 #import "ios/chrome/browser/main/browser_list_factory.h"
 #import "ios/chrome/browser/main/browser_util.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_consumer.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_utils.h"
@@ -444,14 +445,24 @@
                                             /*pin_state=*/YES);
       if (tabIndex == WebStateList::kInvalidIndex) {
         // Move tab across Browsers.
+        base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
+                                      DragItemOrigin::kOtherBrwoser);
         MoveTabToBrowser(tabInfo.tabID, self.browser, destinationIndex);
         return;
       }
+      base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
+                                    DragItemOrigin::kSameBrowser);
+    } else {
+      base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
+                                    DragItemOrigin::kSameCollection);
     }
+
     // Reorder tabs.
     [self.consumer moveItemWithID:tabInfo.tabID toIndex:destinationIndex];
     return;
   }
+  base::UmaHistogramEnumeration(kUmaPinnedViewDragOrigin,
+                                DragItemOrigin::kOther);
 
   // Handle URLs from within Chrome synchronously using a local object.
   if ([dragItem.localObject isKindOfClass:[URLInfo class]]) {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
index 4988caf..0272400 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_tabs_view_controller.mm
@@ -8,9 +8,11 @@
 #import "base/ios/block_types.h"
 #import "base/ios/ios_util.h"
 #import "base/mac/foundation_util.h"
+#import "base/metrics/histogram_functions.h"
 #import "base/notreached.h"
 #import "base/numerics/safe_conversions.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_handler.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_image_data_source.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/pinned_cell.h"
@@ -74,6 +76,9 @@
 
   // Tracks if a drag action is in progress.
   BOOL _dragActionInProgress;
+
+  // YES if the dragged tab moved to a new index.
+  BOOL _dragEndAtNewIndex;
 }
 
 - (instancetype)init {
@@ -362,11 +367,20 @@
 
 - (void)collectionView:(UICollectionView*)collectionView
     dragSessionWillBegin:(id<UIDragSession>)session {
+  _dragEndAtNewIndex = NO;
+  base::UmaHistogramEnumeration(kUmaPinnedViewDragDropTabs,
+                                DragDropTabs::kDragBegin);
+
   [self dragSessionEnabled:YES];
 }
 
 - (void)collectionView:(UICollectionView*)collectionView
      dragSessionDidEnd:(id<UIDragSession>)session {
+  DragDropTabs dragEvent = _dragEndAtNewIndex
+                               ? DragDropTabs::kDragEndAtNewIndex
+                               : DragDropTabs::kDragEndAtSameIndex;
+  base::UmaHistogramEnumeration(kUmaPinnedViewDragDropTabs, dragEvent);
+
   [self.dragDropHandler dragSessionDidEnd];
   [self dragSessionEnabled:NO];
 }
@@ -441,6 +455,7 @@
       destinationIndex =
           base::checked_cast<NSUInteger>(coordinator.destinationIndexPath.item);
     }
+    _dragEndAtNewIndex = YES;
 
     NSIndexPath* dropIndexPath = CreateIndexPath(destinationIndex);
     // Drop synchronously if local object is available.
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
index f909d50..3499e3db 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_coordinator.mm
@@ -23,7 +23,6 @@
 #import "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h"
 #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h"
 #import "ios/chrome/browser/ui/bookmarks/bookmarks_coordinator.h"
-#import "ios/chrome/browser/ui/bookmarks/editor/bookmarks_editor_coordinator.h"
 #import "ios/chrome/browser/ui/commands/application_commands.h"
 #import "ios/chrome/browser/ui/commands/bookmarks_commands.h"
 #import "ios/chrome/browser/ui/commands/browser_commands.h"
@@ -81,8 +80,7 @@
 #error "This file requires ARC support."
 #endif
 
-@interface TabGridCoordinator () <BookmarksEditorCoordinatorDelegate,
-                                  RecentTabsPresentationDelegate,
+@interface TabGridCoordinator () <RecentTabsPresentationDelegate,
                                   HistoryPresentationDelegate,
                                   SceneStateObserver,
                                   SnackbarCoordinatorDelegate,
@@ -98,9 +96,6 @@
   // The coordinator that shows the bookmarking UI after the user taps the Add
   // to Bookmarks button.
   BookmarksCoordinator* _bookmarksCoordinator;
-  // Coordinator to edit a bookmark. Used only if
-  // kEnableNewBookmarksImplementation enabled.
-  BookmarksEditorCoordinator* _bookmarksEditorCoordinator;
 }
 
 @property(nonatomic, assign, readonly) Browser* regularBrowser;
@@ -789,8 +784,6 @@
   self.recentTabsContextMenuHelper = nil;
   self.regularTabContextMenuHelper = nil;
   self.incognitoTabContextMenuHelper = nil;
-  [_bookmarksEditorCoordinator stop];
-  _bookmarksEditorCoordinator = nil;
   [self.sharingCoordinator stop];
   self.sharingCoordinator = nil;
   [self.dispatcher stopDispatchingForProtocol:@protocol(ApplicationCommands)];
@@ -817,15 +810,6 @@
   self.incognitoSnackbarCoordinator = nil;
 }
 
-#pragma mark - BookmarksEditorCoordinatorDelegate
-
-- (void)bookmarksEditorCoordinatorShouldStop:
-    (BookmarksEditorCoordinator*)coordinator {
-  DCHECK(_bookmarksEditorCoordinator);
-  [_bookmarksEditorCoordinator stop];
-  _bookmarksEditorCoordinator = nil;
-}
-
 #pragma mark - TabPresentationDelegate
 
 - (void)showActiveTabInPage:(TabGridPage)page
@@ -1153,16 +1137,7 @@
 }
 
 - (void)editBookmarkWithURL:(const GURL&)URL {
-  if (base::FeatureList::IsEnabled(kEnableNewBookmarksImplementation)) {
-    _bookmarksEditorCoordinator = [[BookmarksEditorCoordinator alloc]
-        initWithBaseViewController:self.baseViewController
-                           browser:self.browser
-                               URL:URL];
-    _bookmarksEditorCoordinator.delegate = self;
-    [_bookmarksEditorCoordinator start];
-  } else {
-    [self.bookmarksCoordinator presentBookmarkEditorForURL:URL];
-  }
+  [self.bookmarksCoordinator presentBookmarkEditorForURL:URL];
 }
 
 - (void)pinTabWithIdentifier:(NSString*)identifier {
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
index 87d7656..314c132 100644
--- a/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
+++ b/ios/chrome/browser/ui/tab_switcher/tab_grid/tab_grid_mediator.mm
@@ -47,6 +47,7 @@
 #import "ios/chrome/browser/ui/main/scene_state_browser_agent.h"
 #import "ios/chrome/browser/ui/menu/action_factory.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_collection_consumer.h"
+#import "ios/chrome/browser/ui/tab_switcher/tab_collection_drag_drop_metrics.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/pinned_tabs/features.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_grid/tab_context_menu/tab_item.h"
 #import "ios/chrome/browser/ui/tab_switcher/tab_switcher_item.h"
@@ -901,14 +902,23 @@
                                             /*pin_state=*/NO);
       if (tabIndex == WebStateList::kInvalidIndex) {
         // Move tab across Browsers.
+        base::UmaHistogramEnumeration(kUmaGridViewDragOrigin,
+                                      DragItemOrigin::kOtherBrwoser);
         MoveTabToBrowser(tabInfo.tabID, self.browser, destinationIndex);
         return;
       }
+      base::UmaHistogramEnumeration(kUmaGridViewDragOrigin,
+                                    DragItemOrigin::kSameBrowser);
+    } else {
+      base::UmaHistogramEnumeration(kUmaGridViewDragOrigin,
+                                    DragItemOrigin::kSameCollection);
     }
+
     // Reorder tab within same grid.
     [self moveItemWithID:tabInfo.tabID toIndex:destinationIndex];
     return;
   }
+  base::UmaHistogramEnumeration(kUmaGridViewDragOrigin, DragItemOrigin::kOther);
 
   // Handle URLs from within Chrome synchronously using a local object.
   if ([dragItem.localObject isKindOfClass:[URLInfo class]]) {
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc
index 27075d9..5d42367 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.cc
+++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -130,10 +130,6 @@
              "TabGridRecencySort",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
-BASE_FEATURE(kEnableNewBookmarksImplementation,
-             "EnableNewBookmarksImplementation",
-             base::FEATURE_DISABLED_BY_DEFAULT);
-
 BASE_FEATURE(kMultilineFadeTruncatingLabel,
              "MultilineFadeTruncatingLabel",
              base::FEATURE_DISABLED_BY_DEFAULT);
@@ -142,6 +138,10 @@
              "EnableAccessibilityIdentifierToOmniboxLeadingImage",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+BASE_FEATURE(kTabStripContextMenu,
+             "TabStripContextMenu",
+             base::FEATURE_DISABLED_BY_DEFAULT);
+
 bool IsTabGridSortedByRecency() {
   return base::FeatureList::IsEnabled(kTabGridRecencySort);
 }
diff --git a/ios/chrome/browser/ui/ui_feature_flags.h b/ios/chrome/browser/ui/ui_feature_flags.h
index 5ed534f..905f194 100644
--- a/ios/chrome/browser/ui/ui_feature_flags.h
+++ b/ios/chrome/browser/ui/ui_feature_flags.h
@@ -119,15 +119,15 @@
 // When enabled sort tab by last usage in the TabGrid.
 BASE_DECLARE_FEATURE(kTabGridRecencySort);
 
-// Feature to enable the new bookmarks implementation.
-BASE_DECLARE_FEATURE(kEnableNewBookmarksImplementation);
-
 // Feature to enable multiline gradient support in fade truncating label.
 BASE_DECLARE_FEATURE(kMultilineFadeTruncatingLabel);
 
 // Flag to enable accessibility identifier to omnibox leading image.
 BASE_DECLARE_FEATURE(kEnableAccessibilityIdentifierToOmniboxLeadingImage);
 
+// Flag to enable tab strip context menu.
+BASE_DECLARE_FEATURE(kTabStripContextMenu);
+
 // Whether the tab grid tabs should be sorted by recency.
 bool IsTabGridSortedByRecency();
 
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn
index d97df43b..fdf4692 100644
--- a/ios/chrome/test/BUILD.gn
+++ b/ios/chrome/test/BUILD.gn
@@ -274,7 +274,6 @@
     "//ios/chrome/browser/ui/authentication/signin/consistency_promo_signin:unit_tests",
     "//ios/chrome/browser/ui/authentication/signin/trusted_vault_reauthentication:unit_tests",
     "//ios/chrome/browser/ui/authentication/signin/user_signin:unit_tests",
-    "//ios/chrome/browser/ui/authentication/signin_sync:unit_tests",
     "//ios/chrome/browser/ui/authentication/unified_consent:unit_tests",
     "//ios/chrome/browser/ui/authentication/unified_consent/identity_chooser:unit_tests",
     "//ios/chrome/browser/ui/autofill:unit_tests",
diff --git a/ios/features.gni b/ios/features.gni
index e895e86..ab89219 100644
--- a/ios/features.gni
+++ b/ios/features.gni
@@ -7,6 +7,9 @@
   # WebKit for mac but incorrectly setting `target_os="ios"`.
   is_webkit_only_build = false
 
+  # Control whether iOS builds with PartitionAlloc.
+  ios_partition_alloc_enabled = false
+
   # Control whether //ios/chrome and //ios/web targets are build. This
   # is used by bots from projects based on top of Chromium that want to
   # only reuse shared code (//ios/net, //remoting/ios, ...).
diff --git a/media/filters/demuxer_manager.h b/media/filters/demuxer_manager.h
index 3d411696..26769d3 100644
--- a/media/filters/demuxer_manager.h
+++ b/media/filters/demuxer_manager.h
@@ -171,7 +171,7 @@
 #endif  // BUILDFLAG(ENABLE_FFMPEG)
 
   // This is usually just the WebMediaPlayerImpl.
-  raw_ptr<Client> client_;
+  raw_ptr<Client, DanglingUntriaged> client_;
 
   // The demuxers need access the the media task runner and media log.
   const scoped_refptr<base::SequencedTaskRunner> media_task_runner_;
diff --git a/net/cookies/cookie_util.h b/net/cookies/cookie_util.h
index 5b28a2d5..ab2d1bf 100644
--- a/net/cookies/cookie_util.h
+++ b/net/cookies/cookie_util.h
@@ -44,7 +44,8 @@
   ACCESS_ALLOWED = 1,
   ACCESS_ALLOWED_STORAGE_ACCESS_GRANT = 2,
   ACCESS_ALLOWED_FORCED = 3,
-  kMaxValue = ACCESS_ALLOWED_FORCED,
+  ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT = 4,
+  kMaxValue = ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT,
 };
 // Helper to fire telemetry indicating if a given request for storage was
 // allowed or not by the provided |result|.
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins
index 30c5c9d..cdf9593 100644
--- a/net/http/transport_security_state_static.pins
+++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@
 #   hash function for preloaded entries again (we have already done so once).
 #
 
-# Last updated: 2023-01-22 12:54 UTC
+# Last updated: 2023-01-25 12:54 UTC
 PinsListTimestamp
-1674392091
+1674651297
 
 TestSPKI
 sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/services/device/fingerprint/OWNERS b/services/device/fingerprint/OWNERS
index 81ca4478..20e41d6 100644
--- a/services/device/fingerprint/OWNERS
+++ b/services/device/fingerprint/OWNERS
@@ -1 +1 @@
-rsorokin@google.com
\ No newline at end of file
+file://ash/login/LOGIN_LOCK_OWNERS
diff --git a/services/network/cookie_settings.cc b/services/network/cookie_settings.cc
index 31aceb8..98df360 100644
--- a/services/network/cookie_settings.cc
+++ b/services/network/cookie_settings.cc
@@ -249,10 +249,8 @@
           ACCESS_ALLOWED_STORAGE_ACCESS_GRANT;
     } else if (ShouldConsiderTopLevelStorageAccessGrants(query_reason) &&
                IsAllowedByTopLevelStorageAccessGrant(url, first_party_url)) {
-      // TODO(crbug.com/1385156): Separate metrics between StorageAccessAPI
-      // and the page-level variant.
       storage_access_result = net::cookie_util::StorageAccessResult::
-          ACCESS_ALLOWED_STORAGE_ACCESS_GRANT;
+          ACCESS_ALLOWED_TOP_LEVEL_STORAGE_ACCESS_GRANT;
     } else if (overrides.Has(
                    net::CookieSettingOverride::kForceThirdPartyByUser)) {
       storage_access_result =
diff --git a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index 6c9be16..8ba25ec 100644
--- a/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -39,7 +39,6 @@
 #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
 #include "services/tracing/public/cpp/perfetto/system_producer.h"
 #include "services/tracing/public/cpp/perfetto/trace_string_lookup.h"
-#include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
 #include "services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h"
 #include "services/tracing/public/cpp/perfetto/track_name_recorder.h"
 #include "services/tracing/public/cpp/trace_event_args_allowlist.h"
@@ -600,7 +599,6 @@
 
 void TraceEventDataSource::RegisterStartupHooks() {
 #if !BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
-  RegisterTracedValueProtoWriter();
   base::trace_event::EnableTypedTraceEvents(
       &TraceEventDataSource::OnAddTypedTraceEvent,
       &TraceEventDataSource::OnAddTracePacket,
diff --git a/services/tracing/public/cpp/trace_startup.cc b/services/tracing/public/cpp/trace_startup.cc
index 39ffdbd5..878085ea 100644
--- a/services/tracing/public/cpp/trace_startup.cc
+++ b/services/tracing/public/cpp/trace_startup.cc
@@ -15,6 +15,7 @@
 #include "services/tracing/public/cpp/perfetto/producer_client.h"
 #include "services/tracing/public/cpp/perfetto/system_producer.h"
 #include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
+#include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
 #include "services/tracing/public/cpp/trace_event_agent.h"
 #include "services/tracing/public/cpp/trace_event_args_allowlist.h"
 #include "services/tracing/public/cpp/tracing_features.h"
@@ -53,6 +54,7 @@
   const base::CommandLine& command_line =
       *base::CommandLine::ForCurrentProcess();
 
+  RegisterTracedValueProtoWriter();
   TraceEventDataSource::GetInstance()->RegisterStartupHooks();
 
   // Create the PerfettoTracedProcess.
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json
index ebc5df1..18f9eea 100644
--- a/testing/buildbot/chrome.json
+++ b/testing/buildbot/chrome.json
@@ -1876,7 +1876,7 @@
       {
         "args": [],
         "cros_board": "dedede",
-        "cros_img": "dedede-release/R111-15324.0.0",
+        "cros_img": "dedede-release/R111-15326.0.0",
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1908,7 +1908,7 @@
       {
         "args": [],
         "cros_board": "dedede",
-        "cros_img": "dedede-release/R110-15278.36.0",
+        "cros_img": "dedede-release/R110-15278.41.0",
         "name": "lacros_all_tast_tests DEDEDE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -1940,7 +1940,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R111-15324.0.0",
+        "cros_img": "eve-release/R111-15326.0.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -1972,7 +1972,7 @@
       {
         "args": [],
         "cros_board": "eve",
-        "cros_img": "eve-release/R110-15278.29.0",
+        "cros_img": "eve-release/R110-15278.41.0",
         "name": "lacros_all_tast_tests EVE_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2083,7 +2083,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R111-15324.0.0",
+        "cros_img": "jacuzzi-release/R111-15326.0.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
@@ -2115,7 +2115,7 @@
       {
         "args": [],
         "cros_board": "jacuzzi",
-        "cros_img": "jacuzzi-release/R110-15278.36.0",
+        "cros_img": "jacuzzi-release/R110-15278.41.0",
         "name": "lacros_all_tast_tests JACUZZI_RELEASE_BETA",
         "resultdb": {
           "enable": true,
@@ -2188,7 +2188,7 @@
       {
         "args": [],
         "cros_board": "herobrine",
-        "cros_img": "herobrine-release/R111-15324.0.0",
+        "cros_img": "herobrine-release/R111-15326.0.0",
         "name": "lacros_fyi_tast_tests HEROBRINE_RELEASE_LKGM",
         "resultdb": {
           "enable": true,
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json
index abded1b..f4f361ef 100644
--- a/testing/buildbot/chromium.fyi.json
+++ b/testing/buildbot/chromium.fyi.json
@@ -67061,28 +67061,6 @@
       }
     ]
   },
-  "mac-arm64-on-arm64-rel-reclient": {
-    "additional_compile_targets": [
-      "all"
-    ],
-    "scripts": [
-      {
-        "name": "check_static_initializers",
-        "script": "check_static_initializers.py",
-        "swarming": {}
-      },
-      {
-        "name": "metrics_python_tests",
-        "script": "metrics_python_tests.py",
-        "swarming": {}
-      },
-      {
-        "name": "webkit_lint",
-        "script": "blink_lint_expectations.py",
-        "swarming": {}
-      }
-    ]
-  },
   "mac-backuprefptr-x64-fyi-rel": {
     "gtest_tests": [
       {
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json
index b611b97f..791b6760 100644
--- a/testing/buildbot/internal.chromeos.fyi.json
+++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1141,7 +1141,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R111-15324.0.0",
+        "cros_img": "octopus-release/R111-15326.0.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1165,7 +1165,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R110-15278.36.0",
+        "cros_img": "octopus-release/R110-15278.41.0",
         "name": "lacros_fyi_tast_tests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1189,7 +1189,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R111-15324.0.0",
+        "cros_img": "octopus-release/R111-15326.0.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1211,7 +1211,7 @@
       {
         "args": [],
         "cros_board": "octopus",
-        "cros_img": "octopus-release/R110-15278.36.0",
+        "cros_img": "octopus-release/R110-15278.41.0",
         "name": "ozone_unittests OCTOPUS_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1240,7 +1240,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R111-15324.0.0",
+        "cros_img": "hana-release/R111-15326.0.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1264,7 +1264,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R110-15278.36.0",
+        "cros_img": "hana-release/R110-15278.41.0",
         "name": "lacros_all_tast_tests HANA_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1288,7 +1288,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R111-15324.0.0",
+        "cros_img": "strongbad-release/R111-15326.0.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1312,7 +1312,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R110-15278.36.0",
+        "cros_img": "strongbad-release/R110-15278.41.0",
         "name": "lacros_all_tast_tests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)",
@@ -1336,7 +1336,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R111-15324.0.0",
+        "cros_img": "hana-release/R111-15326.0.0",
         "name": "ozone_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1358,7 +1358,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R110-15278.36.0",
+        "cros_img": "hana-release/R110-15278.41.0",
         "name": "ozone_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1380,7 +1380,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R111-15324.0.0",
+        "cros_img": "strongbad-release/R111-15326.0.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1402,7 +1402,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R110-15278.36.0",
+        "cros_img": "strongbad-release/R110-15278.41.0",
         "name": "ozone_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "ozone_unittests",
@@ -1424,7 +1424,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R111-15324.0.0",
+        "cros_img": "hana-release/R111-15326.0.0",
         "name": "viz_unittests HANA_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1446,7 +1446,7 @@
       {
         "args": [],
         "cros_board": "hana",
-        "cros_img": "hana-release/R110-15278.36.0",
+        "cros_img": "hana-release/R110-15278.41.0",
         "name": "viz_unittests HANA_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
@@ -1468,7 +1468,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R111-15324.0.0",
+        "cros_img": "strongbad-release/R111-15326.0.0",
         "name": "viz_unittests STRONGBAD_RELEASE_LKGM",
         "swarming": {},
         "test": "viz_unittests",
@@ -1490,7 +1490,7 @@
       {
         "args": [],
         "cros_board": "strongbad",
-        "cros_img": "strongbad-release/R110-15278.36.0",
+        "cros_img": "strongbad-release/R110-15278.41.0",
         "name": "viz_unittests STRONGBAD_RELEASE_BETA",
         "swarming": {},
         "test": "viz_unittests",
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl
index 4899b4f..f73d95c 100644
--- a/testing/buildbot/variants.pyl
+++ b/testing/buildbot/variants.pyl
@@ -471,7 +471,7 @@
     'skylab': {
       'cros_board': 'dedede',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'dedede-release/R111-15324.0.0',
+      'cros_img': 'dedede-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'DEDEDE_RELEASE_LKGM',
@@ -488,8 +488,8 @@
   'CROS_DEDEDE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'dedede',
-      'cros_chrome_version': '110.0.5481.41',
-      'cros_img': 'dedede-release/R110-15278.36.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'dedede-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'DEDEDE_RELEASE_BETA',
@@ -507,7 +507,7 @@
     'skylab': {
       'cros_board': 'eve',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'eve-release/R111-15324.0.0',
+      'cros_img': 'eve-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_LKGM',
@@ -524,8 +524,8 @@
   'CROS_EVE_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'eve',
-      'cros_chrome_version': '110.0.5481.32',
-      'cros_img': 'eve-release/R110-15278.29.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'eve-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'EVE_RELEASE_BETA',
@@ -553,7 +553,7 @@
     'skylab': {
       'cros_board': 'hana',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'hana-release/R111-15324.0.0',
+      'cros_img': 'hana-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_LKGM',
@@ -570,8 +570,8 @@
   'CROS_HANA_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'hana',
-      'cros_chrome_version': '110.0.5481.41',
-      'cros_img': 'hana-release/R110-15278.36.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'hana-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'HANA_RELEASE_BETA',
@@ -589,7 +589,7 @@
     'skylab': {
       'cros_board': 'herobrine',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'herobrine-release/R111-15324.0.0',
+      'cros_img': 'herobrine-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'HEROBRINE_RELEASE_LKGM',
@@ -598,7 +598,7 @@
     'skylab': {
       'cros_board': 'jacuzzi',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'jacuzzi-release/R111-15324.0.0',
+      'cros_img': 'jacuzzi-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_LKGM',
@@ -615,8 +615,8 @@
   'CROS_JACUZZI_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'jacuzzi',
-      'cros_chrome_version': '110.0.5481.41',
-      'cros_img': 'jacuzzi-release/R110-15278.36.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'jacuzzi-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'JACUZZI_RELEASE_BETA',
@@ -674,7 +674,7 @@
     'skylab': {
       'cros_board': 'octopus',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'octopus-release/R111-15324.0.0',
+      'cros_img': 'octopus-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_LKGM',
@@ -691,8 +691,8 @@
   'CROS_OCTOPUS_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'octopus',
-      'cros_chrome_version': '110.0.5481.41',
-      'cros_img': 'octopus-release/R110-15278.36.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'octopus-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'OCTOPUS_RELEASE_BETA',
@@ -710,7 +710,7 @@
     'skylab': {
       'cros_board': 'strongbad',
       'cros_chrome_version': '111.0.5550.0',
-      'cros_img': 'strongbad-release/R111-15324.0.0',
+      'cros_img': 'strongbad-release/R111-15326.0.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_LKGM',
@@ -727,8 +727,8 @@
   'CROS_STRONGBAD_RELEASE_BETA': {
     'skylab': {
       'cros_board': 'strongbad',
-      'cros_chrome_version': '110.0.5481.41',
-      'cros_img': 'strongbad-release/R110-15278.36.0',
+      'cros_chrome_version': '110.0.5481.46',
+      'cros_img': 'strongbad-release/R110-15278.41.0',
     },
     'enabled': True,
     'identifier': 'STRONGBAD_RELEASE_BETA',
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index 6d887ca..da1fe5a 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -3606,15 +3606,6 @@
           'isolated_scripts': 'wpt_web_tests_input',
         },
       },
-      # TODO(crbug.com/1252626): remove this after the migration.
-      'mac-arm64-on-arm64-rel-reclient': {
-        'additional_compile_targets': [
-          'all',
-        ],
-        'test_suites': {
-          'scripts': 'chromium_mac_scripts',
-        }
-      },
       'mac-backuprefptr-x64-fyi-rel': {
         'test_suites': {
           'gtest_tests': 'chromium_mac_and_dangling_pointer_detection_gtests',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json
index 9b9af28..13f705a 100644
--- a/testing/variations/fieldtrial_testing_config.json
+++ b/testing/variations/fieldtrial_testing_config.json
@@ -9264,6 +9264,26 @@
             ]
         }
     ],
+    "PrivacySandboxV4": [
+        {
+            "platforms": [
+                "android",
+                "chromeos",
+                "chromeos_lacros",
+                "linux",
+                "mac",
+                "windows"
+            ],
+            "experiments": [
+                {
+                    "name": "Enabled",
+                    "enable_features": [
+                        "PrivacySandboxSettings4"
+                    ]
+                }
+            ]
+        }
+    ],
     "ProcessHtmlDataImmediately": [
         {
             "platforms": [
@@ -12961,7 +12981,7 @@
             ],
             "experiments": [
                 {
-                    "name": "threshold:0.5,mode:1"
+                    "name": "threshold:0.5,mode:2"
                 }
             ]
         }
diff --git a/third_party/blink/public/platform/DEPS b/third_party/blink/public/platform/DEPS
index b1e9c980..95d99931 100644
--- a/third_party/blink/public/platform/DEPS
+++ b/third_party/blink/public/platform/DEPS
@@ -1,5 +1,4 @@
 include_rules = [
-    "+base/atomicops.h",
     "+base/check.h",
     "+base/check_op.h",
     "+base/containers/flat_set.h",
diff --git a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
index 760b7c7..b7c87a0 100644
--- a/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
+++ b/third_party/blink/public/web/modules/mediastream/media_stream_video_source.h
@@ -136,8 +136,9 @@
 
   void UpdateCapturingLinkSecure(MediaStreamVideoTrack* track, bool is_secure);
 
-  // Indicate that the capturer can discard its alpha channel (if it has one).
-  virtual void SetCanDiscardAlpha(bool can_discard_alpha) {}
+  // Called whenever we might need to reevaluate whether the source can discard
+  // an alpha channel, due to a change in an attached track.
+  void UpdateCanDiscardAlpha();
 
   // Request underlying source to capture a new frame.
   virtual void RequestRefreshFrame() {}
@@ -327,6 +328,10 @@
   // The method is called when the last encoded sink has been removed.
   virtual void OnEncodedSinkDisabled() {}
 
+  // Optionally overridden by subclasses to be notified whether all attached
+  // tracks allow alpha to be dropped.
+  virtual void OnSourceCanDiscardAlpha(bool can_discard_alpha) {}
+
   enum State {
     NEW,
     STARTING,
diff --git a/third_party/blink/public/web/web_document.h b/third_party/blink/public/web/web_document.h
index 3f0662c..66eb8ff4 100644
--- a/third_party/blink/public/web/web_document.h
+++ b/third_party/blink/public/web/web_document.h
@@ -165,16 +165,6 @@
       CrossVariantMojoRemote<
           network::mojom::RestrictedCookieManagerInterfaceBase> cookie_manager);
 
-  // Get an element that's a descendent of this document by the stable Devtools'
-  // node id.
-  // https://chromedevtools.github.io/devtools-protocol/tot/DOM/#type-BackendNodeId
-  // Returns a null WebElement if any of the following are true:
-  // * the `node_id` does not identify any Node
-  // * the Node identified by `node_id` is not an Element
-  // * the Element is not a descendant of this WebDocument or any shadow
-  //   document contained within it
-  WebElement GetElementByDevToolsNodeId(int node_id);
-
 #if INSIDE_BLINK
   WebDocument(Document*);
   WebDocument& operator=(Document*);
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc
index fb10a8c0..5155cc2b 100644
--- a/third_party/blink/renderer/core/dom/document.cc
+++ b/third_party/blink/renderer/core/dom/document.cc
@@ -393,7 +393,7 @@
 
 void FireRequestStorageAccessForOriginHistogram(RequestStorageResult result) {
   base::UmaHistogramEnumeration(
-      "API.StorageAccess.RequestStorageAccessForOrigin", result);
+      "API.TopLevelStorageAccess.RequestStorageAccessForOrigin", result);
 }
 
 class IntrinsicSizeResizeObserverDelegate : public ResizeObserver::Delegate {
diff --git a/third_party/blink/renderer/core/exported/web_document.cc b/third_party/blink/renderer/core/exported/web_document.cc
index 654a6b3..86c435e5 100644
--- a/third_party/blink/renderer/core/exported/web_document.cc
+++ b/third_party/blink/renderer/core/exported/web_document.cc
@@ -45,7 +45,6 @@
 #include "third_party/blink/renderer/core/dom/document.h"
 #include "third_party/blink/renderer/core/dom/document_statistics_collector.h"
 #include "third_party/blink/renderer/core/dom/document_type.h"
-#include "third_party/blink/renderer/core/dom/dom_node_ids.h"
 #include "third_party/blink/renderer/core/dom/element.h"
 #include "third_party/blink/renderer/core/dom/events/event.h"
 #include "third_party/blink/renderer/core/dom/node.h"
@@ -66,7 +65,6 @@
 #include "third_party/blink/renderer/core/html/plugin_document.h"
 #include "third_party/blink/renderer/core/layout/layout_object.h"
 #include "third_party/blink/renderer/core/page/page.h"
-#include "third_party/blink/renderer/platform/graphics/dom_node_id.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 #include "third_party/blink/renderer/platform/weborigin/security_origin.h"
 #include "third_party/blink/renderer/platform/wtf/casting.h"
@@ -323,15 +321,6 @@
   Unwrap<Document>()->SetCookieManager(std::move(cookie_manager));
 }
 
-WebElement WebDocument::GetElementByDevToolsNodeId(const int node_id) {
-  Node* node = DOMNodeIds::NodeForId(static_cast<DOMNodeId>(node_id));
-  if (!node || !node->IsElementNode() ||
-      !node->IsDescendantOrShadowDescendantOf(private_.Get())) {
-    return WebElement();
-  }
-  return WebElement(blink::To<Element>(node));
-}
-
 WebDocument::WebDocument(Document* elem) : WebNode(elem) {}
 
 DEFINE_WEB_NODE_TYPE_CASTS(WebDocument, ConstUnwrap<Node>()->IsDocumentNode())
diff --git a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
index cfb1e91..663323a 100644
--- a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.cc
@@ -179,7 +179,7 @@
   return weak_factory_.GetWeakPtr();
 }
 
-void PushableMediaStreamVideoSource::SetCanDiscardAlpha(
+void PushableMediaStreamVideoSource::OnSourceCanDiscardAlpha(
     bool can_discard_alpha) {
   broker_->SetCanDiscardAlpha(can_discard_alpha);
 }
diff --git a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
index ce8daa72..c8999ca 100644
--- a/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
+++ b/third_party/blink/renderer/modules/breakout_box/pushable_media_stream_video_source.h
@@ -103,7 +103,7 @@
       VideoCaptureCropVersionCB crop_version_callback) override;
   void StopSourceImpl() override;
   base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() override;
-  void SetCanDiscardAlpha(bool can_discard_alpha) override;
+  void OnSourceCanDiscardAlpha(bool can_discard_alpha) override;
   // This function can be called on any thread.
   media::VideoCaptureFeedbackCB GetFeedbackCallback() const override;
 
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
index db093b5e..4e36e78 100644
--- a/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
+++ b/third_party/blink/renderer/modules/credentialmanagement/credentials_container.cc
@@ -977,40 +977,42 @@
     return false;
   }
 
-  // Currently discoverable credentials on Android do not support the payment
-  // extension. As such, we only allow residentKey=preferred, and later
-  // internally map it to discouraged to receive a non-discoverable credential.
-  //
-  // We do not allow developers to directly specify residentKey=discouraged for
-  // Android, in order to align behavior with desktop platforms.
-  //
-  // TODO(crbug.com/1393662): Remove Android-specific code once OS-level support
-  // is available.
-#if BUILDFLAG(IS_ANDROID)
-  if (!authenticator->hasResidentKey() ||
-      authenticator->residentKey() != "preferred") {
-    resolver->Reject(MakeGarbageCollected<DOMException>(
-        DOMExceptionCode::kNotSupportedError,
-        "A resident key must be 'preferred' for 'payment' extension "
-        "('required' is not supported on Android at this time: "
-        "https://crbug.com/1393662)."));
-    return false;
+  if (RuntimeEnabledFeatures::
+          AllowDiscoverableCredentialsForSecurePaymentConfirmationEnabled()) {
+    if ((!authenticator->hasResidentKey() &&
+         !authenticator->hasRequireResidentKey()) ||
+        (authenticator->hasResidentKey() &&
+         authenticator->residentKey() == "discouraged") ||
+        (!authenticator->hasResidentKey() &&
+         authenticator->hasRequireResidentKey() &&
+         !authenticator->requireResidentKey())) {
+      resolver->Reject(MakeGarbageCollected<DOMException>(
+          DOMExceptionCode::kNotSupportedError,
+          "A resident key must be 'preferred' or 'required' for 'payment' "
+          "extension."));
+      return false;
+    }
+  } else {
+    // Currently discoverable credentials on Android do not support the payment
+    // extension. As such, we only allow residentKey=preferred, and later
+    // internally map it to discouraged to receive a non-discoverable
+    // credential.
+    //
+    // We do not allow developers to directly specify residentKey=discouraged
+    // for Android, in order to align behavior with desktop platforms.
+    //
+    // TODO(crbug.com/1393662): Remove Android-specific code once OS-level
+    // support is available.
+    if (!authenticator->hasResidentKey() ||
+        authenticator->residentKey() != "preferred") {
+      resolver->Reject(MakeGarbageCollected<DOMException>(
+          DOMExceptionCode::kNotSupportedError,
+          "A resident key must be 'preferred' for 'payment' extension "
+          "('required' is not supported on Android at this time: "
+          "https://crbug.com/1393662)."));
+      return false;
+    }
   }
-#else
-  if ((!authenticator->hasResidentKey() &&
-       !authenticator->hasRequireResidentKey()) ||
-      (authenticator->hasResidentKey() &&
-       authenticator->residentKey() == "discouraged") ||
-      (!authenticator->hasResidentKey() &&
-       authenticator->hasRequireResidentKey() &&
-       !authenticator->requireResidentKey())) {
-    resolver->Reject(MakeGarbageCollected<DOMException>(
-        DOMExceptionCode::kNotSupportedError,
-        "A resident key must be 'preferred' or 'required' for 'payment' "
-        "extension."));
-    return false;
-  }
-#endif
 
   if (!authenticator->hasAuthenticatorAttachment() ||
       authenticator->authenticatorAttachment() != "platform") {
diff --git a/third_party/blink/renderer/modules/imagecapture/README.md b/third_party/blink/renderer/modules/imagecapture/README.md
index 90bdda1b..58908a35 100644
--- a/third_party/blink/renderer/modules/imagecapture/README.md
+++ b/third_party/blink/renderer/modules/imagecapture/README.md
@@ -30,8 +30,7 @@
     `ImageBitmap` will only have the resolution of the video track — which
     will generally be lower than the camera's still-image resolution.
 
-(_Adapted from the [Origin Trials Web Update post](
-https://developers.google.com/web/updates/2016/12/imagecapture)_)
+(_Adapted from the [blog post](https://developer.chrome.com/blog/imagecapture/)_)
 
 
 ### Photo settings and capabilities
@@ -50,9 +49,9 @@
 |[`PhotoSettings`]         |non-live settings    |`theImageCapturer.takePhoto(photoSettings)`|
 |[`MediaTrackSettings`]    |live settings        |`theTrack.getSettings()`                 |
 
-[`PhotoCapabilities`]: https://w3c.github.io/mediacapture-image/##photocapabilities-section
+[`PhotoCapabilities`]: https://w3c.github.io/mediacapture-image/#photocapabilities-section
 [`MediaTrackCapabilities`]: https://w3c.github.io/mediacapture-image/#mediatrackcapabilities-section
-[`PhotoSettings`]: https://w3c.github.io/mediacapture-image/##photosettings-section
+[`PhotoSettings`]: https://w3c.github.io/mediacapture-image/#photosettings-section
 [`MediaTrackSettings`]: https://w3c.github.io/mediacapture-image/#mediatracksettings-section
 
 ## Other topics
@@ -123,10 +122,7 @@
 
 ## Testing
 
-Image Capture web tests are located in [web_tests/imagecapture],
-[web_tests/fast/imagecapture] and [web_tests/external/mediacapture-image].
+Image Capture web tests are located in [web_tests/external/mediacapture-image].
 
-[web_tests/imagecapture]: https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/web_tests/imagecapture
-[web_tests/fast/imagecapture]: https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/web_tests/fast/imagecapture/
 [web_tests/external/mediacapture-image]: https://chromium.googlesource.com/chromium/src/+/main/third_party/blink/web_tests/external/wpt/mediacapture-image/
 
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
index 15a0bc4..e5c1a8a 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -290,11 +290,11 @@
                                   WrapPersistent(this)));
 }
 
-ScriptPromise ImageCapture::setOptions(ScriptState* script_state,
-                                       const PhotoSettings* photo_settings,
-                                       bool trigger_take_photo /* = false */) {
+ScriptPromise ImageCapture::takePhoto(ScriptState* script_state,
+                                      const PhotoSettings* photo_settings) {
   TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
-                       "ImageCapture::setOptions", TRACE_EVENT_SCOPE_PROCESS);
+                       "ImageCapture::takePhoto", TRACE_EVENT_SCOPE_PROCESS);
+
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
 
@@ -370,20 +370,10 @@
   service_->SetOptions(
       SourceId(), std::move(settings),
       WTF::BindOnce(&ImageCapture::OnMojoSetOptions, WrapPersistent(this),
-                    WrapPersistent(resolver), trigger_take_photo));
+                    WrapPersistent(resolver), /*trigger_take_photo=*/true));
   return promise;
 }
 
-ScriptPromise ImageCapture::takePhoto(ScriptState* script_state,
-                                      const PhotoSettings* photo_settings) {
-  TRACE_EVENT_INSTANT0(TRACE_DISABLED_BY_DEFAULT("video_and_image_capture"),
-                       "ImageCapture::takePhoto (with settings)",
-                       TRACE_EVENT_SCOPE_PROCESS);
-
-  return setOptions(script_state, photo_settings,
-                    true /* trigger_take_photo */);
-}
-
 ScriptPromise ImageCapture::grabFrame(ScriptState* script_state) {
   auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
   ScriptPromise promise = resolver->Promise();
@@ -796,13 +786,14 @@
   service_->SetOptions(
       SourceId(), std::move(settings),
       WTF::BindOnce(&ImageCapture::OnMojoSetOptions, WrapPersistent(this),
-                    WrapPersistent(resolver), false /* trigger_take_photo */));
+                    WrapPersistent(resolver), /*trigger_take_photo=*/false));
 }
 
 void ImageCapture::SetPanTiltZoomSettingsFromTrack(
     base::OnceClosure initialized_callback,
     media::mojom::blink::PhotoStatePtr photo_state) {
-  UpdateMediaTrackCapabilities(base::DoNothing(), std::move(photo_state));
+  UpdateMediaTrackSettingsAndCapabilities(base::DoNothing(),
+                                          std::move(photo_state));
 
   auto* video_track = MediaStreamVideoTrack::From(stream_track_->Component());
   DCHECK(video_track);
@@ -862,7 +853,7 @@
     bool result) {
   service_->GetPhotoState(
       SourceId(),
-      WTF::BindOnce(&ImageCapture::UpdateMediaTrackCapabilities,
+      WTF::BindOnce(&ImageCapture::UpdateMediaTrackSettingsAndCapabilities,
                     WrapPersistent(this), std::move(done_callback)));
 }
 
@@ -967,7 +958,7 @@
       SourceId(),
       WTF::BindOnce(&ImageCapture::OnMojoGetPhotoState, WrapPersistent(this),
                     WrapPersistent(resolver), std::move(resolver_cb),
-                    false /* trigger_take_photo */));
+                    /*trigger_take_photo=*/false));
   return promise;
 }
 
@@ -1017,7 +1008,8 @@
     photo_capabilities_->setFillLightMode(fill_light_mode);
 
   // Update the local track photo_state cache.
-  UpdateMediaTrackCapabilities(base::DoNothing(), std::move(photo_state));
+  UpdateMediaTrackSettingsAndCapabilities(base::DoNothing(),
+                                          std::move(photo_state));
 
   if (trigger_take_photo) {
     service_->TakePhoto(
@@ -1074,7 +1066,7 @@
   service_requests_.erase(resolver);
 }
 
-void ImageCapture::UpdateMediaTrackCapabilities(
+void ImageCapture::UpdateMediaTrackSettingsAndCapabilities(
     base::OnceClosure initialized_callback,
     media::mojom::blink::PhotoStatePtr photo_state) {
   if (!photo_state) {
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.h b/third_party/blink/renderer/modules/imagecapture/image_capture.h
index 4e2acaa..66211a2c 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.h
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.h
@@ -68,13 +68,7 @@
 
   ScriptPromise getPhotoCapabilities(ScriptState*);
   ScriptPromise getPhotoSettings(ScriptState*);
-
-  ScriptPromise setOptions(ScriptState*,
-                           const PhotoSettings*,
-                           bool trigger_take_photo = false);
-
   ScriptPromise takePhoto(ScriptState*, const PhotoSettings*);
-
   ScriptPromise grabFrame(ScriptState*);
 
   void GetMediaTrackCapabilities(MediaTrackCapabilities*) const;
@@ -123,7 +117,7 @@
   // Update local track settings and capabilities and call
   // |initialized_callback| to indicate settings and capabilities have been
   // retrieved.
-  void UpdateMediaTrackCapabilities(
+  void UpdateMediaTrackSettingsAndCapabilities(
       base::OnceClosure initialized_callback,
       media::mojom::blink::PhotoStatePtr photo_state);
 
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.idl b/third_party/blink/renderer/modules/imagecapture/image_capture.idl
index de6c6d30..571ad679 100644
--- a/third_party/blink/renderer/modules/imagecapture/image_capture.idl
+++ b/third_party/blink/renderer/modules/imagecapture/image_capture.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/mediacapture-image/#ImageCaptureAPI
+// https://w3c.github.io/mediacapture-image/#imagecaptureapi
 
 [
     ActiveScriptWrappable,
diff --git a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.idl b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.idl
index e18e0fa5..84d79d8 100644
--- a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.idl
+++ b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.idl
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/mediacapture-image/##photocapabilities-section
+// https://w3c.github.io/mediacapture-image/#photocapabilities-section
 
 enum MeteringMode {
     "none",
diff --git a/third_party/blink/renderer/modules/imagecapture/photo_settings.idl b/third_party/blink/renderer/modules/imagecapture/photo_settings.idl
index 162e16a..26ca776f 100644
--- a/third_party/blink/renderer/modules/imagecapture/photo_settings.idl
+++ b/third_party/blink/renderer/modules/imagecapture/photo_settings.idl
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// https://w3c.github.io/mediacapture-image/##photosettings-section
+// https://w3c.github.io/mediacapture-image/#photosettings-section
 
 dictionary PhotoSettings {
-    boolean redEyeReduction;
+    FillLightMode fillLightMode;
     double imageHeight;
     double imageWidth;
-    FillLightMode fillLightMode;
+    boolean redEyeReduction;
 };
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
index 7ab6ee5..55282cc 100644
--- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
+++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc
@@ -129,7 +129,7 @@
     EXPECT_CALL(*mock_source_, GetCropVersion())
         .Times(testing::AnyNumber())
         .WillRepeatedly(Return(0));
-    EXPECT_CALL(*mock_source_, SetCanDiscardAlpha(_))
+    EXPECT_CALL(*mock_source_, OnSourceCanDiscardAlpha(_))
         .Times(testing::AnyNumber());
 
     auto platform_track = std::make_unique<MediaStreamVideoTrack>(
diff --git a/third_party/blink/renderer/modules/mediastream/DEPS b/third_party/blink/renderer/modules/mediastream/DEPS
index cfd2875..9bffb39 100644
--- a/third_party/blink/renderer/modules/mediastream/DEPS
+++ b/third_party/blink/renderer/modules/mediastream/DEPS
@@ -25,7 +25,6 @@
     "+services/viz/public/cpp/gpu/context_provider_command_buffer.h",
     "+skia/ext/platform_canvas.h",
 
-    "+base/atomicops.h",
     "+base/task/bind_post_task.h",
     "+base/files/file.h",
     "+base/metrics/field_trial.h",
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
index ce6d90e..97656c97 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.cc
@@ -66,7 +66,7 @@
   device_capturer_factory_callback_ = std::move(testing_factory_callback);
 }
 
-void MediaStreamVideoCapturerSource::SetCanDiscardAlpha(
+void MediaStreamVideoCapturerSource::OnSourceCanDiscardAlpha(
     bool can_discard_alpha) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
   source_->SetCanDiscardAlpha(can_discard_alpha);
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
index cfda7bd..a6cdd8dd 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_capturer_source.h
@@ -76,7 +76,7 @@
   FRIEND_TEST_ALL_PREFIXES(MediaStreamVideoCapturerSourceTest, ChangeSource);
 
   // MediaStreamVideoSource overrides.
-  void SetCanDiscardAlpha(bool can_discard_alpha) override;
+  void OnSourceCanDiscardAlpha(bool can_discard_alpha) override;
   void RequestRefreshFrame() override;
   void OnFrameDropped(media::VideoCaptureFrameDropReason reason) override;
   void OnLog(const std::string& message) override;
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
index dbd3ea7..5a823da 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -132,6 +132,8 @@
       break;
     }
   }
+
+  UpdateCanDiscardAlpha();
 }
 
 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track,
@@ -200,6 +202,8 @@
   } else if (callback) {
     std::move(callback).Run();
   }
+
+  UpdateCanDiscardAlpha();
 }
 
 void MediaStreamVideoSource::DidStopSource(RestartResult result) {
@@ -582,4 +586,16 @@
   return track_adapter_;
 }
 
+void MediaStreamVideoSource::UpdateCanDiscardAlpha() {
+  DCHECK(GetTaskRunner()->BelongsToCurrentThread());
+  bool using_alpha = false;
+  for (auto* track : tracks_) {
+    if (track->UsingAlpha()) {
+      using_alpha = true;
+      break;
+    }
+  }
+  OnSourceCanDiscardAlpha(!using_alpha);
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
index ae4bdf1..6ca2221 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source_test.cc
@@ -53,7 +53,7 @@
         String::FromUTF8("dummy_source_id"), MediaStreamSource::kTypeVideo,
         String::FromUTF8("dummy_source_name"), false /* remote */,
         base::WrapUnique(mock_stream_video_source_));
-    ON_CALL(*mock_stream_video_source_, SetCanDiscardAlpha)
+    ON_CALL(*mock_stream_video_source_, OnSourceCanDiscardAlpha)
         .WillByDefault(Return());
     ON_CALL(*mock_stream_video_source_, SupportsEncodedOutput)
         .WillByDefault(Return(true));
@@ -1079,17 +1079,22 @@
   MockMediaStreamVideoSink sink_alpha;
   sink_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kDefault);
 
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
   sink_no_alpha.ConnectToTrack(track);
 
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
   sink_alpha.ConnectToTrack(track);
 
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
   sink_no_alpha.DisconnectFromTrack();
 
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+  // Called once when removing the sink from the track, again when the track is
+  // removed from the source.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
   sink_alpha.DisconnectFromTrack();
+
+  // Extra call when destroying the track.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
 }
 
 TEST_F(MediaStreamVideoSourceTest, CanDiscardAlphaIfOtherSinksDiscard) {
@@ -1105,29 +1110,62 @@
   sink_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kDefault);
 
   // Keep alpha if the only sink is DependsOnOtherSinks.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
   sink_depends.ConnectToTrack(track);
 
   // Now alpha can be dropped since other sink drops alpha.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
   sink_no_alpha.ConnectToTrack(track);
 
   // Alpha can not longer be dropped since a sink uses it.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
   sink_alpha.ConnectToTrack(track);
 
   // Now that alpha track is removes, alpha can be discarded again.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
   sink_alpha.DisconnectFromTrack();
 
   // Now that the alpha dropping track is disconnected, we keep alpha since the
   // only sink depends on other sinks, which keeps alpha by default.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(false));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
   sink_no_alpha.DisconnectFromTrack();
 
   // Alpha is discarded if there are no sinks connected.
-  EXPECT_CALL(*mock_source(), SetCanDiscardAlpha(true));
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
   sink_depends.DisconnectFromTrack();
+
+  // Extra call when destroying the track.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
+}
+
+TEST_F(MediaStreamVideoSourceTest, CanDiscardAlphaMultipleTracks) {
+  InSequence s;
+  WebMediaStreamTrack track_no_alpha = CreateTrack();
+  WebMediaStreamTrack track_with_alpha = CreateTrack();
+
+  MockMediaStreamVideoSink sink_no_alpha;
+  sink_no_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kNo);
+  MockMediaStreamVideoSink sink_alpha;
+  sink_alpha.SetUsesAlpha(MediaStreamVideoSink::UsesAlpha::kDefault);
+
+  // Adding just the track with no alpha, the source can discard alpha.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
+  sink_no_alpha.ConnectToTrack(track_no_alpha);
+
+  // Adding both tracks, the source can no longer discard.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
+  sink_alpha.ConnectToTrack(track_with_alpha);
+
+  // Even when removing the track with no alpha, we still can't discard alpha.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(false));
+  sink_no_alpha.DisconnectFromTrack();
+
+  // Removing all tracks, we can now discard alpha again.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true));
+  sink_alpha.DisconnectFromTrack();
+
+  // Extra call when destroying the tracks.
+  EXPECT_CALL(*mock_source(), OnSourceCanDiscardAlpha(true)).Times(2);
 }
 
 }  // namespace blink
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
index 5569664..15420cd 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -768,15 +768,23 @@
   RequestRefreshFrame();
   source_->UpdateCapturingLinkSecure(this,
                                      secure_tracker_.is_capturing_secure());
-  // Alpha can't be discarded if any sink uses alpha, or if the only sinks
-  // connected are kDependsOnOtherSinks.
-  const bool can_discard_alpha =
-      alpha_using_sinks_.empty() && !alpha_discarding_sinks_.empty();
-  source_->SetCanDiscardAlpha(can_discard_alpha);
+
+  source_->UpdateCanDiscardAlpha();
+
   if (is_screencast_)
     StartTimerForRequestingFrames();
 }
 
+bool MediaStreamVideoTrack::UsingAlpha() {
+  // Alpha can't be discarded if any sink uses alpha, or if the only sinks
+  // connected are kDependsOnOtherSinks.
+  bool only_sinks_with_alpha_depending_on_other_sinks =
+      !sinks_.empty() && alpha_using_sinks_.empty() &&
+      alpha_discarding_sinks_.empty();
+  return !alpha_using_sinks_.empty() ||
+         only_sinks_with_alpha_depending_on_other_sinks;
+}
+
 void MediaStreamVideoTrack::SetSinkNotifyFrameDroppedCallback(
     WebMediaStreamSink* sink,
     const VideoCaptureNotifyFrameDroppedCB& callback) {
@@ -807,10 +815,8 @@
   UpdateSourceHasConsumers();
   source_->UpdateCapturingLinkSecure(this,
                                      secure_tracker_.is_capturing_secure());
-  const bool can_discard_alpha =
-      sinks_.empty() ||
-      (alpha_using_sinks_.empty() && !alpha_discarding_sinks_.empty());
-  source_->SetCanDiscardAlpha(can_discard_alpha);
+
+  source_->UpdateCanDiscardAlpha();
   // Restart the timer with existing sinks.
   if (is_screencast_)
     StartTimerForRequestingFrames();
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
index e359080b..9686bb2 100644
--- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
+++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.h
@@ -193,6 +193,8 @@
     return MediaStreamTrackPlatform::StreamType::kVideo;
   }
 
+  bool UsingAlpha();
+
  private:
   FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, StartTrack);
   FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, RemoteTrackStop);
diff --git a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
index 5c6adbe0..76abdf5e 100644
--- a/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
+++ b/third_party/blink/renderer/modules/mediastream/mock_media_stream_video_source.h
@@ -29,7 +29,7 @@
   MOCK_METHOD0(OnEncodedSinkDisabled, void());
   MOCK_METHOD0(OnRequestRefreshFrame, void());
   MOCK_METHOD1(OnCapturingLinkSecured, void(bool));
-  MOCK_METHOD1(SetCanDiscardAlpha, void(bool can_discard_alpha));
+  MOCK_METHOD1(OnSourceCanDiscardAlpha, void(bool can_discard_alpha));
   MOCK_CONST_METHOD0(SupportsEncodedOutput, bool());
   MOCK_METHOD1(OnFrameDropped, void(media::VideoCaptureFrameDropReason));
   MOCK_METHOD3(Crop,
diff --git a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.h b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.h
index 2038a42..119dadd 100644
--- a/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.h
+++ b/third_party/blink/renderer/modules/mediastream/processed_local_audio_source.h
@@ -7,7 +7,6 @@
 
 #include <string>
 
-#include "base/atomicops.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/synchronization/lock.h"
 #include "base/task/single_thread_task_runner.h"
diff --git a/third_party/blink/renderer/platform/heap/DEPS b/third_party/blink/renderer/platform/heap/DEPS
index bd01526..8d536734 100644
--- a/third_party/blink/renderer/platform/heap/DEPS
+++ b/third_party/blink/renderer/platform/heap/DEPS
@@ -6,7 +6,6 @@
     "+third_party/blink/renderer/platform/heap",
 
     # Dependencies.
-    "+base/atomicops.h",
     "+base/bits.h",
     "+base/functional/unretained_traits.h",
     "+base/sampling_heap_profiler/poisson_allocation_sampler.h",
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
index 0520f8b..f889633 100644
--- a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
+++ b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.cc
@@ -109,7 +109,7 @@
   traced_value_->AppendAsTraceFormat(out);
 }
 
-bool TracedValue::AppendToProto(ProtoAppender* appender) {
+bool TracedValue::AppendToProto(ProtoAppender* appender) const {
   return traced_value_->AppendToProto(appender);
 }
 
diff --git a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
index 4b4fae3..157803b 100644
--- a/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
+++ b/third_party/blink/renderer/platform/instrumentation/tracing/traced_value.h
@@ -57,7 +57,7 @@
  private:
   // ConvertableToTraceFormat
   void AppendAsTraceFormat(std::string*) const final;
-  bool AppendToProto(ProtoAppender* appender) final;
+  bool AppendToProto(ProtoAppender* appender) const final;
   void EstimateTraceMemoryOverhead(
       base::trace_event::TraceEventMemoryOverhead*) final;
 };
diff --git a/third_party/blink/renderer/platform/mediastream/DEPS b/third_party/blink/renderer/platform/mediastream/DEPS
index 9a36779a..f564a4cd 100644
--- a/third_party/blink/renderer/platform/mediastream/DEPS
+++ b/third_party/blink/renderer/platform/mediastream/DEPS
@@ -6,7 +6,6 @@
     "+third_party/blink/renderer/platform/mediastream",
 
     # Dependencies.
-    "+base/atomicops.h",
     "+media/base",
     "+media/webrtc/audio_processor_controls.h",
     "+media/webrtc/webrtc_features.h",
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
index e173770..c9f63ca 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.cc
@@ -4,6 +4,7 @@
 
 #include "third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h"
 
+#include <atomic>
 #include <string>
 #include <utility>
 
@@ -57,7 +58,7 @@
   }
 
   deliverer_.AddConsumer(sink);
-  sink->OnEnabledChanged(!!base::subtle::NoBarrier_Load(&is_enabled_));
+  sink->OnEnabledChanged(is_enabled_.load(std::memory_order_relaxed));
 }
 
 void MediaStreamAudioTrack::RemoveSink(WebMediaStreamAudioSink* sink) {
@@ -76,7 +77,7 @@
             (enabled ? "true" : "false"));
 
   const bool previously_enabled =
-      !!base::subtle::NoBarrier_AtomicExchange(&is_enabled_, enabled ? 1 : 0);
+      is_enabled_.exchange(enabled, std::memory_order_relaxed);
   if (enabled == previously_enabled)
     return;
 
@@ -88,7 +89,7 @@
 
 bool MediaStreamAudioTrack::IsEnabled() const {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-  return is_enabled_;
+  return is_enabled_.load(std::memory_order_relaxed);
 }
 
 void MediaStreamAudioTrack::SetContentHint(
@@ -156,9 +157,9 @@
     received_audio_callback_ = true;
   }
 
-  // Note: Using NoBarrier_Load because the timing of when the audio thread sees
-  // a changed |is_enabled_| value can be relaxed.
-  const bool deliver_data = !!base::subtle::NoBarrier_Load(&is_enabled_);
+  // Note: Using relaxed ordering because the timing of when the audio thread
+  // sees a changed |is_enabled_| value can be relaxed.
+  const bool deliver_data = is_enabled_.load(std::memory_order_relaxed);
 
   if (deliver_data) {
     deliverer_.OnData(audio_bus, reference_time);
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
index 8c7edab..33e9d41 100644
--- a/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_audio_track.h
@@ -7,7 +7,6 @@
 
 #include <memory>
 
-#include "base/atomicops.h"
 #include "base/functional/callback.h"
 #include "base/memory/weak_ptr.h"
 #include "base/synchronization/lock.h"
@@ -116,8 +115,8 @@
   // Manages sinks connected to this track and the audio format and data flow.
   MediaStreamAudioDeliverer<WebMediaStreamAudioSink> deliverer_;
 
-  // While false (0), silent audio is delivered to the sinks.
-  base::subtle::Atomic32 is_enabled_;
+  // While false, silent audio is delivered to the sinks.
+  std::atomic<bool> is_enabled_;
 
   // Buffer used to deliver silent audio data while this track is disabled.
   std::unique_ptr<media::AudioBus> silent_bus_;
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
index c9af57f..ab119b4 100644
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -122,7 +122,7 @@
     //
     // The default value of the base::Feature instance is:
     //  base::FEATURE_ENABLED_BY_DEFAULT if 'status' field is 'stable", and
-    //  base::FEATURE_DISABLED_BY_DEFAULT otheriwse.
+    //  base::FEATURE_DISABLED_BY_DEFAULT otherwise.
     // It can be overridden by 'base_feature_status' field.
     //
     // If the flag should be associated with a feature not in blink::features,
@@ -285,6 +285,13 @@
       name: "AllowContentInitiatedDataUrlNavigations",
     },
     {
+      // TODO(crbug.com/1393662): Remove this flag once Android supports
+      // creating discoverable credentials with the 'payment' extension.
+      name: "AllowDiscoverableCredentialsForSecurePaymentConfirmation",
+      base_feature: "AllowDiscoverableCredentialsForSecurePaymentConfirmation",
+      status: {"Android": "", "default": "stable"},
+    },
+    {
       name: "AndroidDownloadableFontsMatching",
       public: true,
     },
@@ -2084,7 +2091,6 @@
     {
       name: "PaymentInstruments",
       depends_on: ["PaymentApp"],
-      status: "stable",
     },
     {
       name: "PaymentMethodChangeEvent",
diff --git a/third_party/blink/renderer/platform/scheduler/DEPS b/third_party/blink/renderer/platform/scheduler/DEPS
index 71a0712..13accc51 100644
--- a/third_party/blink/renderer/platform/scheduler/DEPS
+++ b/third_party/blink/renderer/platform/scheduler/DEPS
@@ -7,7 +7,6 @@
 
   # Dependencies.
   "+base/atomic_sequence_num.h",
-  "+base/atomicops.h",
   "+base/barrier_closure.h",
   "+base/cancelable_callback.h",
   "+base/command_line.h",
diff --git a/third_party/blink/renderer/platform/scheduler/common/auto_advancing_virtual_time_domain.cc b/third_party/blink/renderer/platform/scheduler/common/auto_advancing_virtual_time_domain.cc
index ee153d3..6d3bc76 100644
--- a/third_party/blink/renderer/platform/scheduler/common/auto_advancing_virtual_time_domain.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/auto_advancing_virtual_time_domain.cc
@@ -6,7 +6,6 @@
 
 #include <atomic>
 
-#include "base/atomicops.h"
 #include "base/time/time_override.h"
 #include "build/build_config.h"
 #include "third_party/blink/renderer/platform/scheduler/common/scheduler_helper.h"
diff --git a/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc b/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
index 1fe0a5b..090ad71 100644
--- a/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.cc
@@ -4,14 +4,16 @@
 
 #include "third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h"
 
+#include <atomic>
+
 PollableThreadSafeFlag::PollableThreadSafeFlag(base::Lock* write_lock_)
     : flag_(false), write_lock_(write_lock_) {}
 
 void PollableThreadSafeFlag::SetWhileLocked(bool value) {
   write_lock_->AssertAcquired();
-  base::subtle::Release_Store(&flag_, value);
+  flag_.store(value, std::memory_order_release);
 }
 
 bool PollableThreadSafeFlag::IsSet() const {
-  return base::subtle::Acquire_Load(&flag_);
+  return flag_.load(std::memory_order_acquire);
 }
diff --git a/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h b/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
index 2553a51e..4b8fe269 100644
--- a/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
+++ b/third_party/blink/renderer/platform/scheduler/common/pollable_thread_safe_flag.h
@@ -5,7 +5,8 @@
 #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_
 #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_COMMON_POLLABLE_THREAD_SAFE_FLAG_H_
 
-#include "base/atomicops.h"
+#include <atomic>
+
 #include "base/synchronization/lock.h"
 #include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
 
@@ -30,7 +31,7 @@
   bool IsSet() const;
 
  private:
-  base::subtle::Atomic32 flag_;
+  std::atomic<bool> flag_;
   base::Lock* write_lock_;  // Not owned.
 };
 
diff --git a/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc b/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
index 6f9d1e0..a8a7e32 100644
--- a/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
+++ b/third_party/blink/renderer/platform/scheduler/common/thread_cpu_throttler.cc
@@ -4,9 +4,9 @@
 
 #include "third_party/blink/renderer/platform/scheduler/public/thread_cpu_throttler.h"
 
+#include <atomic>
 #include <memory>
 
-#include "base/atomicops.h"
 #include "base/logging.h"
 #include "base/memory/singleton.h"
 #include "base/synchronization/atomic_flag.h"
@@ -21,10 +21,6 @@
 #include <windows.h>
 #endif
 
-using base::subtle::Atomic32;
-using base::subtle::Acquire_Load;
-using base::subtle::Release_Store;
-
 namespace blink {
 namespace scheduler {
 
@@ -57,8 +53,8 @@
   static bool signal_handler_installed_;
   static struct sigaction old_signal_handler_;
 #endif
-  static Atomic32 thread_exists_;
-  static Atomic32 throttling_rate_percent_;
+  static std::atomic<bool> thread_exists_;
+  static std::atomic<int> throttling_rate_percent_;
 
   base::PlatformThreadHandle throttled_thread_handle_;
   base::PlatformThreadHandle throttling_thread_handle_;
@@ -69,8 +65,8 @@
 bool ThreadCPUThrottler::ThrottlingThread::signal_handler_installed_;
 struct sigaction ThreadCPUThrottler::ThrottlingThread::old_signal_handler_;
 #endif
-Atomic32 ThreadCPUThrottler::ThrottlingThread::throttling_rate_percent_;
-Atomic32 ThreadCPUThrottler::ThrottlingThread::thread_exists_;
+std::atomic<int> ThreadCPUThrottler::ThrottlingThread::throttling_rate_percent_;
+std::atomic<bool> ThreadCPUThrottler::ThrottlingThread::thread_exists_;
 
 ThreadCPUThrottler::ThrottlingThread::ThrottlingThread(double rate)
 #ifdef OS_WIN
@@ -80,17 +76,18 @@
     : throttled_thread_handle_(base::PlatformThread::CurrentHandle()) {
 #endif
   SetThrottlingRate(rate);
-  CHECK_EQ(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 1), 0);
+  CHECK(!thread_exists_.exchange(true, std::memory_order_relaxed));
   Start();
 }  // namespace scheduler
 
 ThreadCPUThrottler::ThrottlingThread::~ThrottlingThread() {
   Stop();
-  CHECK_EQ(base::subtle::NoBarrier_AtomicExchange(&thread_exists_, 0), 1);
+  CHECK(thread_exists_.exchange(false, std::memory_order_relaxed));
 }
 
 void ThreadCPUThrottler::ThrottlingThread::SetThrottlingRate(double rate) {
-  Release_Store(&throttling_rate_percent_, static_cast<Atomic32>(rate * 100));
+  throttling_rate_percent_.store(static_cast<int>(rate * 100),
+                                 std::memory_order_release);
 }
 
 void ThreadCPUThrottler::ThrottlingThread::ThreadMain() {
@@ -132,7 +129,8 @@
   static base::TimeTicks lastResumeTime;
   base::TimeTicks now = base::TimeTicks::Now();
   base::TimeDelta run_duration = now - lastResumeTime;
-  uint32_t throttling_rate_percent = Acquire_Load(&throttling_rate_percent_);
+  uint32_t throttling_rate_percent =
+      throttling_rate_percent_.load(std::memory_order_acquire);
   // Limit the observed run duration to 1000μs to deal with the first entrance
   // to the signal handler.
   uint32_t run_duration_us = static_cast<uint32_t>(
@@ -154,7 +152,7 @@
   pthread_kill(throttled_thread_handle_.platform_handle(), SIGUSR2);
   Sleep(base::Microseconds(quant_time_us));
 #elif BUILDFLAG(IS_WIN)
-  double rate = Acquire_Load(&throttling_rate_percent_) / 100.;
+  double rate = throttling_rate_percent_.load(std::memory_order_acquire) / 100.;
   base::TimeDelta run_duration =
       base::Microseconds(static_cast<int>(quant_time_us / rate));
   base::TimeDelta sleep_duration =
diff --git a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
index e1867d2d..15051d1 100644
--- a/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
+++ b/third_party/blink/renderer/platform/scheduler/main_thread/main_thread_scheduler_impl.h
@@ -9,7 +9,6 @@
 #include <memory>
 #include <stack>
 
-#include "base/atomicops.h"
 #include "base/dcheck_is_on.h"
 #include "base/gtest_prod_util.h"
 #include "base/memory/weak_ptr.h"
diff --git a/third_party/blink/web_tests/SlowTests b/third_party/blink/web_tests/SlowTests
index 4a850ec..036c34f 100644
--- a/third_party/blink/web_tests/SlowTests
+++ b/third_party/blink/web_tests/SlowTests
@@ -552,7 +552,9 @@
 crbug.com/874695 http/tests/fetch/workers/thorough/* [ Slow ]
 crbug.com/874695 [ Debug Mac12 ] http/tests/images/png-progressive-load.html [ Slow ]
 crbug.com/874695 [ Release ] http/tests/images/png-progressive-load.html [ Slow ]
-crbug.com/874695 http/tests/images/webp-progressive-load.html [ Slow ]
+crbug.com/874695 [ Linux Release ] http/tests/images/webp-progressive-load.html [ Slow ]
+crbug.com/874695 [ Mac ] http/tests/images/webp-progressive-load.html [ Slow ]
+crbug.com/874695 [ Release Win ] http/tests/images/webp-progressive-load.html [ Slow ]
 crbug.com/874695 http/tests/media/controls/toggle-class-with-state-source-buffer.html [ Slow ]
 crbug.com/874695 http/tests/media/preload-conditions.html [ Slow ]
 crbug.com/874695 http/tests/media/video-buffered.html [ Slow ]
@@ -686,7 +688,6 @@
 crbug.com/874695 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
 crbug.com/874695 [ Mac10.15 Release ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
 crbug.com/874695 [ Mac11 Release ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
-crbug.com/874695 [ Mac11-arm64 Release ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
 crbug.com/874695 [ Mac12 ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
 crbug.com/874695 [ Release Win ] virtual/threaded/http/tests/devtools/tracing/timeline-style/timeline-style-recalc-all-invalidator-types.js [ Slow ]
 crbug.com/874695 virtual/threaded/synthetic_gestures/synthetic-pinch-zoom-gesture-touchpad-zoom-in-slow.html [ Slow ]
@@ -867,7 +868,6 @@
 crbug.com/982116 [ Linux ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
 crbug.com/982116 [ Mac10.15 Release ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
 crbug.com/982116 [ Mac11 Release ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
-crbug.com/982116 [ Mac11-arm64 Release ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
 crbug.com/982116 [ Mac12 ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
 crbug.com/982116 [ Release Win ] http/tests/devtools/elements/styles-4/styles-new-API.js [ Slow ]
 crbug.com/655458 external/wpt/workers/Worker_terminate_event_queue.htm [ Slow ]
@@ -1349,3 +1349,5 @@
 crbug.com/1372747 [ Win ] http/tests/uri/css-href.php [ Slow ]
 
 crbug.com/1376679 [ Mac12 ] virtual/threaded/external/wpt/scroll-animations/css/scroll-timeline-dynamic.tentative.html [ Slow ]
+
+crbug.com/1366717 http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack.js [ Slow ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index 36ef29c..b0f6e2c 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -3035,7 +3035,6 @@
 crbug.com/626703 external/wpt/webcodecs/videoFrame-serialization.crossAgentCluster.html [ Timeout ]
 crbug.com/626703 [ Win11 ] wpt_internal/geolocation-api/watchPosition-page-visibility.https.html [ Timeout ]
 crbug.com/626703 [ Win10.20h2 ] external/wpt/web-animations/idlharness.window.html [ Crash Failure ]
-crbug.com/626703 [ Mac11 ] external/wpt/performance-timeline/tentative/include-frames-from-child-cross-origin-grandchild.sub.html [ Timeout ]
 crbug.com/626703 [ Mac ] external/wpt/url/a-element-xhtml.xhtml?exclude=(file|javascript|mailto) [ Crash Failure ]
 crbug.com/626703 [ Mac12-arm64 ] virtual/pending-beacon/external/wpt/pending-beacon/pending_post_beacon-cors.tentative.https.window.html [ Timeout ]
 crbug.com/626703 [ Win10.20h2 ] wpt_internal/geolocation-api/watchPosition-page-visibility.https.html [ Timeout ]
@@ -3052,8 +3051,6 @@
 crbug.com/626703 [ Linux ] external/wpt/video-rvfc/request-video-frame-callback-during-xr-session.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/web-nfc/NDEFReader_make-read-only.https.window.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/web-nfc/NDEFReader_scan.https.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/web-nfc/NDEFReader_write.https.html [ Timeout ]
-crbug.com/626703 [ Linux ] external/wpt/webxr/anchors/ar_anchor_states.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/webxr/ar-module/xrSession_interactionMode.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/webxr/dom-overlay/ar_dom_overlay.https.html [ Timeout ]
 crbug.com/626703 [ Linux ] external/wpt/webxr/dom-overlay/ar_dom_overlay_hit_test.https.html [ Timeout ]
@@ -4859,7 +4856,7 @@
 
 # Sheriff 2021-03-19
 crbug.com/1189976 http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints.js [ Failure Pass Timeout ]
-crbug.com/1189976 http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints-editing-dom-from-inspector.js [ Failure Pass Timeout ]
+crbug.com/1189976 [ Debug Mac12 ] http/tests/devtools/sources/debugger-breakpoints/dom-breakpoints-editing-dom-from-inspector.js [ Failure Pass Timeout ]
 crbug.com/1190176 [ Linux ] fast/peerconnection/RTCPeerConnection-addMultipleTransceivers.html [ Crash Failure Pass ]
 
 crbug.com/1176039 [ Mac ] virtual/stable/media/stable/video-object-fit-stable.html [ Failure Pass ]
@@ -5176,7 +5173,6 @@
 crbug.com/1163437 external/wpt/css/css-highlight-api/painting/custom-highlight-painting-below-grammar.html [ Failure ]
 crbug.com/1147859 external/wpt/css/css-highlight-api/painting/custom-highlight-painting-below-target-text.html [ Failure ]
 crbug.com/1147859 [ Linux ] external/wpt/css/css-highlight-api/painting/custom-highlight-painting-004-2.html [ Failure ]
-crbug.com/1147859 [ Linux ] virtual/forced-high-contrast-colors/external/wpt/forced-colors-mode/forced-colors-mode-53.html [ Failure ]
 crbug.com/1147859 [ Mac ] virtual/forced-high-contrast-colors/external/wpt/forced-colors-mode/forced-colors-mode-53.html [ Failure ]
 
 
@@ -6948,3 +6944,9 @@
 # Sheriff 2023-01-24
 crbug.com/1409804 [ Mac ] fast/backgrounds/repeat/negative-offset-repeat-transformed.html [ Failure ]
 crbug.com/1409804 [ Mac ] fast/borders/border-image-rotate-transform.html [ Failure ]
+
+# These tests must be disabled for the next webrtc rollout (2023-01-25), and
+# will be adjusted and reenabled afterwards.
+crbug.com/webrtc/14653 external/wpt/webrtc-stats/outbound-rtp.https.html [ Failure Pass ]
+crbug.com/webrtc/14653 external/wpt/webrtc-stats/rtp-stats-creation.html [ Failure Pass ]
+crbug.com/webrtc/14653 external/wpt/webrtc-stats/supported-stats.https.html [ Failure Pass ]
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html
index 2c6f0b62..1784072 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https.html
@@ -20,25 +20,26 @@
 
 // This document has COOP: restrict-properties. The popup has COOP:
 // restrict-properties. Opening from an iframe should not be different from
-// opening from the main frame and the opener should be severed.
+// opening from the main frame and the opener should be restricted if
+// cross-origin.
 [
   {
     "title": "same origin iframe, same origin popup",
     "iframeOrigin": SAME_ORIGIN,
     "popupOrigin": SAME_ORIGIN,
-    "opener": "restricted"
+    "opener": "preserved"
   },
   {
     "title": "same site iframe, same origin popup",
     "iframeOrigin": SAME_SITE,
     "popupOrigin": SAME_ORIGIN,
-    "opener": "restricted"
+    "opener": "preserved"
   },
   {
     "title": "cross origin iframe, same origin popup",
     "iframeOrigin": CROSS_ORIGIN,
     "popupOrigin": SAME_ORIGIN,
-    "opener": "restricted"
+    "opener": "preserved"
   },
   {
     "title": "same origin iframe, same site popup",
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt
deleted file mode 100644
index 85fef3c9..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt
+++ /dev/null
@@ -1,9 +0,0 @@
-This is a testharness.js-based test.
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with window_open assert_equals: Iframe has dom access to the popup? expected "false" but got "true"
-PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with anchor
-PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with form
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with window_open assert_equals: Iframe has cross origin access to the popup? expected "false" but got "true"
-PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with anchor
-PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with form
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_3-4-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_3-4-expected.txt
index 414431ce..71f4d09 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_3-4-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_3-4-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with cross origin iframe, same origin popup with window_open assert_equals: Iframe has cross origin access to the popup? expected "false" but got "true"
+PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with cross origin iframe, same origin popup with window_open
 PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with cross origin iframe, same origin popup with anchor
 PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with cross origin iframe, same origin popup with form
 FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same site popup with window_open assert_equals: Iframe has cross origin access to the popup? expected "false" but got "true"
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers
deleted file mode 100644
index d5c99062..0000000
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/named_targeting.https.html.headers
+++ /dev/null
@@ -1 +0,0 @@
-Cross-Origin-Opener-Policy: restrict-properties
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
index c7d65ce..7e0d37d 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
@@ -3,6 +3,6 @@
 FAIL Same-origin popup with coop unsafe-none assert_false: Main page has dom access to the popup? expected false got true
 PASS Same-origin popup with coop same-origin
 PASS Same-origin popup with coop same-origin-allow-popups
-FAIL Same-origin popup with coop restrict-properties assert_false: Main page has dom access to the popup? expected false got true
+PASS Same-origin popup with coop restrict-properties
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html
index 491cbc3..c0020fa 100644
--- a/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html
+++ b/third_party/blink/web_tests/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https.html
@@ -34,7 +34,7 @@
   {
     "title": "popup with coop restrict-properties",
     "coop": "restrict-properties",
-    "opener": "restricted"
+    "opener": "preserved"
   }
 ].forEach(variant => {
   popup_test(`Same-origin ${variant.title}`, SAME_ORIGIN,
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl b/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
index d0e5bd9..65b64bd 100644
--- a/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
+++ b/third_party/blink/web_tests/external/wpt/interfaces/payment-handler.idl
@@ -9,7 +9,6 @@
 
 [SecureContext, Exposed=(Window,Worker)]
 interface PaymentManager {
-  [SameObject] readonly attribute PaymentInstruments instruments;
   attribute DOMString userHint;
   Promise<undefined> enableDelegations(sequence<PaymentDelegation> delegations);
 };
@@ -21,28 +20,6 @@
   "payerEmail"
 };
 
-[SecureContext, Exposed=(Window,Worker)]
-interface PaymentInstruments {
-  Promise<boolean> delete(DOMString instrumentKey);
-  Promise<any> get(DOMString instrumentKey);
-  Promise<sequence<DOMString>>  keys();
-  Promise<boolean> has(DOMString instrumentKey);
-  Promise<undefined> set(DOMString instrumentKey, PaymentInstrument details);
-  Promise<undefined> clear();
-};
-
-dictionary PaymentInstrument {
-  required DOMString name;
-  sequence<ImageObject> icons;
-  DOMString method;
-};
-
-dictionary ImageObject {
-    required USVString src;
-    DOMString sizes;
-    DOMString type;
-};
-
 partial interface ServiceWorkerGlobalScope {
   attribute EventHandler oncanmakepayment;
 };
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling-expected.txt b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling-expected.txt
index da3370fc..051564a 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling-expected.txt
@@ -6,8 +6,8 @@
 FAIL An upscaled image (using scale) should report the natural size assert_equals: expected 14098 but got 34652
 PASS An upscaled image (using object-size) should report the natural size
 PASS An intersecting element with a partial-intersecting image (object-position) should report the image intersection
-FAIL A background image larger than the container should report the container size assert_equals: expected (number) 2500 but got (string) "not reported"
-FAIL A background image smaller than the container should report the natural size assert_equals: expected (number) 14098 but got (string) "not reported"
-FAIL A scaled-down background image should report the background size assert_equals: expected (number) 100 but got (string) "not reported"
+PASS A background image larger than the container should report the container size
+PASS A background image smaller than the container should report the natural size
+FAIL A scaled-down background image should report the background size assert_equals: expected 100 but got 14098
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling.html
index a4f7d80..5cb3767ca 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling.html
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/image-upscaling.html
@@ -29,15 +29,18 @@
         applyStyle(image, imageStyle);
         applyStyle(container, containerStyle);
         image.id = token();
+        container.id = token();
         const entryReported = new Promise(resolve => new popup.PerformanceObserver(entryList => {
             entryList.getEntries().forEach(entry => {
-                if (entry.id === image.id)
+                if (entry.id === image.id || entry.id === container.id)
                     resolve(entry.size);
             });
         }).observe({type: 'largest-contentful-paint'}));
         popup.document.body.appendChild(container);
-        const timeout = new Promise(resolve => t.step_timeout(() => resolve('not reported'), 1000));
-        return {lcpSize: (await Promise.any([entryReported, timeout])), naturalSize};
+        return {
+            lcpSize: (await await_with_timeout(1000, 'not reported', entryReported)),
+            naturalSize
+        };
     }
 
     // We set the image to display: none when testing background, so that only the background is reported
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/resources/largest-contentful-paint-helpers.js b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/resources/largest-contentful-paint-helpers.js
index 043587c..b0fe1b08 100644
--- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/resources/largest-contentful-paint-helpers.js
+++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/resources/largest-contentful-paint-helpers.js
@@ -1,6 +1,22 @@
 const image_delay = 1000;
 const delay_pipe_value = image_delay / 1000;
 
+const await_with_timeout = async (delay, message, promise, cleanup = ()=>{}) => {
+  let timeout_id;
+  const timeout = new Promise((_, reject) => {
+    timeout_id = step_timeout(() =>
+      reject(new DOMException(message, "TimeoutError")), delay)
+  });
+  let result = null;
+  try {
+    result = await Promise.race([promise, timeout]);
+    clearTimeout(timeout_id);
+  } finally {
+    cleanup();
+  }
+  return result;
+};
+
 // Receives an image LargestContentfulPaint |entry| and checks |entry|'s attribute values.
 // The |timeLowerBound| parameter is a lower bound on the loadTime value of the entry.
 // The |options| parameter may contain some string values specifying the following:
diff --git a/third_party/blink/web_tests/external/wpt/lint.ignore b/third_party/blink/web_tests/external/wpt/lint.ignore
index 1182195..011f05c60 100644
--- a/third_party/blink/web_tests/external/wpt/lint.ignore
+++ b/third_party/blink/web_tests/external/wpt/lint.ignore
@@ -116,8 +116,6 @@
 CONSOLE: service-workers/service-worker/resources/clients-get-other-origin.html
 CONSOLE: webrtc/tools/*
 CONSOLE: webaudio/resources/audit.js:41
-CONSOLE: resource-timing/resources/resource-loaders.js
-CONSOLE: resource-timing/resources/entry-invariants.js
 
 # use of console in a public library - annotation-model ensures
 # it is not actually used
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js
index dfb0190a..d34e2063 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js
@@ -20,7 +20,6 @@
       idl_array.add_objects({
         ServiceWorkerRegistration: ['registration'],
         PaymentManager: ['paymentManager'],
-        PaymentInstruments: ['instruments'],
       });
     }
     if (isServiceWorker) {
@@ -41,7 +40,6 @@
     }
     if (hasRegistration) {
       self.paymentManager = self.registration.paymentManager;
-      self.instruments = self.paymentManager.instruments;
     }
   }
 );
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
index 1aae22f..dc57fd5 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.js.ini
@@ -14,9 +14,6 @@
   [PaymentManager interface object name]
     expected: FAIL
 
-  [PaymentManager interface: attribute instruments]
-    expected: FAIL
-
   [PaymentManager interface: existence and properties of interface prototype object]
     expected: FAIL
 
@@ -31,9 +28,6 @@
   [CanMakePaymentEvent interface: new CanMakePaymentEvent("type") must inherit property "respondWith(Promise<boolean>)" with the proper type]
     expected: FAIL
 
-  [PaymentManager interface: attribute instruments]
-    expected: FAIL
-
   [PaymentManager interface: attribute userHint]
     expected: FAIL
 
@@ -156,9 +150,6 @@
   [PaymentManager interface object name]
     expected: FAIL
 
-  [PaymentManager interface: attribute instruments]
-    expected: FAIL
-
   [PaymentManager interface: existence and properties of interface prototype object]
     expected: FAIL
 
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
index 6798849..90e3142f 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.serviceworker-expected.txt
@@ -1,5 +1,5 @@
 This is a testharness.js-based test.
-Found 104 tests; 67 PASS, 37 FAIL, 0 TIMEOUT, 0 NOTRUN.
+Found 78 tests; 42 PASS, 36 FAIL, 0 TIMEOUT, 0 NOTRUN.
 PASS idl_test setup
 PASS idl_test validation
 PASS Partial interface ServiceWorkerRegistration: original interface defined
@@ -15,39 +15,13 @@
 FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute instruments assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager must be primary interface of paymentManager assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 PASS Stringification of paymentManager
-PASS PaymentManager interface: paymentManager must inherit property "instruments" with the proper type
 PASS PaymentManager interface: paymentManager must inherit property "userHint" with the proper type
 PASS PaymentManager interface: paymentManager must inherit property "enableDelegations(sequence<PaymentDelegation>)" with the proper type
 PASS PaymentManager interface: calling enableDelegations(sequence<PaymentDelegation>) on paymentManager with too few arguments must throw TypeError
-PASS PaymentInstruments interface: existence and properties of interface object
-PASS PaymentInstruments interface object length
-PASS PaymentInstruments interface object name
-PASS PaymentInstruments interface: existence and properties of interface prototype object
-PASS PaymentInstruments interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentInstruments interface: existence and properties of interface prototype object's @@unscopables property
-PASS PaymentInstruments interface: operation delete(DOMString)
-PASS PaymentInstruments interface: operation get(DOMString)
-PASS PaymentInstruments interface: operation keys()
-PASS PaymentInstruments interface: operation has(DOMString)
-PASS PaymentInstruments interface: operation set(DOMString, PaymentInstrument)
-PASS PaymentInstruments interface: operation clear()
-PASS PaymentInstruments must be primary interface of instruments
-PASS Stringification of instruments
-PASS PaymentInstruments interface: instruments must inherit property "delete(DOMString)" with the proper type
-PASS PaymentInstruments interface: calling delete(DOMString) on instruments with too few arguments must throw TypeError
-PASS PaymentInstruments interface: instruments must inherit property "get(DOMString)" with the proper type
-PASS PaymentInstruments interface: calling get(DOMString) on instruments with too few arguments must throw TypeError
-PASS PaymentInstruments interface: instruments must inherit property "keys()" with the proper type
-PASS PaymentInstruments interface: instruments must inherit property "has(DOMString)" with the proper type
-PASS PaymentInstruments interface: calling has(DOMString) on instruments with too few arguments must throw TypeError
-PASS PaymentInstruments interface: instruments must inherit property "set(DOMString, PaymentInstrument)" with the proper type
-PASS PaymentInstruments interface: calling set(DOMString, PaymentInstrument) on instruments with too few arguments must throw TypeError
-PASS PaymentInstruments interface: instruments must inherit property "clear()" with the proper type
 PASS CanMakePaymentEvent interface: existence and properties of interface object
 FAIL CanMakePaymentEvent interface object length assert_equals: wrong value for CanMakePaymentEvent.length expected 1 but got 2
 PASS CanMakePaymentEvent interface object name
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt
index 2ee5817e..28845dfb 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.sharedworker-expected.txt
@@ -14,21 +14,8 @@
 FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute instruments assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-PASS PaymentInstruments interface: existence and properties of interface object
-PASS PaymentInstruments interface object length
-PASS PaymentInstruments interface object name
-PASS PaymentInstruments interface: existence and properties of interface prototype object
-PASS PaymentInstruments interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentInstruments interface: existence and properties of interface prototype object's @@unscopables property
-PASS PaymentInstruments interface: operation delete(DOMString)
-PASS PaymentInstruments interface: operation get(DOMString)
-PASS PaymentInstruments interface: operation keys()
-PASS PaymentInstruments interface: operation has(DOMString)
-PASS PaymentInstruments interface: operation set(DOMString, PaymentInstrument)
-PASS PaymentInstruments interface: operation clear()
 PASS CanMakePaymentEvent interface: existence and properties of interface object
 PASS PaymentRequestEvent interface: existence and properties of interface object
 PASS ServiceWorkerRegistration interface: attribute paymentManager
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt
index 2ee5817e..28845dfb 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/idlharness.https.any.worker-expected.txt
@@ -14,21 +14,8 @@
 FAIL PaymentManager interface: existence and properties of interface prototype object assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-FAIL PaymentManager interface: attribute instruments assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: attribute userHint assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
 FAIL PaymentManager interface: operation enableDelegations(sequence<PaymentDelegation>) assert_own_property: self does not have own property "PaymentManager" expected property "PaymentManager" missing
-PASS PaymentInstruments interface: existence and properties of interface object
-PASS PaymentInstruments interface object length
-PASS PaymentInstruments interface object name
-PASS PaymentInstruments interface: existence and properties of interface prototype object
-PASS PaymentInstruments interface: existence and properties of interface prototype object's "constructor" property
-PASS PaymentInstruments interface: existence and properties of interface prototype object's @@unscopables property
-PASS PaymentInstruments interface: operation delete(DOMString)
-PASS PaymentInstruments interface: operation get(DOMString)
-PASS PaymentInstruments interface: operation keys()
-PASS PaymentInstruments interface: operation has(DOMString)
-PASS PaymentInstruments interface: operation set(DOMString, PaymentInstrument)
-PASS PaymentInstruments interface: operation clear()
 PASS CanMakePaymentEvent interface: existence and properties of interface object
 PASS PaymentRequestEvent interface: existence and properties of interface object
 PASS ServiceWorkerRegistration interface: attribute paymentManager
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https-expected.txt b/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https-expected.txt
deleted file mode 100644
index 5ece796..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https-expected.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-This is a testharness.js-based test.
-FAIL Instrument keys are returned in the original insertion order promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Deleting an existing instrument returns true promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Deleting an existing instrument the second time returns false promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-PASS Deleting a non-existing instrument returns false
-FAIL Getting an existing instrument returns the instrument promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-PASS Getting a non-existing instrument returns undefined
-FAIL Resetting an existing instrument updates the instrument promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Clearing the instruments promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Cannot register instruments with invalid icon media type image/jif promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Don't crash when registering instruments with very long icon media type image/pngggggg... promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Don't crash when registering an instrument with a very long icon size 888...x888... promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Don't crash when 'sizes' missing from icon definition promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Don't crash when 'type' missing from icon definition promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Cannot register instruments with invalid icon size "256 256" (missing "x") promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Cannot register instruments with invalid icon URL (has a null character) promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Cannot register instruments with non-existing non-https icon URL promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Cannot register instruments with an existing non-https icon URL promise_rejects_js: function "function() { throw e }" threw object "NotAllowedError: Not allowed to install this payment handler" ("NotAllowedError") expected instance of function "function TypeError() { [native code] }" ("TypeError")
-FAIL Don't crash on very long key, name, method, and capability strings. promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-FAIL Don't crash on null characters in key, name, method, and capability strings. promise_test: Unhandled rejection with value: object "NotAllowedError: Not allowed to install this payment handler"
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html b/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html
deleted file mode 100644
index 121c1315..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html
+++ /dev/null
@@ -1,379 +0,0 @@
-<!doctype html>
-<meta charset="utf-8">
-<title>Tests for PaymentInstruments interface</title>
-<link rel="help" href="https://w3c.github.io/payment-handler/#paymentinstruments-interface">
-<link rel="manifest" href="manifest.json">
-<script src="/resources/testharness.js"></script>
-<script src="/resources/testharnessreport.js"></script>
-<script src="register-and-activate-service-worker.js"></script>
-<script>
-function runTests(registration) {
-  const methodName = window.location.origin + '/payment-handler/payment-app/';
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set('instrument-key-1', {
-      name: 'Instrument Name 1',
-    });
-    await registration.paymentManager.instruments.set('instrument-key-2', {
-      name: 'Instrument Name 2',
-    });
-    await registration.paymentManager.instruments.delete('instrument-key-1');
-    await registration.paymentManager.instruments.set('instrument-key-1', {
-      name: 'Instrument Name 1',
-    });
-    const keys = await registration.paymentManager.instruments.keys();
-    assert_array_equals(keys, ['instrument-key-2', 'instrument-key-1']);
-  }, 'Instrument keys are returned in the original insertion order');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name',
-      },
-    );
-    const result = await registration.paymentManager.instruments.delete(
-      'existing-instrument-key',
-    );
-    assert_true(result);
-  }, 'Deleting an existing instrument returns true');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name',
-      },
-    );
-    await registration.paymentManager.instruments.delete(
-      'existing-instrument-key',
-    );
-    const result = await registration.paymentManager.instruments.delete(
-      'existing-instrument-key',
-    );
-    assert_false(result);
-  }, 'Deleting an existing instrument the second time returns false');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const result = await registration.paymentManager.instruments.delete(
-      'non-existing-instrument-key',
-    );
-    assert_false(result);
-  }, 'Deleting a non-existing instrument returns false');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    const result = await registration.paymentManager.instruments.get(
-      'existing-instrument-key',
-    );
-    assert_equals(result.name, 'Instrument Name');
-  }, 'Getting an existing instrument returns the instrument');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const result = await registration.paymentManager.instruments.get(
-      'non-existing-instrument-key',
-    );
-    assert_equals(result, undefined);
-  }, 'Getting a non-existing instrument returns undefined');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name v1',
-        icons: [
-          {src: '/images/green-16x16.png', sizes: '16x16', type: 'image/png'},
-        ],
-        method: methodName,
-      },
-    );
-    let result = await registration.paymentManager.instruments.get(
-      'existing-instrument-key',
-    );
-    assert_equals(result.name, 'Instrument Name v1');
-    assert_equals(result.icons.length, 1);
-    assert_equals(
-      result.icons[0].src,
-      new URL('/images/green-16x16.png', window.location.href).href,
-    );
-    assert_equals(result.icons[0].sizes, '16x16');
-    assert_equals(result.icons[0].type, 'image/png');
-    assert_equals(result.method, methodName);
-    assert_array_equals(result.capabilities.supportedNetworks, ['mir']);
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name v2',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    result = await registration.paymentManager.instruments.get(
-      'existing-instrument-key',
-    );
-    assert_equals(result.name, 'Instrument Name v2');
-    assert_equals(result.icons.length, 1);
-    assert_equals(
-      result.icons[0].src,
-      new URL('/images/rgrg-256x256.png', window.location.href).href,
-    );
-    assert_equals(result.icons[0].sizes, '256x256');
-    assert_equals(result.icons[0].type, 'image/png');
-    assert_equals(result.method, methodName);
-  }, 'Resetting an existing instrument updates the instrument');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(
-      'existing-instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    await registration.paymentManager.instruments.clear();
-    const result = await registration.paymentManager.instruments.get(
-      'existing-instrument-key',
-    );
-    assert_equals(result, undefined);
-  }, 'Clearing the instruments');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/jif',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, 'Cannot register instruments with invalid icon media type image/jif');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/pn' + 'g'.repeat(100000),
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, "Don't crash when registering instruments with very long icon media type image/pngggggg...");
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    return registration.paymentManager.instruments.set('instrument-key', {
-      name: 'Instrument Name',
-      icons: [
-        {
-          src: '/images/rgrg-256x256.png',
-          sizes: '8'.repeat(100000) + 'x' + '8'.repeat(100000),
-          type: 'image/png',
-        },
-      ],
-      method: methodName,
-    });
-  }, "Don't crash when registering an instrument with a very long icon size 888...x888...");
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    return registration.paymentManager.instruments.set('instrument-key', {
-      name: 'Instrument Name',
-      icons: [
-        {
-          src: '/images/rgrg-256x256.png',
-          type: 'image/png',
-        },
-      ],
-      method: methodName,
-    });
-  }, "Don't crash when 'sizes' missing from icon definition");
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    return registration.paymentManager.instruments.set('instrument-key', {
-      name: 'Instrument Name',
-      icons: [
-        {
-          src: '/images/rgrg-256x256.png',
-          sizes: '256x256',
-        },
-      ],
-      method: methodName,
-    });
-  }, "Don't crash when 'type' missing from icon definition");
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rgrg-256x256.png',
-            sizes: '256 256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, 'Cannot register instruments with invalid icon size "256 256" (missing "x")');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: '/images/rg\0rg-256x256.png',
-            sizes: '256x256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, 'Cannot register instruments with invalid icon URL (has a null character)');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src: 'http://test.example/images/rgrg-256x256.png',
-            sizes: '256x256',
-            type: 'image/png',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, 'Cannot register instruments with non-existing non-https icon URL');
-
-  promise_test(async t => {
-    await registration.paymentManager.instruments.clear();
-    const setPromise = registration.paymentManager.instruments.set(
-      'instrument-key',
-      {
-        name: 'Instrument Name',
-        icons: [
-          {
-            src:
-              'http://www.chromium.org/_/rsrc/1438879449147/config/customLogo.gif',
-            sizes: '48x48',
-            type: 'image/gif',
-          },
-        ],
-        method: methodName,
-      },
-    );
-    return promise_rejects_js(t, TypeError, setPromise);
-  }, 'Cannot register instruments with an existing non-https icon URL');
-
-  async function testUnusualStrings(existingKey, nonExistingKey) {
-    await registration.paymentManager.instruments.clear();
-    await registration.paymentManager.instruments.set(existingKey, {
-      name: existingKey,
-      icons: [
-        {src: '/images/rgrg-256x256.png', sizes: '256x256', type: 'image/png'},
-      ],
-      method: existingKey,
-      capabilities: {aCapabilityName: existingKey},
-    });
-    const hasExistingInstrument = await registration.paymentManager.instruments.has(
-      existingKey,
-    );
-    assert_true(hasExistingInstrument);
-    const hasNonExistingInstrument = await registration.paymentManager.instruments.has(
-      nonExistingKey,
-    );
-    assert_false(hasNonExistingInstrument);
-    const existingInstrument = await registration.paymentManager.instruments.get(
-      existingKey,
-    );
-    assert_equals(existingInstrument.name, existingKey);
-    const nonExistingInstrument = await registration.paymentManager.instruments.get(
-      nonExistingKey,
-    );
-    assert_equals(nonExistingInstrument, undefined);
-    const deletedExistingInstrument = await registration.paymentManager.instruments.delete(
-      existingKey,
-    );
-    assert_true(deletedExistingInstrument);
-    const deletedNonExistingInstrument = await registration.paymentManager.instruments.delete(
-      nonExistingKey,
-    );
-    assert_false(deletedNonExistingInstrument);
-  }
-
-  promise_test(async t => {
-    const length = 100000;
-    await testUnusualStrings('0'.repeat(length), '1'.repeat(length));
-  }, "Don't crash on very long key, name, method, and capability strings.");
-
-  promise_test(async t => {
-    await testUnusualStrings('foo\0bar', 'foo\0baz');
-  }, "Don't crash on null characters in key, name, method, and capability strings.");
-}
-
-registerAndActiveServiceWorker('app-simple.js', 'payment-app/', runTests);
-</script>
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html.ini b/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html.ini
deleted file mode 100644
index d3aff8e..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/payment-instruments.https.html.ini
+++ /dev/null
@@ -1,51 +0,0 @@
-[payment-instruments.https.html]
-  [Resetting an existing instrument updates the instrument]
-    expected: FAIL
-
-  [Clearing the instruments]
-    expected: FAIL
-
-  [Don't crash when registering instruments with very long icon media type image/pngggggg...]
-    expected: FAIL
-
-  [Cannot register instruments with an existing non-https icon URL]
-    expected: FAIL
-
-  [Deleting an existing instrument returns true]
-    expected: FAIL
-
-  [Don't crash on very long key, name, method, and capability strings.]
-    expected: FAIL
-
-  [Don't crash on null characters in key, name, method, and capability strings.]
-    expected: FAIL
-
-  [Don't crash when registering an instrument with a very long icon size 888...x888...]
-    expected: FAIL
-
-  [Cannot register instruments with invalid icon media type image/jif]
-    expected: FAIL
-
-  [Instrument keys are returned in the original insertion order]
-    expected: FAIL
-
-  [Cannot register instruments with invalid icon URL (has a null character)]
-    expected: FAIL
-
-  [Deleting an existing instrument the second time returns false]
-    expected: FAIL
-
-  [Cannot register instruments with non-existing non-https icon URL]
-    expected: FAIL
-
-  [Getting an existing instrument returns the instrument]
-    expected: FAIL
-
-  [Cannot register instruments with invalid icon size "256 256" (missing "x")]
-    expected: FAIL
-
-  [Don't crash when 'type' missing from icon definition]
-    expected: FAIL
-
-  [Don't crash when 'sizes' missing from icon definition]
-    expected: FAIL
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/register-and-activate-service-worker.js b/third_party/blink/web_tests/external/wpt/payment-handler/register-and-activate-service-worker.js
deleted file mode 100644
index fb54c5c..0000000
--- a/third_party/blink/web_tests/external/wpt/payment-handler/register-and-activate-service-worker.js
+++ /dev/null
@@ -1,28 +0,0 @@
-async function registerAndActiveServiceWorker(script, scope, callback) {
-  const registration = await navigator.serviceWorker.register(script, {scope});
-  const serviceWorker =
-    registration.installing || registration.waiting || registration.active;
-  if (serviceWorker) {
-    waitForServiceWorkerActivation(scope, callback);
-    return;
-  }
-
-  registration.addEventListener('updatefound', event => {
-    waitForServiceWorkerActivation(scope, callback);
-  });
-}
-
-async function waitForServiceWorkerActivation(scope, callback) {
-  const registration = await navigator.serviceWorker.getRegistration(scope);
-  if (registration.active) {
-    callback(registration);
-    return;
-  }
-
-  const serviceWorker = registration.installing || registration.waiting;
-  serviceWorker.addEventListener('statechange', event => {
-    if (event.target.state == 'activated') {
-      callback(registration);
-    }
-  });
-}
diff --git a/third_party/blink/web_tests/external/wpt/payment-handler/same-object-attributes.https.html b/third_party/blink/web_tests/external/wpt/payment-handler/same-object-attributes.https.html
index 2e5dea3a..27c2044 100644
--- a/third_party/blink/web_tests/external/wpt/payment-handler/same-object-attributes.https.html
+++ b/third_party/blink/web_tests/external/wpt/payment-handler/same-object-attributes.https.html
@@ -13,7 +13,6 @@
   await wait_for_state(t, registration.installing, 'activated');
 
   assert_equals(registration.paymentManager, registration.paymentManager);
-  assert_equals(registration.paymentManager.instruments, registration.paymentManager.instruments);
 });
 
 </script>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/cross-origin-start-end-time-with-redirects.html b/third_party/blink/web_tests/external/wpt/resource-timing/cross-origin-start-end-time-with-redirects.html
index 1b107d3a..8e368d13 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/cross-origin-start-end-time-with-redirects.html
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/cross-origin-start-end-time-with-redirects.html
@@ -19,13 +19,19 @@
 const blank_page = `/resource-timing/resources/blank_page_green.htm`;
 const destUrl = `/common/slow-redirect.py?delay=${delay}&location=${REMOTE_ORIGIN}/${blank_page}`;
 
-const timeBefore = performance.now()
-attribute_test(load.iframe, destUrl, entry => {
-    assert_equals(entry.startTime, entry.fetchStart, 'startTime and fetchStart should be equal');
-    assert_greater_than(entry.startTime, timeBefore, 'startTime and fetchStart should be greater than the time before fetching');
-    // See https://github.com/w3c/resource-timing/issues/264
-    assert_less_than(Math.round(entry.startTime - timeBefore), delay * 1000, 'startTime should not expose redirect delays');
-}, "Verify that cross-origin resources don't implicitly expose their redirect timings")
+const timeBefore = performance.now();
+(async () => {
+  // Wait 10 ms, to ensure the difference between startTime and timeBefore is
+  // larger than 1 ms, to avoid flakiness in browsers that clamp timestamps to
+  // 1 ms.
+  await new Promise(r => step_timeout(r, 10));
+  attribute_test(load.iframe, destUrl, entry => {
+      assert_equals(entry.startTime, entry.fetchStart, 'startTime and fetchStart should be equal');
+      assert_greater_than(entry.startTime, timeBefore, 'startTime and fetchStart should be greater than the time before fetching');
+      // See https://github.com/w3c/resource-timing/issues/264
+      assert_less_than(Math.round(entry.startTime - timeBefore), delay * 1000, 'startTime should not expose redirect delays');
+  }, "Verify that cross-origin resources don't implicitly expose their redirect timings")
+})();
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html b/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html
index 4d5d121..6990c6c 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/object-not-found-after-cross-origin-redirect.html
@@ -23,13 +23,19 @@
 }
 const destUrl = `/common/slow-redirect.py?delay=${delay}&location=${REMOTE_ORIGIN}${not_found_page}`;
 
-const timeBefore = performance.now()
-attribute_test(load_null_object, destUrl, entry => {
-    assert_equals(entry.startTime, entry.fetchStart, 'startTime and fetchStart should be equal');
-    assert_greater_than(entry.startTime, timeBefore, 'startTime and fetchStart should be greater than the time before fetching');
-    // See https://github.com/w3c/resource-timing/issues/264
-    assert_less_than(Math.round(entry.startTime - timeBefore), delay * 1000, 'startTime should not expose redirect delays');
-}, "Verify that cross-origin object resources don't implicitly expose their redirect timings")
+const timeBefore = performance.now();
+(async () => {
+  // Wait 10 ms, to ensure the difference between startTime and timeBefore is
+  // larger than 1 ms, to avoid flakiness in browsers that clamp timestamps to
+  // 1 ms.
+  await new Promise(r => step_timeout(r, 10));
+  attribute_test(load_null_object, destUrl, entry => {
+      assert_equals(entry.startTime, entry.fetchStart, 'startTime and fetchStart should be equal');
+      assert_greater_than(entry.startTime, timeBefore, 'startTime and fetchStart should be greater than the time before fetching');
+      // See https://github.com/w3c/resource-timing/issues/264
+      assert_less_than(Math.round(entry.startTime - timeBefore), delay * 1000, 'startTime should not expose redirect delays');
+  }, "Verify that cross-origin object resources don't implicitly expose their redirect timings")
+})();
 
 </script>
 </body>
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/entry-invariants.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/entry-invariants.js
index dc907533..bbc913b7 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/entry-invariants.js
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/entry-invariants.js
@@ -1,3 +1,19 @@
+const await_with_timeout = async (delay, message, promise, cleanup = ()=>{}) => {
+  let timeout_id;
+  const timeout = new Promise((_, reject) => {
+    timeout_id = step_timeout(() =>
+      reject(new DOMException(message, "TimeoutError")), delay)
+  });
+  let result = null;
+  try {
+    result = await Promise.race([promise, timeout]);
+    clearTimeout(timeout_id);
+  } finally {
+    cleanup();
+  }
+  return result;
+};
+
 // Asserts that the given attributes are present in 'entry' and hold equal
 // values.
 const assert_all_equal_ = (entry, attributes) => {
@@ -451,12 +467,10 @@
       });
 
       await loader(path, validator);
-      const timeout = new Promise(r => step_timeout(() => {
-        console.log("Timeout was reached before entry fired");
-        r(null);
-      }, 2000));
-      const entry = await Promise.race([loaded_entry, timeout]);
-      assert_not_equals(entry, null, 'No entry was recieved');
+      const entry = await await_with_timeout(2000,
+        "Timeout was reached before entry fired",
+        loaded_entry);
+      assert_not_equals(entry, null, 'No entry was received');
       run_test(entry);
   }, test_label);
 };
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/resources/resource-loaders.js b/third_party/blink/web_tests/external/wpt/resource-timing/resources/resource-loaders.js
index 70889b70..37fea16 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/resources/resource-loaders.js
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/resources/resource-loaders.js
@@ -135,7 +135,7 @@
   // object.
   object: async (path, type) => {
     const object = document.createElement("object");
-    const loaded = new Promise(resolve => {
+    const object_load_settled = new Promise(resolve => {
       object.onload = object.onerror = resolve;
     });
     object.data = load.cache_bust(path);
@@ -143,12 +143,11 @@
       object.type = type;
     }
     document.body.appendChild(object);
-    const timeout = new Promise(r => step_timeout(() => {
-      console.log("Timeout was reached before load or error events fired");
-      r();
-    }, 2000));
-    await Promise.race([loaded, timeout]);
-    document.body.removeChild(object);
+    await await_with_timeout(2000,
+      "Timeout was reached before load or error events fired",
+      object_load_settled,
+      () => { document.body.removeChild(object) }
+    );
   },
 
   // Returns a promise that settles once the given path has been fetched
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html b/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html
index 3c606c5..3a184c6 100644
--- a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html
+++ b/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html
@@ -24,6 +24,10 @@
   return load.object(path, "image/png");
 }
 
+const load_frame_object = async path => {
+  return load.object(path, "text/html");
+}
+
 const load_null_object = async path => {
   return load.object(path, null);
 }
@@ -38,6 +42,7 @@
   load.xhr_async,
   load.iframe,
   load_image_object,
+  load_frame_object,
   load_null_object
 ]) {
   for(const status of status_codes) {
@@ -88,6 +93,7 @@
   load.stylesheet,
   load.iframe,
   load_image_object,
+  load_frame_object,
   load_null_object
 ]) {
   for(const tao of [false, true]) {
@@ -113,6 +119,7 @@
 // Same-Origin => Cross-Origin => Same-Origin => Same-Origin redirect chain
 for(const loader of [
   load.iframe,
+  load_frame_object,
   load_null_object
 ]) {
   for(const status of status_codes) {
@@ -136,6 +143,7 @@
 // Response status for iframes is exposed for same origin redirects
 for(const loader of [
   load.iframe,
+  load_frame_object,
   load_null_object
 ]) {
   for(const status of status_codes) {
diff --git a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini b/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini
deleted file mode 100644
index cd9aff10..0000000
--- a/third_party/blink/web_tests/external/wpt/resource-timing/response-status-code.html.ini
+++ /dev/null
@@ -1,596 +0,0 @@
-[response-status-code.html]
-  [This test validates the response status of resources. 271]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 268]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 267]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 270]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 269]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 125]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 243]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 130]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 116]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 266]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 126]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 215]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 138]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 220]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 221]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 180]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 110]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 173]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 112]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 213]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 262]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 111]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 192]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 174]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 230]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 93]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 197]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 201]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 103]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 109]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 210]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 95]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 133]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 200]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 228]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 158]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 190]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 240]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 118]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 260]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 227]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 177]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 143]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 127]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 147]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 203]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 171]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 114]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 225]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 209]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 255]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 263]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 251]
-    expected: [PASS, TIMEOUT, NOTRUN]
-
-  [This test validates the response status of resources. 164]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 239]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 235]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 155]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 119]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 222]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 123]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 176]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 199]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 256]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 156]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 163]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 207]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 193]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 132]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 144]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 257]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 181]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 245]
-    expected:
-      if product == "chrome": [PASS, FAIL, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 205]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 142]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 151]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 159]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 102]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 107]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 149]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 172]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 113]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 194]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 234]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 170]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 161]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 217]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 219]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 91]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 154]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 140]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 175]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 129]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 231]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 248]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 153]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 224]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 106]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 90]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 162]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 128]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 168]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 157]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 99]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 120]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 165]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 136]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 250]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 92]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 122]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 184]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 115]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 145]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 202]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 204]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 206]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 104]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 146]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 241]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 216]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 212]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 198]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 117]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 94]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 101]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 264]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 185]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 211]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 226]
-    expected: [PASS, TIMEOUT, NOTRUN]
-
-  [This test validates the response status of resources. 135]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 141]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 87]
-    expected: [PASS, TIMEOUT]
-
-  [This test validates the response status of resources. 137]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 189]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 253]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 233]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 214]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 261]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 196]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 237]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 124]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 105]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 178]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 258]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 131]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 134]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 166]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 186]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 97]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 100]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 179]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 182]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 139]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 183]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 167]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 195]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 265]
-    expected:
-      if product == "chrome": [PASS, NOTRUN]
-      NOTRUN
-
-  [This test validates the response status of resources. 108]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 208]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 238]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 148]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 98]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 160]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 187]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 188]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 223]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 232]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 236]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 152]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 229]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 218]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 150]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 121]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 169]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 96]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 191]
-    expected: [PASS, NOTRUN]
-
-  [This test validates the response status of resources. 275]
-    expected:
-      if product == "chrome": [PASS, FAIL]
-
-  [This test validates the response status of resources. 273]
-    expected:
-      if product == "chrome": [PASS, FAIL]
-
-  [This test validates the response status of resources. 276]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 277]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 298]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 272]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 246]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 293]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 278]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 274]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 296]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 292]
-    expected: [PASS, FAIL]
-
-  [This test validates the response status of resources. 83]
-    expected: [PASS, FAIL]
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue-expected.txt
deleted file mode 100644
index f0bc065..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue-expected.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Tests that deprecation issues are reported for paymentManager.instruments
-Inspector issue: {
-    issue : {
-        code : DeprecationIssue
-        details : {
-            deprecationIssueDetails : {
-                affectedFrame : {
-                    frameId : <string>
-                }
-                sourceCodeLocation : {
-                    columnNumber : 35
-                    lineNumber : 2
-                    scriptId : <string>
-                    url : 
-                }
-                type : PaymentInstruments
-            }
-        }
-    }
-}
-
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue.js b/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue.js
deleted file mode 100644
index 1339c67b..0000000
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/issues/payment-instruments-issue.js
+++ /dev/null
@@ -1,18 +0,0 @@
-(async function (testRunner) {
-  const {session, dp} = await testRunner.startBlank(
-    'Tests that deprecation issues are reported for ' +
-    'paymentManager.instruments');
-  await dp.Audits.enable();
-  const promise = dp.Audits.onceIssueAdded();
-  const dir = '/inspector-protocol/resources';
-
-  // Access the deprecated PaymentInstruments field:
-  session.evaluate(`navigator.serviceWorker.register("${dir}/blank.js")
-    .then((registration) => {
-      registration.paymentManager.instruments.clear();
-    })`);
-
-  const result = await promise;
-  testRunner.log(result.params, "Inspector issue: ");
-  testRunner.completeTest();
-})
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack-expected.txt
index edd201a..34e5f6a 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack-expected.txt
@@ -1,27 +1,25 @@
 Tests that tracking and untracking IndexedDB for storage key works
 
 Open database, object store and set value
-[
-    [0] : {
-        method : Storage.indexedDBListUpdated
-        params : {
-            origin : http://127.0.0.1:8000
-            storageKey : http://127.0.0.1:8000/
-        }
-        sessionId : <string>
+{
+    method : Storage.indexedDBListUpdated
+    params : {
+        origin : http://127.0.0.1:8000
+        storageKey : http://127.0.0.1:8000/
     }
-    [1] : {
-        method : Storage.indexedDBContentUpdated
-        params : {
-            databaseName : test-database
-            objectStoreName : test-store
-            origin : http://127.0.0.1:8000
-            storageKey : http://127.0.0.1:8000/
-        }
-        sessionId : <string>
+    sessionId : <string>
+}
+Title{
+    method : Storage.indexedDBContentUpdated
+    params : {
+        databaseName : <string>
+        objectStoreName : test-store
+        origin : http://127.0.0.1:8000
+        storageKey : http://127.0.0.1:8000/
     }
-    [2] : key-value pair added successfully
-]
+    sessionId : <string>
+}
+key-value pair added successfully
 
 Untrack IndexedDB for storage key
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack.js b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack.js
index e883923..0189138 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/indexed-db-storage-key-track-untrack.js
@@ -1,7 +1,6 @@
 (async function(testRunner) {
   const {dp, session} = await testRunner.startBlank(
       `Tests that tracking and untracking IndexedDB for storage key works\n`);
-
   await dp.Page.enable();
   const protocolMessages = [];
   const originalDispatchMessage = DevToolsAPI.dispatchMessage;
@@ -19,8 +18,8 @@
   let errorForLog = new Error();
   setTimeout(() => {
     testRunner.log(protocolMessages);
-    testRunner.die('Timeout', errorForLog);
-  }, 5000);
+    testRunner.die('Took longer than 25s', errorForLog);
+  }, 25000);
 
   const frameId = (await dp.Page.getResourceTree()).result.frameTree.frame.id;
   errorForLog = new Error();
@@ -37,11 +36,12 @@
       message => {return `indexedDB content updated for ${message.params}`});
 
   testRunner.log(`Open database, object store and set value`);
+  const id = Math.random();
 
   // Create database, objectStore and add a key-value pair.
   const valuePromise = session.evaluateAsync(`
     new Promise(async resolve => {
-      const request = window.indexedDB.open("test-database");
+      const request = window.indexedDB.open("test-database${id}");
       request.onerror = (event) => {
         resolve('failed to create a database');
       };
@@ -54,8 +54,11 @@
     })
   `);
 
-  testRunner.log(await Promise.all(
-      [listUpdatedPromise, contentUpdatedPromise, valuePromise]));
+  const [listUpdatedEvent, contentUpdatedEvent, value] = await Promise.all(
+    [listUpdatedPromise, contentUpdatedPromise, valuePromise]);
+  testRunner.log(listUpdatedEvent);
+  testRunner.log(contentUpdatedEvent, "Title", ['databaseName', 'sessionId']);
+  testRunner.log(value);
   errorForLog = new Error();
 
   testRunner.log('\nUntrack IndexedDB for storage key');
@@ -70,7 +73,7 @@
   // Open database, objectStore and add another value.
   const oneMoreValue = await session.evaluateAsync(`
     new Promise(async resolve => {
-      const openreq = window.indexedDB.open("test-database");
+      const openreq = window.indexedDB.open("test-database${id}");
       openreq.onerror = (event) => {
         resolve("not able to open database");
       }
@@ -86,9 +89,19 @@
 
   testRunner.log(oneMoreValue);
 
-  // Clean up
-  await dp.IndexedDB.deleteDatabase({storageKey, databaseName: "test-database"});
-  errorForLog = new Error();
+    // Clean up
+  try {
+    await session.evaluateAsync(`
+      new Promise(async (resolve, reject) => {
+        const req = window.indexedDB.deleteDatabase("test-database${id}");
+        req.onsuccess = resolve;
+        req.onerror = reject;
+      });
+    `);
+  } catch (e) {
+    testRunner.log(e);
+  } finally {
+    testRunner.completeTest();
+  }
 
-  testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js
index 657bcf03..027a5674 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/storage/interest-groups.js
@@ -49,15 +49,18 @@
     events = [];
   }
 
-  let resolveWaitForWinPromise;
-  const waitForWinPromise = new Promise((resolve, reject)=>{
-    resolveWaitForWinPromise = resolve;
+  let observedBids = 0;
+  let resolveWaitForTwoBidsPromise;
+  const waitForTwoBidsPromise = new Promise((resolve, reject)=>{
+    resolveWaitForTwoBidsPromise = resolve;
   });
 
   dp.Storage.onInterestGroupAccessed((messageObject)=>{
     events.push(messageObject.params);
-    if (messageObject.params.type == 'win') {
-      resolveWaitForWinPromise();
+    if (messageObject.params.type == 'bid') {
+      ++observedBids;
+      if (observedBids == 2)
+        resolveWaitForTwoBidsPromise();
     }
   });
   await page.navigate(base + 'empty.html');
@@ -70,12 +73,12 @@
   // Need to navigate a fenced frame to the winning ad for the bids to be
   // recorded.
   await runAdAuctionAndNavigateFencedFrame();
-  // Have to wait for the win to be received, which happens after commit
-  // (which also can't be waited for). Only do this if FLEDGE is enabled
-  // and has sent events already, to avoid waiting for events that will
-  // never occur.
+  // Have to wait for the bids to be received, since there's no way to wait
+  // for the fenced frame navigation to complete directly. Only do this if
+  // FLEDGE is enabled and has sent events already, to avoid waiting for events
+  // that will never occur.
   if (events.length > 0)
-    await waitForWinPromise;
+    await waitForTwoBidsPromise;
   await logAndClearEvents();
 
   // Disable interest group logging, and run the same set of events. No new
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
index d4fa687..60ee1d6 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
@@ -2,18 +2,11 @@
 Attached to page target: about:blank
     (title: )
     (waiting: false)
-Detached: about:blank
+Dettached: about:blank
 Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
     (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
     (waiting: false)
 Auction winner:undefined
-Attached to page target: about:blank
-    (title: )
-    (waiting: false)
-Detached: about:blank
-Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
-    (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
-    (waiting: false)
 Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
     (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
     (waiting: false)
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js
index 8f159760..d17e2a6 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/auto-attach-auction-worklet.js
@@ -18,11 +18,6 @@
     return input;
   }
 
-  let detachedBidderWorklets = 0;
-  let resolveWaitForSecondBidderWorkletDetachedPromise;
-  const waitForSecondBidderWorkletDetachedPromise = new Promise((resolve, reject)=>{
-    resolveWaitForSecondBidderWorkletDetachedPromise = resolve;
-  });
   bp.Target.onAttachedToTarget(event => {
     const params = event.params;
     testRunner.log(
@@ -33,13 +28,7 @@
   });
 
   bp.Target.onDetachedFromTarget(event => {
-    let url = urlForSession.get(event.params.sessionId);
-    testRunner.log('Detached: ' + url);
-    if (url.endsWith("fledge_bidding_logic.js.php")) {
-      ++detachedBidderWorklets;
-      if (detachedBidderWorklets == 2)
-        resolveWaitForSecondBidderWorkletDetachedPromise();
-    }
+    testRunner.log('Dettached: ' + urlForSession.get(event.params.sessionId));
   });
 
   const base = 'https://a.test:8443/inspector-protocol/resources/'
@@ -57,18 +46,11 @@
   const winner1 = await page1_session.evaluateAsync(auctionJs);
   testRunner.log('Auction winner:' + handleUrn(winner1));
 
-  // Ask to auto-attach related before re-running the auction. Use another page to
-  // avoid reporting events that happen after the auction completes.
-  const page2 = await testRunner.createPage({url: base + 'fledge_join.html'});
-  const page2_session = await page2.createSession();
+  // Ask to auto-attach related before re-running the auction.
   await bp.Target.autoAttachRelated(
-      {targetId: page2.targetId(), waitForDebuggerOnStart: false});
+      {targetId: page1.targetId(), waitForDebuggerOnStart: false});
 
-  const winner2 = await page2_session.evaluateAsync(auctionJs);
-  // If FLEDGE is enabled, need to wait for post-auction scripts to run, to
-  // ensure a consistent number of FLEDGE scripts have been invoked.
-  if (detachedBidderWorklets > 0)
-    await waitForSecondBidderWorkletDetachedPromise;
+  const winner2 = await page1_session.evaluateAsync(auctionJs);
   testRunner.log('Auction winner:' + handleUrn(winner2));
   testRunner.log('DONE');
   testRunner.completeTest();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js
index 7f17618..ac9b726 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/target/target-auction-worklet.js
@@ -11,12 +11,6 @@
     return input;
   }
 
-  let attachedWorklets = 0;
-  let resolveWaitForThirdWorkletPromise;
-  const waitForThirdWorkletPromise = new Promise((resolve, reject)=>{
-    resolveWaitForThirdWorkletPromise = resolve;
-  });
-
   bp.Target.onAttachedToTarget(async event => {
     const params = event.params;
     testRunner.log(`Attached to target ${params.targetInfo.url}`);
@@ -24,9 +18,6 @@
       const targetSession =
           new TestRunner.Session(testRunner, event.params.sessionId);
       if (params.targetInfo.type === 'auction_worklet') {
-        ++attachedWorklets;
-        if (attachedWorklets == 3)
-          resolveWaitForThirdWorkletPromise();
         testRunner.log('  Bidder instrumentation breakpoint set attempted');
         targetSession.protocol.Debugger.enable();
         targetSession.protocol.Runtime.enable();
@@ -62,16 +53,6 @@
       {targetId: page.targetId(), waitForDebuggerOnStart: true});
 
   const winner = await session.evaluateAsync(auctionJs);
-
-  // Have to wait for the third worklet to be attached (first the seller
-  // is attached, then the bidder is attached to bid, and then the
-  // bidder worklet is reloaded to call reportWin()), as reportWin()
-  // is invoked racily with reporting auction completion. Only do this
-  // if FLEDGE is enabled and has sent events already, to avoid waiting
-  // for events that will never occur.
-  if (attachedWorklets > 0)
-    await waitForThirdWorkletPromise;
-
   testRunner.log('Auction winner:' + handleUrn(winner));
   testRunner.log('DONE');
   testRunner.completeTest();
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
index 913ef94..ad9475b 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -7,4 +7,5 @@
 Saw process assignment for bidder for host:nope
 Saw process assignment for seller for host:nope
 Saw process release for bidder for host:nope
+Saw process release for seller for host:nope
 
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js
index a725f13..bcfc14c3 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet-network.js
@@ -61,7 +61,7 @@
     }
   }
 
-  let sortedRequestInfo = [...requestIdToInfo.values()].sort((a, b) => {
+  const sortedRequestInfo = [...requestIdToInfo.values()].sort((a, b) => {
     if (a.url < b.url)
       return -1;
     else if (a.url === b.url)
@@ -69,15 +69,6 @@
     return +1;
   });
 
-  // There may racily be two bidding logic loads, depending on how far along running reportings scripts
-  // has advanced, which is done after auction completion is signalled. If there are two such loads,
-  // ignore the second one.
-  if (sortedRequestInfo.length > 2 &&
-      sortedRequestInfo[0].endsWith("fledge_bidding_logic.js.php") &&
-      sortedRequestInfo[1].endsWith("fledge_bidding_logic.js.php")) {
-    sortedRequestInfo = sortedRequestInfo.splice(1);
-  }
-
   for (let requestInfo of sortedRequestInfo) {
     testRunner.log(requestInfo.url + ':');
     for (let ev of requestInfo.events) {
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
index 1de8236..717bbebb 100644
--- a/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
+++ b/third_party/blink/web_tests/http/tests/inspector-protocol/timeline/auction-worklet.js
@@ -50,6 +50,7 @@
   let sawBidderRunningInProcess = 'nope';
   let sawSellerRunningInProcess = 'nope';
   let sawBidderDoneWithProcess = 'nope';
+  let sawSellerDoneWithProcess = 'nope';
   for (ev of devtoolsEvents) {
     if (ev.name === 'AuctionWorkletRunningInProcess') {
       let data = ev.args.data;
@@ -64,9 +65,9 @@
       let data = ev.args.data;
       if (data.type === 'bidder') {
         sawBidderDoneWithProcess = data.host;
+      } else if (data.type === 'seller') {
+        sawSellerDoneWithProcess = data.host;
       }
-      // Note that seller unload is not guaranteed to be observed, as it can
-      // happen after auction completion.
       verifyAuctionProcessEventData(data);
     }
     if (ev.name === 'generate_bid')
@@ -94,8 +95,8 @@
       sawSellerRunningInProcess);
   testRunner.log(
       'Saw process release for bidder for host:' + sawBidderDoneWithProcess);
-  // Note that seller unload is not guaranteed to be observed, as it can happen
-  // after auction completion.
+  testRunner.log(
+      'Saw process release for seller for host:' + sawSellerDoneWithProcess);
 
   testRunner.completeTest();
 })
diff --git a/third_party/blink/web_tests/http/tests/payments/payment-instruments-expected.txt b/third_party/blink/web_tests/http/tests/payments/payment-instruments-expected.txt
deleted file mode 100644
index 700c5303..0000000
--- a/third_party/blink/web_tests/http/tests/payments/payment-instruments-expected.txt
+++ /dev/null
@@ -1,17 +0,0 @@
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-CONSOLE WARNING: The page that installed the payment handler does not contain a web app manifest link: <link rel="manifest" href="some-file-name-here">. This manifest defines the payment handler's name and icon. User may not recognize this payment handler in UI, because it will be labeled only by its origin.
-This is a testharness.js-based test.
-FAIL PaymentInstruments set/get methods test with basic-card assert_unreached: unexpected rejection: assert_object_equals: value is undefined, expected object Reached unreachable code
-PASS PaymentInstruments set/get methods test with url method
-PASS PaymentInstruments.get() should throw NotFoundError if no stored key
-PASS PaymentInstruments delete method test
-PASS PaymentInstruments |has| method test
-PASS PaymentInstruments |keys| method test
-PASS PaymentInstruments |clear| method test
-PASS Throw NotAllowedError if permission is not granted
-Harness: the test ran to completion.
-
diff --git a/third_party/blink/web_tests/http/tests/payments/payment-instruments.html b/third_party/blink/web_tests/http/tests/payments/payment-instruments.html
deleted file mode 100644
index f5d98b6..0000000
--- a/third_party/blink/web_tests/http/tests/payments/payment-instruments.html
+++ /dev/null
@@ -1,378 +0,0 @@
-<!doctype html>
-<meta charset="utf-8">
-<title>PaymentHandler: Tests for PaymentInstruments</title>
-<link rel="help" href="https://w3c.github.io/webpayments-payment-apps-api/#payment-instruments">
-<script src="../resources/testharness.js"></script>
-<script src="../resources/testharnessreport.js"></script>
-<script src="../resources/permissions-helper.js"></script>
-<script src="../../serviceworker/resources/test-helpers.js"></script>
-<script>
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          return registration.paymentManager.instruments.set(
-              'test_key',
-              {
-                name: 'Visa ending ****4756',
-                icons: [
-                  {
-                    'src': './resources/icon-1x.png',
-                    'sizes': '32x32 48x48',
-                    'type': 'image/png'
-                  },
-                  {
-                    'src': './resources/icon-2x.png',
-                    'sizes': '96x96',
-                    'type': 'image/png',
-                    'purpose': 'any monochrome'
-                  }
-                ],
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              });
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-          return registration.paymentManager.instruments.get('test_key');
-        })
-      .then(stored_instrument => {
-          assert_equals(stored_instrument.name, 'Visa ending ****4756');
-          assert_equals(stored_instrument.method, 'basic-card');
-          assert_equals(stored_instrument.icons.length, 2);
-          assert_object_equals(stored_instrument.icons[0], {
-              src: location.origin + '/payments/resources/icon-1x.png',
-              sizes: '32x32 48x48',
-              type: 'image/png'
-            });
-          assert_object_equals(stored_instrument.icons[1], {
-              src: location.origin + '/payments/resources/icon-2x.png',
-              sizes: '96x96',
-              type: 'image/png'
-            });
-          assert_object_equals(stored_instrument.capabilities, {
-              supportedNetworks: ['visa'],
-              supportedTypes: ['credit']
-            });
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments set/get methods test with basic-card');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          return registration.paymentManager.instruments.set(
-              'test_key',
-              {
-                name: 'ChromePay',
-                icons: [
-                  {
-                    'src': './resources/icon-1x.png',
-                    'sizes': '32x32 48x48',
-                    'type': 'image/png'
-                  },
-                  {
-                    'src': './resources/icon-2x.png',
-                    'sizes': '96x96',
-                    'type': 'image/png',
-                    'purpose': 'any monochrome'
-                  }
-                ],
-                method: 'https://www.chromium.org/pay'
-              });
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-          return registration.paymentManager.instruments.get('test_key');
-        })
-      .then(stored_instrument => {
-          assert_equals(stored_instrument.name, 'ChromePay');
-          assert_equals(stored_instrument.method, 'https://www.chromium.org/pay');
-          assert_equals(stored_instrument.icons.length, 2);
-          assert_object_equals(stored_instrument.icons[0], {
-              src: location.origin + '/payments/resources/icon-1x.png',
-              sizes: '32x32 48x48',
-              type: 'image/png'
-            });
-          assert_object_equals(stored_instrument.icons[1], {
-              src: location.origin + '/payments/resources/icon-2x.png',
-              sizes: '96x96',
-              type: 'image/png'
-            });
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments set/get methods test with url method');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return registration.paymentManager.instruments.get('test_key');
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments.get() should throw NotFoundError if no stored key');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          return registration.paymentManager.instruments.set(
-              'test_key',
-              {
-                name: 'Visa ending ****4756',
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              });
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-          return registration.paymentManager.instruments.delete('test_key');
-        })
-      .then(result => {
-          assert_equals(result, true);
-          return registration.paymentManager.instruments.delete('test_key');
-        })
-      .then(result => {
-          assert_equals(result, false);
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments delete method test');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          return registration.paymentManager.instruments.set(
-              'test_key',
-              {
-                name: 'Visa ending ****4756',
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              });
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-          return registration.paymentManager.instruments.has('test_key');
-        })
-      .then(result => {
-          assert_equals(result, true);
-          return registration.paymentManager.instruments.has('unstored_test_key');
-        })
-      .then(result => {
-          assert_equals(result, false);
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments |has| method test');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          var instruments = [
-            registration.paymentManager.instruments.set(
-              'test_key1',
-              {
-                name: 'Visa ending ****4756',
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              }),
-            registration.paymentManager.instruments.set(
-              'test_key2',
-              {
-                name: "My Bob Pay Account: john@example.test",
-                method: "https://bobpay.test/"
-              })
-          ];
-          return Promise.all(instruments);
-        })
-      .then(result => {
-          assert_array_equals(result, [undefined, undefined]);
-          return registration.paymentManager.instruments.keys();
-        })
-      .then(result => {
-          assert_array_equals(result, ['test_key1', 'test_key2']);
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments |keys| method test');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'granted');
-        })
-      .then(() => {
-          var instruments = [
-            registration.paymentManager.instruments.set(
-              'test_key1',
-              {
-                name: 'Visa ending ****4756',
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              }),
-            registration.paymentManager.instruments.set(
-              'test_key2',
-              {
-                name: "My Bob Pay Account: john@example.test",
-                method: "https://bobpay.test/"
-              })
-          ];
-          return Promise.all(instruments);
-        })
-      .then(result => {
-          assert_array_equals(result, [undefined, undefined]);
-          return registration.paymentManager.instruments.keys();
-        })
-      .then(result => {
-          assert_equals(result.length, 2);
-          return registration.paymentManager.instruments.clear();
-        })
-      .then(result => {
-          assert_equals(result, undefined);
-          return registration.paymentManager.instruments.keys();
-        })
-      .then(result => {
-          assert_equals(result.length, 0);
-        })
-      .catch(unreached_rejection(test));
-  }, 'PaymentInstruments |clear| method test');
-
-promise_test(test => {
-    var registration;
-    var script_url = 'resources/empty-worker.js';
-    var scope = 'resources/';
-
-    return service_worker_unregister_and_register(test, script_url, scope)
-      .then(r => {
-          registration = r;
-          return wait_for_state(test, registration.installing, 'activated');
-        })
-      .then(state => {
-          assert_equals(state, 'activated');
-          return PermissionsHelper.setPermission('payment-handler', 'denied');
-        })
-      .then(() => {
-          return registration.paymentManager.instruments.set(
-              'test_key',
-              {
-                name: 'Visa ending ****4756',
-                icons: [
-                  {
-                    'src': './resources/icon-1x.png',
-                    'sizes': '32x32 48x48',
-                    'type': 'image/png'
-                  },
-                  {
-                    'src': './resources/icon-2x.png',
-                    'sizes': '96x96',
-                    'type': 'image/png',
-                    'purpose': 'any monochrome'
-                  }
-                ],
-                method: 'basic-card',
-                capabilities: {
-                  supportedNetworks: ['visa'],
-                  supportedTypes: ['credit']
-                }
-              });
-        })
-      .then(result => {
-          assert_unreached();
-        })
-      .catch(e => {
-          assert_equals(e.name, 'NotAllowedError');
-        });
-  }, 'Throw NotAllowedError if permission is not granted');
-
-</script>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 24210d42..9954001 100644
--- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1120,15 +1120,6 @@
     method quadraticCurveTo
     method rect
     method roundRect
-interface PaymentInstruments
-    attribute @@toStringTag
-    method clear
-    method constructor
-    method delete
-    method get
-    method has
-    method keys
-    method set
 interface PaymentRequestEvent : ExtendableEvent
     attribute @@toStringTag
     getter instrumentKey
diff --git a/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt b/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt
index d77492a..3c3cfcb 100644
--- a/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt
+++ b/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/iframe-popup.https_1-2-expected.txt
@@ -1,7 +1,7 @@
 This is a testharness.js-based test.
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with window_open assert_equals: Popup has an opener? expected "true" but got "false"
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with anchor assert_equals: Popup has an opener? expected "true" but got "false"
-FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with form assert_equals: Popup has an opener? expected "true" but got "false"
+PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with window_open
+PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with anchor
+PASS COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same origin iframe, same origin popup with form
 FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with window_open assert_equals: Popup has an opener? expected "true" but got "false"
 FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with anchor assert_equals: Popup has an opener? expected "true" but got "false"
 FAIL COOP: restrict-properties to popup COOP: restrict-properties via an iframe, with same site iframe, same origin popup with form assert_equals: Popup has an opener? expected "true" but got "false"
diff --git a/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt b/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
index d370a09..cf44e70 100644
--- a/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
+++ b/third_party/blink/web_tests/virtual/coop-restrict-properties/external/wpt/html/cross-origin-opener-policy/tentative/restrict-properties/popup-with-same-origin.https-expected.txt
@@ -3,6 +3,6 @@
 FAIL Same-origin popup with coop unsafe-none assert_false: Popup is closed from opener? expected false got true
 PASS Same-origin popup with coop same-origin
 PASS Same-origin popup with coop same-origin-allow-popups
-FAIL Same-origin popup with coop restrict-properties assert_false: Popup is closed from opener? expected false got true
+PASS Same-origin popup with coop restrict-properties
 Harness: the test ran to completion.
 
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
index a34d5f858..4ae5935 100644
--- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
+++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/target/auto-attach-auction-worklet-expected.txt
@@ -2,18 +2,11 @@
 Attached to page target: about:blank
     (title: )
     (waiting: false)
-Detached: about:blank
+Dettached: about:blank
 Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
     (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
     (waiting: false)
 Auction winner:urn:uuid:(randomized)
-Attached to page target: about:blank
-    (title: )
-    (waiting: false)
-Detached: about:blank
-Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
-    (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
-    (waiting: false)
 Attached to page target: https://a.test:8443/inspector-protocol/resources/fledge_join.html
     (title: https://a.test:8443/inspector-protocol/resources/fledge_join.html)
     (waiting: false)
@@ -23,12 +16,12 @@
 Attached to auction_worklet target: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
     (title: FLEDGE bidder worklet for https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php)
     (waiting: false)
-Detached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
-Detached: https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
+Dettached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
+Dettached: https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php
 Attached to auction_worklet target: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
     (title: FLEDGE bidder worklet for https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php)
     (waiting: false)
-Detached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
+Dettached: https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
 Auction winner:urn:uuid:(randomized)
 DONE
 
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
index 90d905a..8441ca2 100644
--- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
+++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-expected.txt
@@ -7,4 +7,5 @@
 Saw process assignment for bidder for host:a.test
 Saw process assignment for seller for host:a.test
 Saw process release for bidder for host:a.test
+Saw process release for seller for host:a.test
 
diff --git a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt
index d587f50..9d9581a 100644
--- a/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt
+++ b/third_party/blink/web_tests/virtual/fledge/http/tests/inspector-protocol/timeline/auction-worklet-network-expected.txt
@@ -43,6 +43,47 @@
 }
 
 
+https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php:
+ResourceSendRequest {
+    requestId : <string>
+    url : https://a.test:8443/inspector-protocol/resources/fledge_bidding_logic.js.php
+}
+ResourceReceiveResponse {
+    encodedDataLength : 229
+    fromCache : false
+    fromServiceWorker : false
+    mimeType : application/javascript
+    requestId : <string>
+    responseTime : <absolute timestamp>
+    statusCode : 200
+    timing : {
+        connectEnd : <relative timestamp>
+        connectStart : <relative timestamp>
+        dnsEnd : <relative timestamp>
+        dnsStart : <relative timestamp>
+        proxyEnd : -1
+        proxyStart : -1
+        pushEnd : 0
+        pushStart : 0
+        receiveHeadersEnd : <relative timestamp>
+        requestTime : <number>
+        sendEnd : <relative timestamp>
+        sendStart : <relative timestamp>
+        sslEnd : <relative timestamp>
+        sslStart : <relative timestamp>
+        workerReady : -1
+        workerStart : -1
+    }
+}
+ResourceFinish {
+    decodedBodyLength : 598
+    didFail : false
+    encodedDataLength : 229
+    finishTime : <number>
+    requestId : <string>
+}
+
+
 https://a.test:8443/inspector-protocol/resources/fledge_decision_logic.js.php:
 ResourceSendRequest {
     requestId : <string>
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
index 36dd775..db26a19f 100644
--- a/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1038,15 +1038,6 @@
     method quadraticCurveTo
     method rect
     method roundRect
-interface PaymentInstruments
-    attribute @@toStringTag
-    method clear
-    method constructor
-    method delete
-    method get
-    method has
-    method keys
-    method set
 interface PaymentRequestEvent : ExtendableEvent
     attribute @@toStringTag
     getter instrumentKey
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
index 22724f1..77dc7b3 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1100,15 +1100,6 @@
 [Worker]     method quadraticCurveTo
 [Worker]     method rect
 [Worker]     method roundRect
-[Worker] interface PaymentInstruments
-[Worker]     attribute @@toStringTag
-[Worker]     method clear
-[Worker]     method constructor
-[Worker]     method delete
-[Worker]     method get
-[Worker]     method has
-[Worker]     method keys
-[Worker]     method set
 [Worker] interface Performance : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onresourcetimingbufferfull
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
index cdb5bdd5..c05bbea 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
@@ -5721,18 +5721,8 @@
     getter sortingCode
     method constructor
     method toJSON
-interface PaymentInstruments
-    attribute @@toStringTag
-    method clear
-    method constructor
-    method delete
-    method get
-    method has
-    method keys
-    method set
 interface PaymentManager
     attribute @@toStringTag
-    getter instruments
     getter userHint
     method constructor
     method enableDelegations
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
index 147e97e2..f68f8f1 100644
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -970,15 +970,6 @@
 [Worker]     method quadraticCurveTo
 [Worker]     method rect
 [Worker]     method roundRect
-[Worker] interface PaymentInstruments
-[Worker]     attribute @@toStringTag
-[Worker]     method clear
-[Worker]     method constructor
-[Worker]     method delete
-[Worker]     method get
-[Worker]     method has
-[Worker]     method keys
-[Worker]     method set
 [Worker] interface Performance : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onresourcetimingbufferfull
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
index a35f479..52baa54 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1217,15 +1217,6 @@
 [Worker]     method quadraticCurveTo
 [Worker]     method rect
 [Worker]     method roundRect
-[Worker] interface PaymentInstruments
-[Worker]     attribute @@toStringTag
-[Worker]     method clear
-[Worker]     method constructor
-[Worker]     method delete
-[Worker]     method get
-[Worker]     method has
-[Worker]     method keys
-[Worker]     method set
 [Worker] interface Performance : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onresourcetimingbufferfull
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
index 56e9f5f..2fe020f 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6485,18 +6485,8 @@
     getter sortingCode
     method constructor
     method toJSON
-interface PaymentInstruments
-    attribute @@toStringTag
-    method clear
-    method constructor
-    method delete
-    method get
-    method has
-    method keys
-    method set
 interface PaymentManager
     attribute @@toStringTag
-    getter instruments
     getter userHint
     method constructor
     method enableDelegations
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
index a9c6a54..04be4fca 100644
--- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
+++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1047,15 +1047,6 @@
 [Worker]     method quadraticCurveTo
 [Worker]     method rect
 [Worker]     method roundRect
-[Worker] interface PaymentInstruments
-[Worker]     attribute @@toStringTag
-[Worker]     method clear
-[Worker]     method constructor
-[Worker]     method delete
-[Worker]     method get
-[Worker]     method has
-[Worker]     method keys
-[Worker]     method set
 [Worker] interface Performance : EventTarget
 [Worker]     attribute @@toStringTag
 [Worker]     getter onresourcetimingbufferfull
diff --git a/tools/clang/scripts/build.py b/tools/clang/scripts/build.py
index 4b3346b..d36da39e 100755
--- a/tools/clang/scripts/build.py
+++ b/tools/clang/scripts/build.py
@@ -604,6 +604,15 @@
 
   global CLANG_REVISION, PACKAGE_VERSION, LLVM_BUILD_DIR
 
+  # TODO(crbug.com/1410101): Remove in next Clang roll.
+  if args.llvm_force_head_revision:
+    global RELEASE_VERSION
+    RELEASE_VERSION = '17'
+    old_lib_dir = os.path.join(LLVM_BUILD_DIR, 'lib', 'clang', '16.0.0')
+    if (os.path.isdir(old_lib_dir)):
+      print('Removing old lib dir: ', old_lib_dir)
+      RmTree(old_lib_dir)
+
   if (args.pgo or args.thinlto) and not args.bootstrap:
     print('--pgo/--thinlto requires --bootstrap')
     return 1
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
index 7cad059..a6a98b75 100755
--- a/tools/clang/scripts/update.py
+++ b/tools/clang/scripts/update.py
@@ -40,6 +40,7 @@
 
 PACKAGE_VERSION = '%s-%s' % (CLANG_REVISION, CLANG_SUB_REVISION)
 RELEASE_VERSION = '16'
+# TODO(crbug.com/1410101): Bump to 17 in next Clang roll.
 
 CDS_URL = os.environ.get('CDS_CLANG_BUCKET_OVERRIDE',
     'https://commondatastorage.googleapis.com/chromium-browser-clang')
@@ -330,6 +331,11 @@
                       help='Verify that clang has the passed-in version.')
   args = parser.parse_args()
 
+  # TODO(crbug.com/1410101): Remove in next Clang roll.
+  if args.llvm_force_head_revision:
+    global RELEASE_VERSION
+    RELEASE_VERSION = '17'
+
   if args.verify_version and args.verify_version != RELEASE_VERSION:
     print('RELEASE_VERSION is %s but --verify-version argument was %s.' % (
         RELEASE_VERSION, args.verify_version))
diff --git a/tools/clang/scripts/upload_revision.py b/tools/clang/scripts/upload_revision.py
index 3c02fb4..4ad0b62 100755
--- a/tools/clang/scripts/upload_revision.py
+++ b/tools/clang/scripts/upload_revision.py
@@ -419,24 +419,37 @@
   Git('checkout', 'origin/main', '-b', branch_name, no_run=args.no_git)
 
   old_clang_version = PatchClangRevision(clang_version)
-  old_rust_version = PatchRustRevision(rust_version)
-  assert (clang_version != old_clang_version
-          or rust_version != old_rust_version), (
-              'Change the sub-revision of Clang or Rust if there is '
-              'no major version change.')
-  # TODO: Turn the nightly dates into git hashes?
-  PatchRustStage0()
-  # TODO: Do this when we block Clang updates without a matching Rust compiler.
-  # PatchRustRemoveFallback()
+  # Avoiding changing Rust versions when rolling Clang until we can fetch
+  # stdlib sources at the same revisionas the compiler, from the
+  # FALLBACK_REVISION in update.py.
+  roll_rust = False
+  if roll_rust:
+    old_rust_version = PatchRustRevision(rust_version)
+    assert (clang_version != old_clang_version
+            or rust_version != old_rust_version), (
+                'Change the sub-revision of Clang or Rust if there is '
+                'no major version change.')
+    # TODO: Turn the nightly dates into git hashes?
+    PatchRustStage0()
+    # TODO: Do this when we block Clang updates without a matching Rust
+    # compiler.
+    # PatchRustRemoveFallback()
+  else:
+    assert (clang_version !=
+            old_clang_version), ('Change the sub-revision of Clang if there is '
+                                 'no major version change.')
 
   clang_change = f'{old_clang_version} : {clang_version}'
   clang_change_log = (
       f'{GOB_LLVM_URL}/+log/'
       f'{old_clang_version.short_git_hash}..{clang_version.short_git_hash}')
 
-  rust_change = (
-      f'{old_rust_version.string_without_dashes(with_sub_revision = True)} '
-      f': {rust_version.string_without_dashes(with_sub_revision = True)}')
+  if roll_rust:
+    rust_change = (
+        f'{old_rust_version.string_without_dashes(with_sub_revision = True)} '
+        f': {rust_version.string_without_dashes(with_sub_revision = True)}')
+  else:
+    rust_change = '[skipping Rust]'
 
   title = f'Roll clang+rust {clang_change} / {rust_change}'
 
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl
index 0ed1c15..80794f4 100644
--- a/tools/mb/mb_config.pyl
+++ b/tools/mb/mb_config.pyl
@@ -460,8 +460,6 @@
       'linux-wpt-fyi-rel': 'release_trybot_minimal_symbols_reclient',
       'linux-wpt-identity-fyi-rel': 'release_bot_minimal_symbols_reclient',
       'linux-wpt-input-fyi-rel': 'release_bot_minimal_symbols_reclient',
-      # TODO(crbug.com/1252626): remove this after the migration.
-      'mac-arm64-on-arm64-rel-reclient': 'mac_arm64_release_bot_reclient',
       'mac-backuprefptr-x64-fyi-rel': 'release_trybot_backuprefptr_x64_reclient',
       'mac-hermetic-upgrade-rel': 'release_bot_reclient',
       'mac-perfetto-rel': 'perfetto_release_bot_reclient',
diff --git a/tools/mb/mb_config_expectations/chromium.fyi.json b/tools/mb/mb_config_expectations/chromium.fyi.json
index ff796db..305c29f 100644
--- a/tools/mb/mb_config_expectations/chromium.fyi.json
+++ b/tools/mb/mb_config_expectations/chromium.fyi.json
@@ -1197,15 +1197,6 @@
       "use_remoteexec": true
     }
   },
-  "mac-arm64-on-arm64-rel-reclient": {
-    "gn_args": {
-      "dcheck_always_on": false,
-      "is_component_build": false,
-      "is_debug": false,
-      "target_cpu": "arm64",
-      "use_remoteexec": true
-    }
-  },
   "mac-backuprefptr-x64-fyi-rel": {
     "gn_args": {
       "dcheck_always_on": true,
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index ec5d455..4ede548 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -44269,9 +44269,9 @@
   <summary>Stages of the first run experience.</summary>
   <int value="0" label="Start First Run"/>
   <int value="1" label="Complete First Run"/>
-  <int value="2" label="Show sync screen"/>
-  <int value="3" label="Close sync screen with sync"/>
-  <int value="4" label="Close sync screen without sync"/>
+  <int value="2" label="Show sync screen (deprecated)"/>
+  <int value="3" label="Close sync screen with sync (deprecated)"/>
+  <int value="4" label="Close sync screen without sync (deprecated)"/>
   <int value="5"
       label="Close sync screen on advance sync settings (deprecated)"/>
   <int value="6" label="Show sign in screen"/>
@@ -53488,6 +53488,14 @@
   <int value="2" label="A tab is dropped at a new index position."/>
 </enum>
 
+<enum name="IOSTabSwitcherDragOrigin">
+  <int value="0"
+      label="The item is from the same collection in the same Chrome window."/>
+  <int value="1" label="The item is from the same Chrome window."/>
+  <int value="2" label="The item is from another Chrome window."/>
+  <int value="3" label="The item is not a Chrome Tab."/>
+</enum>
+
 <enum name="IOSTabSwitcherPageChangeInteraction">
   <int value="0" label="Unknown Interaction"/>
   <int value="1" label="Scroll View Drag"/>
@@ -90511,6 +90519,8 @@
   <int value="401" label="DIAGPKG"/>
   <int value="402" label="PSM1"/>
   <int value="403" label="BGI"/>
+  <int value="404" label="FTPLOC"/>
+  <int value="405" label="ATLOC"/>
 </enum>
 
 <enum name="SBClientDownloadIsSignedBinary">
@@ -94567,6 +94577,7 @@
   <int value="7" label="Error Pin Required"/>
   <int value="8" label="Error Timeout"/>
   <int value="9" label="Error Unknown"/>
+  <int value="10" label="Error Wrong State"/>
 </enum>
 
 <enum name="SimpleCache.EntryCreatedAndStream2Omitted">
@@ -97092,6 +97103,8 @@
   <int value="2" label="Access grant used to allow access"/>
   <int value="3"
       label="Storage access allowed by force-allowed third-party-cookies"/>
+  <int value="4"
+      label="Storage access allowed by the top-level version of the API"/>
 </enum>
 
 <enum name="StoragePartitionRemoverTasks">
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml
index 41c0568..b66a657 100644
--- a/tools/metrics/histograms/metadata/android/histograms.xml
+++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -3521,6 +3521,7 @@
     <variant name="StartSurface" summary="tabs opened from the start surface"/>
     <variant name="Startup" summary="tabs opened during the startup process"/>
     <variant name="TabGroupUI" summary="tabs opened from Tab group UI"/>
+    <variant name="TabSwitcherUI" summary="tabs opened from Tab Switcher UI"/>
     <variant name="TypeUnknown"
         summary="tabs opened from a different case than one's listed"/>
   </token>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml
index e3b7163..3486696c 100644
--- a/tools/metrics/histograms/metadata/ios/histograms.xml
+++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -688,11 +688,21 @@
     <variant name="SyncScreenWithIdentityPicker"
         summary="The screen that asks the user to turn on sync while showing
                  an account picker. Displayed when MICe is disabled and an
-                 account is detected."/>
+                 account is detected.">
+      <obsolete>
+        This metric is obsolete as of M111 as the corresponding screen was
+        removed.
+      </obsolete>
+    </variant>
     <variant name="SyncScreenWithoutIdentityPicker"
         summary="The screen that asks the user to turn on sync while no
                  account picker is present. Displayed when MICe is enabled or
-                 when no account is detected."/>
+                 when no account is detected.">
+      <obsolete>
+        This metric is obsolete as of M111 as the corresponding screen was
+        removed.
+      </obsolete>
+    </variant>
     <variant name="TangibleSyncScreen"
         summary="The tangible sync screen that asks the user to turn on sync."/>
     <variant name="WelcomeScreenWithoutUMACheckbox"
@@ -1988,11 +1998,19 @@
   <owner>gambard@chromium.org</owner>
   <owner>bling-team@google.com</owner>
   <summary>
-    Records tab drag and drop interactions on the tab switcher. An intercation
+    Records tab drag and drop interactions on the tab switcher. An interaction
     is recorded twice (one drag and one drop).
   </summary>
 </histogram>
 
+<histogram name="IOS.TabSwitcher.DragOrigin" enum="IOSTabSwitcherDragOrigin"
+    expires_after="2024-01-22">
+  <owner>ewannpv@chromium.org</owner>
+  <owner>pakzhygitov@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>Records the origin of dropped items in the tab switcher.</summary>
+</histogram>
+
 <histogram name="IOS.TabSwitcher.PageChangeInteraction"
     enum="IOSTabSwitcherPageChangeInteraction" expires_after="2023-07-16">
   <owner>marq@chromium.org</owner>
@@ -2005,6 +2023,25 @@
   </summary>
 </histogram>
 
+<histogram name="IOS.TabSwitcher.PinnedTabs.DragDropTabs"
+    enum="IOSTabSwitcherDragDropTabs" expires_after="2023-11-16">
+  <owner>ewannpv@chromium.org</owner>
+  <owner>pakzhygitov@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>
+    Records tab drag and drop interactions in the pinned tab view. An
+    interaction is recorded twice (one drag and one drop).
+  </summary>
+</histogram>
+
+<histogram name="IOS.TabSwitcher.PinnedTabs.DragOrigin"
+    enum="IOSTabSwitcherDragOrigin" expires_after="2024-01-22">
+  <owner>ewannpv@chromium.org</owner>
+  <owner>pakzhygitov@google.com</owner>
+  <owner>bling-team@google.com</owner>
+  <summary>Records the origin of dropped items in the pinned tab view.</summary>
+</histogram>
+
 <histogram name="IOS.TabSwitcher.TimeSpent" units="ms"
     expires_after="2023-05-14">
   <owner>mrefaat@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/storage/histograms.xml b/tools/metrics/histograms/metadata/storage/histograms.xml
index 3a4bfcab..a9783415 100644
--- a/tools/metrics/histograms/metadata/storage/histograms.xml
+++ b/tools/metrics/histograms/metadata/storage/histograms.xml
@@ -94,6 +94,11 @@
 
 <histogram name="API.StorageAccess.RequestStorageAccessForOrigin"
     enum="RequestStorageResult" expires_after="2023-07-16">
+  <obsolete>
+    Metric collection is being separated from the standard Storage Access API.
+    See API.TopLevelStorageAccess.RequestStorageAccessForOrigin. Note that
+    future re-consolidation of these metrics may be possible.
+  </obsolete>
   <owner>cfredric@chromium.org</owner>
   <owner>mreichhoff@chromium.org</owner>
   <owner>brandm@microsoft.com</owner>
@@ -106,6 +111,31 @@
   </summary>
 </histogram>
 
+<histogram name="API.TopLevelStorageAccess.RequestOutcome"
+    enum="StorageAccessAPIRequestOutcome" expires_after="2023-08-31">
+  <owner>cfredric@chromium.org</owner>
+  <owner>mreichhoff@chromium.org</owner>
+  <summary>
+    Records the outcome of a particular Top-Level Storage Access API permission
+    request.
+
+    Recorded at the time of the request, for every request.
+  </summary>
+</histogram>
+
+<histogram name="API.TopLevelStorageAccess.RequestStorageAccessForOrigin"
+    enum="RequestStorageResult" expires_after="2023-08-31">
+  <owner>cfredric@chromium.org</owner>
+  <owner>mreichhoff@chromium.org</owner>
+  <summary>
+    Records invocations of document.requestStorageAccessForOrigin and reasons
+    the request was approved or rejected. Recorded for every call to the
+    function, regardless of outcome. Note that
+    API.StorageAccess.RequestStorageAccess is similar, but for the other variant
+    of this API.
+  </summary>
+</histogram>
+
 <histogram name="Clipboard.ExtensionContentScriptReadHasUserActivation"
     units="proportion" expires_after="2021-08-09">
   <obsolete>
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 149e1dd0..408ab4a1 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -6,7 +6,7 @@
         },
         "win": {
             "hash": "e51500880a1dfa116d8e0a9c9d5b7c6b26f6e282",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/61eeba8d065b8fc69f9dee9b36bc94d9d6a0293c/trace_processor_shell.exe"
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/facc417319406ebaa00a0b26eca03cbbb03a7e9f/trace_processor_shell.exe"
         },
         "linux_arm": {
             "hash": "6373f26144aad58f230d11d6a91efda5a09c9873",
@@ -21,8 +21,8 @@
             "full_remote_path": "perfetto-luci-artifacts/v31.0/mac-arm64/trace_processor_shell"
         },
         "linux": {
-            "hash": "0a1bc30edd57b6f981224f8764e603048e260337",
-            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/61eeba8d065b8fc69f9dee9b36bc94d9d6a0293c/trace_processor_shell"
+            "hash": "e4667854f5daa74d0c492536ffdbb926938d9a03",
+            "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/82a170d5b41dcb00787fafde01073ad1731ee56b/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/tools/rust/update_rust.py b/tools/rust/update_rust.py
index 71e72e1..c640966b 100755
--- a/tools/rust/update_rust.py
+++ b/tools/rust/update_rust.py
@@ -30,7 +30,7 @@
 # These fields are written by //tools/clang/scripts/upload_revision.py, and
 # should not be changed manually.
 RUST_REVISION_TAG = '2'
-RUST_REVISION = '20230117'
+RUST_REVISION = '20221209'
 RUST_SUB_REVISION = 1
 
 # Trunk on 2022-10-15.
diff --git a/ui/gl/test/gl_surface_test_support.cc b/ui/gl/test/gl_surface_test_support.cc
index 4d273ef..4674dad 100644
--- a/ui/gl/test/gl_surface_test_support.cc
+++ b/ui/gl/test/gl_surface_test_support.cc
@@ -127,16 +127,22 @@
   params.single_process = true;
   ui::OzonePlatform::InitializeForGPU(params);
 #endif
-  if (features::UsePassthroughCommandDecoder()) {
-    auto* display = InitializeOneOffImplementation(
-        GLImplementationParts(gl::ANGLEImplementation::kNull), false);
+  return InitializeOneOffImplementation(
+      GLImplementationParts(kGLImplementationStubGL), false);
+}
 
-    DCHECK_EQ(gl::GetANGLEImplementation(), gl::ANGLEImplementation::kNull);
-    return display;
-  } else {
-    return InitializeOneOffImplementation(
-        GLImplementationParts(kGLImplementationStubGL), false);
-  }
+// static
+GLDisplay* GLSurfaceTestSupport::InitializeOneOffWithNullAngleBindings() {
+#if BUILDFLAG(IS_OZONE)
+  ui::OzonePlatform::InitParams params;
+  params.single_process = true;
+  ui::OzonePlatform::InitializeForGPU(params);
+#endif
+  auto* display = InitializeOneOffImplementation(
+      GLImplementationParts(gl::ANGLEImplementation::kNull), false);
+
+  DCHECK_EQ(gl::GetANGLEImplementation(), gl::ANGLEImplementation::kNull);
+  return display;
 }
 
 // static
diff --git a/ui/gl/test/gl_surface_test_support.h b/ui/gl/test/gl_surface_test_support.h
index 4aaf718..b194c013 100644
--- a/ui/gl/test/gl_surface_test_support.h
+++ b/ui/gl/test/gl_surface_test_support.h
@@ -19,6 +19,8 @@
       bool fallback_to_swiftshader);
   static GLDisplay* InitializeOneOffWithMockBindings();
   static GLDisplay* InitializeOneOffWithStubBindings();
+  static GLDisplay* InitializeOneOffWithNullAngleBindings();
+
   static void ShutdownGL(GLDisplay* display);
 };
 
diff --git a/ui/message_center/public/cpp/notification.cc b/ui/message_center/public/cpp/notification.cc
index 575f514..26adfd5 100644
--- a/ui/message_center/public/cpp/notification.cc
+++ b/ui/message_center/public/cpp/notification.cc
@@ -32,10 +32,9 @@
   return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
 }
 
-// Returns an image created on the current thread that shares the same
-// underlying ImageSkia data as the original image.
-gfx::Image DuplicateImage(const gfx::Image& image) {
-  return image.IsEmpty() ? gfx::Image() : gfx::Image(image.AsImageSkia());
+gfx::Image DeepCopyImage(const gfx::Image& image) {
+  return image.IsEmpty() ? gfx::Image()
+                         : gfx::Image(image.AsImageSkia().DeepCopy());
 }
 
 }  // namespace
@@ -108,14 +107,15 @@
   notification_copy->set_icon(ui::ImageModel::FromImageSkia(
       notification_copy->icon().Rasterize(color_provider)));
   notification_copy->set_image(include_body_image
-                                   ? DuplicateImage(notification_copy->image())
+                                   ? DeepCopyImage(notification_copy->image())
                                    : gfx::Image());
   notification_copy->set_small_image(
-      include_small_image ? notification_copy->small_image() : gfx::Image());
+      include_small_image ? DeepCopyImage(notification_copy->small_image())
+                          : gfx::Image());
   for (size_t i = 0; i < notification_copy->buttons().size(); i++) {
     notification_copy->SetButtonIcon(
         i, include_icon_images
-               ? DuplicateImage(notification_copy->buttons()[i].icon)
+               ? DeepCopyImage(notification_copy->buttons()[i].icon)
                : gfx::Image());
   }
   return notification_copy;
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
index 951c5b7..b43a63d2 100644
--- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -28,9 +28,8 @@
 #include "ui/gfx/overlay_plane_data.h"
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
-#include "ui/gl/gl_image.h"
-#include "ui/gl/gl_image_native_pixmap.h"
 #include "ui/gl/gl_surface.h"
+#include "ui/ozone/public/native_pixmap_gl_binding.h"
 #include "ui/ozone/public/overlay_candidates_ozone.h"
 #include "ui/ozone/public/overlay_manager_ozone.h"
 #include "ui/ozone/public/ozone_platform.h"
@@ -80,9 +79,7 @@
   BufferWrapper();
   ~BufferWrapper();
 
-  scoped_refptr<gfx::NativePixmap> image() const {
-    return image_->GetNativePixmap();
-  }
+  scoped_refptr<gfx::NativePixmap> image() const { return pixmap_; }
   SkSurface* sk_surface() const { return sk_surface_.get(); }
 
   bool Initialize(GrDirectContext* gr_context,
@@ -96,7 +93,8 @@
   gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
   gfx::Size size_;
 
-  scoped_refptr<gl::GLImageNativePixmap> image_;
+  scoped_refptr<gfx::NativePixmap> pixmap_;
+  std::unique_ptr<NativePixmapGLBinding> pixmap_gl_binding_;
   unsigned int gl_tex_ = 0;
   sk_sp<SkSurface> sk_surface_;
 };
@@ -116,20 +114,24 @@
   glGenTextures(1, &gl_tex_);
 
   gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
-  scoped_refptr<gfx::NativePixmap> pixmap =
+
+  pixmap_ = OzonePlatform::GetInstance()
+                ->GetSurfaceFactoryOzone()
+                ->CreateNativePixmap(widget, nullptr, size, format,
+                                     gfx::BufferUsage::SCANOUT);
+
+  pixmap_gl_binding_ =
       OzonePlatform::GetInstance()
           ->GetSurfaceFactoryOzone()
-          ->CreateNativePixmap(widget, nullptr, size, format,
-                               gfx::BufferUsage::SCANOUT);
-  image_ = gl::GLImageNativePixmap::Create(size, format, std::move(pixmap));
-  if (!image_) {
-    LOG(ERROR) << "Failed to create GLImage";
+          ->GetCurrentGLOzone()
+          ->ImportNativePixmap(pixmap_, format, gfx::BufferPlane::DEFAULT, size,
+                               gfx::ColorSpace(), GL_TEXTURE_2D, gl_tex_);
+
+  if (!pixmap_gl_binding_) {
+    LOG(ERROR) << "Failed to create NativePixmapEGLBinding";
     return false;
   }
 
-  glBindTexture(GL_TEXTURE_2D, gl_tex_);
-  image_->BindTexImage(GL_TEXTURE_2D);
-
   widget_ = widget;
   size_ = size;
 
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc
index 13997a4..155f3df 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -23,10 +23,10 @@
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_context.h"
 #include "ui/gl/gl_fence.h"
-#include "ui/gl/gl_image_native_pixmap.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/init/gl_factory.h"
 #include "ui/gl/presenter.h"
+#include "ui/ozone/public/native_pixmap_gl_binding.h"
 #include "ui/ozone/public/overlay_candidates_ozone.h"
 #include "ui/ozone/public/overlay_manager_ozone.h"
 #include "ui/ozone/public/ozone_platform.h"
@@ -80,7 +80,7 @@
 
 scoped_refptr<gfx::NativePixmap> SurfacelessGlRenderer::BufferWrapper::image()
     const {
-  return image_->GetNativePixmap();
+  return pixmap_;
 }
 
 bool SurfacelessGlRenderer::BufferWrapper::Initialize(
@@ -90,20 +90,24 @@
   glGenTextures(1, &gl_tex_);
 
   gfx::BufferFormat format = display::DisplaySnapshot::PrimaryFormat();
-  scoped_refptr<gfx::NativePixmap> pixmap =
-      OzonePlatform::GetInstance()
-          ->GetSurfaceFactoryOzone()
-          ->CreateNativePixmap(widget, nullptr, size, format,
-                               gfx::BufferUsage::SCANOUT);
-  image_ = gl::GLImageNativePixmap::Create(size, format, std::move(pixmap));
-  if (!image_) {
-    LOG(ERROR) << "Failed to create GLImage";
-    return false;
-  }
+  pixmap_ = OzonePlatform::GetInstance()
+                ->GetSurfaceFactoryOzone()
+                ->CreateNativePixmap(widget, nullptr, size, format,
+                                     gfx::BufferUsage::SCANOUT);
 
   glBindFramebufferEXT(GL_FRAMEBUFFER, gl_fb_);
-  glBindTexture(GL_TEXTURE_2D, gl_tex_);
-  image_->BindTexImage(GL_TEXTURE_2D);
+
+  pixmap_gl_binding_ =
+      OzonePlatform::GetInstance()
+          ->GetSurfaceFactoryOzone()
+          ->GetCurrentGLOzone()
+          ->ImportNativePixmap(pixmap_, format, gfx::BufferPlane::DEFAULT, size,
+                               gfx::ColorSpace(), GL_TEXTURE_2D, gl_tex_);
+
+  if (!pixmap_gl_binding_) {
+    LOG(ERROR) << "Failed to create NativePixmapEGLBinding";
+    return false;
+  }
 
   glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
                             gl_tex_, 0);
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.h b/ui/ozone/demo/surfaceless_gl_renderer.h
index 5342f57..0eed7962 100644
--- a/ui/ozone/demo/surfaceless_gl_renderer.h
+++ b/ui/ozone/demo/surfaceless_gl_renderer.h
@@ -12,12 +12,12 @@
 #include "ui/ozone/demo/gl_renderer.h"
 
 namespace gl {
-class GLImageNativePixmap;
 class Presenter;
 }
 
 namespace ui {
 class OverlayCandidatesOzone;
+class NativePixmapGLBinding;
 class PlatformWindowSurface;
 
 static const int kMaxLayers = 8;
@@ -59,7 +59,8 @@
     gfx::AcceleratedWidget widget_ = gfx::kNullAcceleratedWidget;
     gfx::Size size_;
 
-    scoped_refptr<gl::GLImageNativePixmap> image_;
+    scoped_refptr<gfx::NativePixmap> pixmap_;
+    std::unique_ptr<NativePixmapGLBinding> pixmap_gl_binding_;
     unsigned int gl_fb_ = 0;
     unsigned int gl_tex_ = 0;
   };
diff --git a/ui/ozone/platform/flatland/flatland_connection.cc b/ui/ozone/platform/flatland/flatland_connection.cc
index f943feb..d15dbcb 100644
--- a/ui/ozone/platform/flatland/flatland_connection.cc
+++ b/ui/ozone/platform/flatland/flatland_connection.cc
@@ -15,7 +15,8 @@
 
 namespace ui {
 
-FlatlandConnection::FlatlandConnection(const std::string& debug_name) {
+FlatlandConnection::FlatlandConnection(base::StringPiece debug_name,
+                                       OnErrorCallback error_callback) {
   zx_status_t status =
       base::ComponentContextForProcess()
           ->svc()
@@ -23,9 +24,14 @@
   if (status != ZX_OK) {
     ZX_LOG(FATAL, status) << "Failed to connect to Flatland";
   }
-  flatland_->SetDebugName(debug_name);
+
+  flatland_->SetDebugName(static_cast<std::string>(debug_name));
+  DCHECK(error_callback);
   flatland_.events().OnError =
-      fit::bind_member(this, &FlatlandConnection::OnError);
+      [callback = std::move(error_callback)](
+          fuchsia::ui::composition::FlatlandError error) mutable {
+        std::move(callback).Run(std::move(error));
+      };
   flatland_.events().OnFramePresented =
       fit::bind_member(this, &FlatlandConnection::OnFramePresented);
   flatland_.events().OnNextFrameBegin =
@@ -63,12 +69,6 @@
   presented_callbacks_.push(std::move(callback));
 }
 
-void FlatlandConnection::OnError(
-    fuchsia::ui::composition::FlatlandError error) {
-  LOG(ERROR) << "Flatland error: " << static_cast<int>(error);
-  // TODO(fxbug.dev/93998): Send error signal to the owners of this class.
-}
-
 void FlatlandConnection::OnNextFrameBegin(
     fuchsia::ui::composition::OnNextFrameBeginValues values) {
   present_credits_ += values.additional_present_credits();
diff --git a/ui/ozone/platform/flatland/flatland_connection.h b/ui/ozone/platform/flatland/flatland_connection.h
index af011f4..46d52815 100644
--- a/ui/ozone/platform/flatland/flatland_connection.h
+++ b/ui/ozone/platform/flatland/flatland_connection.h
@@ -11,6 +11,7 @@
 
 #include "base/containers/queue.h"
 #include "base/functional/callback.h"
+#include "base/strings/string_piece.h"
 
 namespace ui {
 
@@ -20,7 +21,13 @@
 // should not call Flatland::Present on their own.
 class FlatlandConnection final {
  public:
-  explicit FlatlandConnection(const std::string& debug_name);
+  using OnFramePresentedCallback =
+      base::OnceCallback<void(zx_time_t actual_presentation_time)>;
+  using OnErrorCallback =
+      base::OnceCallback<void(fuchsia::ui::composition::FlatlandError error)>;
+
+  explicit FlatlandConnection(base::StringPiece debug_name,
+                              OnErrorCallback callback);
   ~FlatlandConnection();
 
   FlatlandConnection(const FlatlandConnection&) = delete;
@@ -28,24 +35,27 @@
 
   fuchsia::ui::composition::Flatland* flatland() { return flatland_.get(); }
 
+  // Returns an unused, non-zero transform identifier.
   fuchsia::ui::composition::TransformId NextTransformId() {
     return {++next_transform_id_};
   }
 
+  // Returns an unused, non-zero content identifier.
   fuchsia::ui::composition::ContentId NextContentId() {
     return {++next_content_id_};
   }
 
-  using OnFramePresentedCallback =
-      base::OnceCallback<void(zx_time_t actual_presentation_time)>;
   void Present();
   void Present(fuchsia::ui::composition::PresentArgs present_args,
                OnFramePresentedCallback callback);
 
  private:
-  void OnError(fuchsia::ui::composition::FlatlandError error);
+  // Method that is listening to Flatland's OnNextFrameBegin() callback.
+  // Returns one or more present credits.
   void OnNextFrameBegin(
       fuchsia::ui::composition::OnNextFrameBeginValues values);
+  // Method that is listening to Flatland's OnFramePresented() callback.
+  // Returns feedback on the prior frame presentation.
   void OnFramePresented(fuchsia::scenic::scheduling::FramePresentedInfo info);
 
   fuchsia::ui::composition::FlatlandPtr flatland_;
@@ -64,8 +74,17 @@
     fuchsia::ui::composition::PresentArgs present_args;
     OnFramePresentedCallback callback;
   };
+
+  // Keeps track of pending Presents that cannot be committed in the situation
+  // when we don't have enough present credits.
   base::queue<PendingPresent> pending_presents_;
+  // Keeps track of release fences for the previous frame, indicating when it is
+  // safe to reuse the resources. Ozone defines and sends release fences for
+  // the current frame, whereas Flatland expects the release fences for the
+  // previous frame resources.
   std::vector<zx::event> previous_present_release_fences_;
+  // Keeps track of Presents that are committed, but Flatland hasn't indicated
+  // that have taken effect by calling OnFramePresented().
   base::queue<OnFramePresentedCallback> presented_callbacks_;
 };
 
diff --git a/ui/ozone/platform/flatland/flatland_connection_unittest.cc b/ui/ozone/platform/flatland/flatland_connection_unittest.cc
index 1e24760..7236c0a 100644
--- a/ui/ozone/platform/flatland/flatland_connection_unittest.cc
+++ b/ui/ozone/platform/flatland/flatland_connection_unittest.cc
@@ -48,7 +48,9 @@
   // Create the FlatlandConnection but don't pump the loop.  No FIDL calls are
   // completed yet.
   const std::string debug_name = GetCurrentTestName();
-  FlatlandConnection flatland_connection(debug_name);
+  FlatlandConnection flatland_connection(
+      debug_name, base::BindLambdaForTesting(
+                      [](fuchsia::ui::composition::FlatlandError) { FAIL(); }));
   EXPECT_EQ(fake_flatland_.debug_name(), "");
 
   // Ensure the debug name is set.
@@ -66,7 +68,10 @@
 
   // Create the FlatlandConnection but don't pump the loop.  No FIDL calls are
   // completed yet.
-  FlatlandConnection flatland_connection(GetCurrentTestName());
+  FlatlandConnection flatland_connection(
+      GetCurrentTestName(),
+      base::BindLambdaForTesting(
+          [](fuchsia::ui::composition::FlatlandError) { FAIL(); }));
   EXPECT_EQ(presents_called, 0u);
 
   flatland_connection.Present();
@@ -84,7 +89,10 @@
 
   // Create the FlatlandConnection but don't pump the loop.  No FIDL calls are
   // completed yet.
-  FlatlandConnection flatland_connection(GetCurrentTestName());
+  FlatlandConnection flatland_connection(
+      GetCurrentTestName(),
+      base::BindLambdaForTesting(
+          [](fuchsia::ui::composition::FlatlandError) { FAIL(); }));
   EXPECT_EQ(presents_called, 0u);
 
   flatland_connection.Present();
@@ -149,7 +157,10 @@
 
   // Create the FlatlandConnection but don't pump the loop.  No FIDL calls are
   // completed yet.
-  FlatlandConnection flatland_connection(GetCurrentTestName());
+  FlatlandConnection flatland_connection(
+      GetCurrentTestName(),
+      base::BindLambdaForTesting(
+          [](fuchsia::ui::composition::FlatlandError) { FAIL(); }));
   EXPECT_EQ(presents_called, 0u);
 
   zx::event first_release_fence;
diff --git a/ui/ozone/platform/flatland/flatland_surface.cc b/ui/ozone/platform/flatland/flatland_surface.cc
index 86c750d..d1f1dce 100644
--- a/ui/ozone/platform/flatland/flatland_surface.cc
+++ b/ui/ozone/platform/flatland/flatland_surface.cc
@@ -11,6 +11,7 @@
 #include "base/check_op.h"
 #include "base/fuchsia/fuchsia_logging.h"
 #include "base/fuchsia/process_context.h"
+#include "base/functional/bind.h"
 #include "base/trace_event/trace_event.h"
 #include "ui/gfx/geometry/rect_conversions.h"
 #include "ui/gfx/geometry/rect_f.h"
@@ -140,7 +141,9 @@
 FlatlandSurface::FlatlandSurface(
     FlatlandSurfaceFactory* flatland_surface_factory,
     gfx::AcceleratedWidget window)
-    : flatland_("Chromium FlatlandSurface"),
+    : flatland_("Chromium FlatlandSurface",
+                base::BindOnce(&FlatlandSurface::OnFlatlandError,
+                               base::Unretained(this))),
       flatland_surface_factory_(flatland_surface_factory),
       window_(window) {
   // Create Flatland Allocator connection.
@@ -430,6 +433,15 @@
   child_transforms_.clear();
 }
 
+void FlatlandSurface::OnFlatlandError(
+    fuchsia::ui::composition::FlatlandError error) {
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+  LOG(ERROR) << "Flatland error: " << static_cast<int>(error);
+  base::LogFidlErrorAndExitProcess(FROM_HERE,
+                                   "fuchsia::ui::composition::Flatland");
+}
+
 FlatlandSurface::PresentedFrame::PresentedFrame(
     fuchsia::ui::composition::ContentId image_id,
     scoped_refptr<gfx::NativePixmap> primary_plane,
diff --git a/ui/ozone/platform/flatland/flatland_surface.h b/ui/ozone/platform/flatland/flatland_surface.h
index 75b9cef3..04a77263 100644
--- a/ui/ozone/platform/flatland/flatland_surface.h
+++ b/ui/ozone/platform/flatland/flatland_surface.h
@@ -60,11 +60,6 @@
   template <typename T>
   friend class FlatlandSurfaceTestBase;
 
-  struct PresentationState {
-    base::TimeTicks presentation_time;
-    base::TimeDelta interval;
-  };
-
   struct PresentedFrame {
     PresentedFrame(fuchsia::ui::composition::ContentId image_id,
                    scoped_refptr<gfx::NativePixmap> primary_plane,
@@ -116,6 +111,8 @@
 
   void ClearScene();
 
+  void OnFlatlandError(fuchsia::ui::composition::FlatlandError error);
+
   fuchsia::ui::composition::AllocatorPtr flatland_allocator_;
   FlatlandConnection flatland_;
 
diff --git a/ui/ozone/platform/flatland/flatland_window.cc b/ui/ozone/platform/flatland/flatland_window.cc
index 0ab2da5..54d86d3 100644
--- a/ui/ozone/platform/flatland/flatland_window.cc
+++ b/ui/ozone/platform/flatland/flatland_window.cc
@@ -54,7 +54,9 @@
       window_id_(manager_->AddWindow(this)),
       view_ref_(std::move(properties.view_ref_pair.view_ref)),
       view_controller_(std::move(properties.view_controller)),
-      flatland_("Chromium FlatlandWindow"),
+      flatland_("Chromium FlatlandWindow",
+                base::BindOnce(&FlatlandWindow::OnFlatlandError,
+                               base::Unretained(this))),
       bounds_(
           platform_window_delegate->ConvertRectToPixels(properties.bounds)) {
   if (view_controller_) {
@@ -435,9 +437,15 @@
   platform_window_delegate_->DispatchEvent(event);
 }
 
+void FlatlandWindow::OnFlatlandError(
+    fuchsia::ui::composition::FlatlandError error) {
+  LOG(ERROR) << "Flatland error: " << static_cast<int>(error);
+  platform_window_delegate_->OnClosed();
+}
+
 void FlatlandWindow::OnViewControllerDisconnected(zx_status_t status) {
   view_controller_ = nullptr;
-  platform_window_delegate_->OnCloseRequest();
+  platform_window_delegate_->OnClosed();
 }
 
 }  // namespace ui
diff --git a/ui/ozone/platform/flatland/flatland_window.h b/ui/ozone/platform/flatland/flatland_window.h
index 880a170..acb7cc1 100644
--- a/ui/ozone/platform/flatland/flatland_window.h
+++ b/ui/ozone/platform/flatland/flatland_window.h
@@ -113,6 +113,7 @@
 
   void UpdateSize();
 
+  void OnFlatlandError(fuchsia::ui::composition::FlatlandError error);
   void OnViewControllerDisconnected(zx_status_t status);
 
   FlatlandWindowManager* const manager_;
diff --git a/ui/ozone/platform/wayland/host/wayland_subsurface.h b/ui/ozone/platform/wayland/host/wayland_subsurface.h
index d830615..9bc0d10 100644
--- a/ui/ozone/platform/wayland/host/wayland_subsurface.h
+++ b/ui/ozone/platform/wayland/host/wayland_subsurface.h
@@ -71,7 +71,7 @@
   const raw_ptr<WaylandConnection> connection_;
   // |parent_| refers to the WaylandWindow whose wl_surface is the parent to
   // this subsurface.
-  const raw_ptr<WaylandWindow> parent_;
+  const raw_ptr<WaylandWindow, DanglingUntriaged> parent_;
 };
 
 }  // namespace ui
diff --git a/ui/views/corewm/tooltip_lacros.h b/ui/views/corewm/tooltip_lacros.h
index fb42ade..d9a29e2 100644
--- a/ui/views/corewm/tooltip_lacros.h
+++ b/ui/views/corewm/tooltip_lacros.h
@@ -71,7 +71,7 @@
   // True if tooltip is visible.
   bool is_visible_ = false;
 
-  raw_ptr<aura::Window> parent_window_ = nullptr;
+  raw_ptr<aura::Window, DanglingUntriaged> parent_window_ = nullptr;
   std::u16string text_;
   gfx::Point position_;
   TooltipTrigger trigger_;
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
index 08302a6..62ea431 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/ExternalNavigationDelegateImpl.java
@@ -53,9 +53,9 @@
     }
 
     @Override
-    public boolean shouldAvoidDisambiguationDialog(Intent intent) {
+    public boolean shouldAvoidDisambiguationDialog(GURL intentDataUrl) {
         // Don't show the disambiguation dialog if WebLayer can handle the intent.
-        return UrlUtilities.isAcceptedScheme(intent.toUri(0));
+        return UrlUtilities.isAcceptedScheme(intentDataUrl);
     }
 
     @Override